From 222b3c1eaaad00ce9face0868ec69ce96a27cbdb Mon Sep 17 00:00:00 2001
From: "Brian S. O'Neill" <bronee@gmail.com>
Date: Wed, 1 Aug 2007 03:22:51 +0000
Subject: JDBCRepository allows non-null column to be @Nullable if also
 @Independent. Fixed bug in generating SQL with nullable primary key
 properties.

---
 .../carbonado/repo/jdbc/JDBCStorableGenerator.java | 61 ++++++++++++++++------
 .../repo/jdbc/JDBCStorableIntrospector.java        | 13 +++--
 2 files changed, 55 insertions(+), 19 deletions(-)

(limited to 'src/main')

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 0e5b74e..f86ab27 100644
--- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java
+++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableGenerator.java
@@ -79,8 +79,9 @@ class JDBCStorableGenerator<S extends Storable> {
 
     // Modes for automatic versioning when setting PreparedStatement values.
     private static final int NORMAL = 0;
-    private static final int INITIAL_VERSION = 1;
-    private static final int INCREMENT_VERSION = 2;
+    private static final int NOT_NULL = 1;
+    private static final int INITIAL_VERSION = 2;
+    private static final int INCREMENT_VERSION = 3;
 
     private static final Map<Object, Class<? extends Storable>> cCache;
 
@@ -837,9 +838,9 @@ class JDBCStorableGenerator<S extends Storable> {
                 }
                 b.loadConstant(property.getColumnName());
                 CodeBuilderUtil.callStringBuilderAppendString(b);
-                if (property.isNullable()) {
-                    // TODO: Support null primary key or version property. Is this possible?
-                    throw new UnsupportedOperationException();
+                if (false && property.isNullable()) {
+                    // FIXME: Support null primary key or version property.
+                    throw new UnsupportedOperationException(property.toString());
                 } else {
                     b.loadConstant("=?");
                     CodeBuilderUtil.callStringBuilderAppendString(b);
@@ -931,9 +932,9 @@ class JDBCStorableGenerator<S extends Storable> {
             // statement.
 
             for (JDBCStorableProperty<S> property : whereProperties) {
-                if (property.isNullable()) {
-                    // TODO: Support null primary key or version property. Is this possible?
-                    throw new UnsupportedOperationException();
+                if (false && property.isNullable()) {
+                    // FIXME: Support null primary key or version property.
+                    throw new UnsupportedOperationException(property.toString());
                 } else {
                     b.loadLocal(psVar);
                     b.loadLocal(indexVar);
@@ -1349,32 +1350,60 @@ class JDBCStorableGenerator<S extends Storable> {
         Label tryAfterPs = b.createLabel().setLocation();
 
         // Now set where clause parameters.
+        Label nextProperty = null;
+        LocalVariable paramIndexVar = null;
         ordinal = 0;
         for (JDBCStorableProperty property : properties) {
             if (!property.isSelectable()) {
                 continue;
             }
 
-            Label nextProperty = b.createLabel();
+            if (paramIndexVar == null) {
+                ordinal++;
+            } else {
+                b.integerIncrement(paramIndexVar, 1);
+            }
+
+            if (nextProperty != null) {
+                nextProperty.setLocation();
+                nextProperty = null;
+            }
+
+            nextProperty = b.createLabel();
 
             final TypeDesc propertyType = TypeDesc.forClass(property.getType());
 
-            if (!property.isNullable()) {
-                b.loadLocal(psVar);
-                b.loadConstant(++ordinal);
-            } else {
+            if (property.isNullable()) {
                 // Nullable properties are dynamically added to where clause,
                 // and are at the end of the prepared statement. If value is
                 // null, then skip to the next property, since the statement
                 // was appended earlier with "IS NULL".
+
+                // Cannot use constant parameter index anymore.
+                if (paramIndexVar == null) {
+                    paramIndexVar = b.createLocalVariable(null, TypeDesc.INT);
+                    b.loadConstant(ordinal);
+                    b.storeLocal(paramIndexVar);
+                }
+
                 b.loadThis();
                 b.loadField(superType, property.getName(), propertyType);
                 b.ifNullBranch(nextProperty, true);
             }
 
-            setPreparedStatementValue(b, property, NORMAL, null, instanceVar, null, null);
+            b.loadLocal(psVar);
+            if (paramIndexVar == null) {
+                b.loadConstant(ordinal);
+            } else {
+                b.loadLocal(paramIndexVar);
+            }
+
+            setPreparedStatementValue(b, property, NOT_NULL, null, instanceVar, null, null);
+        }
 
+        if (nextProperty != null) {
             nextProperty.setLocation();
+            nextProperty = null;
         }
 
         return tryAfterPs;
@@ -1392,7 +1421,7 @@ class JDBCStorableGenerator<S extends Storable> {
      * the original lob. An update statement needs to be issued after the load
      * to insert/update the large value.
      *
-     * @param mode one of NORMAL, INITIAL_VERSION or INCREMENT_VERSION
+     * @param mode one of NORMAL, NOT_NULL, INITIAL_VERSION or INCREMENT_VERSION
      * @param instanceVar when null, assume properties are contained in
      * "this". Otherwise, invoke property access methods on storable referenced
      * in var.
@@ -1464,7 +1493,7 @@ class JDBCStorableGenerator<S extends Storable> {
             CodeBuilderUtil.initialVersion(b, fromType, 1);
         } else if (mode == INCREMENT_VERSION) {
             CodeBuilderUtil.incrementVersion(b, fromType);
-        } else if (!fromType.isPrimitive()) {
+        } else if (!fromType.isPrimitive() && mode != NOT_NULL) {
             // Handle case where property value is null.
             b.dup();
             Label notNull = b.createLabel();
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 4805ee2..bc0c29a 100644
--- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java
+++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java
@@ -325,7 +325,7 @@ public class JDBCStorableIntrospector extends StorableIntrospector {
                                  "\" must have a Nullable annotation");
                         }
                     } else {
-                        if (mainProperty.isNullable()) {
+                        if (mainProperty.isNullable() && !mainProperty.isIndependent()) {
                             errorMessages.add
                                 ("Property \"" + mainProperty.getName() +
                                  "\" must not have a Nullable annotation");
@@ -498,11 +498,18 @@ public class JDBCStorableIntrospector extends StorableIntrospector {
                 do {
                     String columnName = rs.getString("COLUMN_NAME");
                     String propertyName = columnToProperty.remove(columnName);
+
+                    if (propertyName == null) {
+                        errorMessages.add
+                            ("Column \"" + columnName + "\" must be part of primary key");
+                        continue;
+                    }
+
                     StorableProperty mainProperty = mainProperties.get(propertyName);
 
                     if (!mainProperty.isPrimaryKeyMember()) {
                         errorMessages.add
-                            ("Property \"" + propertyName + "\" must be a primary key member");
+                            ("Property \"" + propertyName + "\" must be part of primary key");
                     }
                 } while (rs.next());
             } finally {
@@ -515,7 +522,7 @@ public class JDBCStorableIntrospector extends StorableIntrospector {
 
                 if (mainProperty.isPrimaryKeyMember()) {
                     errorMessages.add
-                        ("Property \"" + propertyName + "\" cannot be a primary key member");
+                        ("Property \"" + propertyName + "\" cannot be part of primary key");
                 }
             }
         }
-- 
cgit v1.2.3