Commits

Max Noel committed 952e1dd

* autoincrement_int keys no longer overwrite data when items with explicitly-set hash_keys were manually put in the DB.

Comments (0)

Files changed (1)

dynamodb_mapper/model.py

     table, new objects in your table will have an auto-incrementing primary
     key.
 
-    Note, however, that attempts to insert items with explicit, user-set values
-    for the hash key will fail.
+    Note that you can still insert items with explicit values for your primary
+    key -- the autoincrementing scheme is only used for objects with unset
+    hash_keys (or to be more precise, left set to the default value of 0).
 
     Auto-incrementing int keys are implemented by storing a special "magic"
     item in the table with the following properties:
                 # Conditional write: we're overwriting iff the value
                 # hasn't changed.
                 max_hash_item.put({"__max_hash_key__": max_hash_key})
+                # We just reserved that value for the hash key
+                item[item.hash_key_name] = max_hash_key + 1
+                # If despite our checks someone manually inserted an item at
+                # that primary key, we'll retry with the next available value.
+                item.put({item.hash_key_name: False})
                 break
             except DynamoDBResponseError as e:
                 if e.error_code != "ConditionalCheckFailedException":
                     raise
                 # The max key has changed (concurrent write): retry.
 
-        # We just reserved that value for the hash key
-        item[item.hash_key_name] = max_hash_key + 1
-        item.put()
-
     def save(self, allow_overwrite=True):
         """Save the object to the database.
 
         This method may be used both to insert a new object in the DB, or to
-        update an existing one (iff allow_overwrite == True -- otherwise,
-        the operation fails with OverwriteError).
+        update an existing one (iff allow_overwrite == True).
+
+        :param allow_overwrite: If False, the method will only succeed if this
+            object's primary keys don't exist in the database (otherwise,
+            :class:`OverwriteError` is raised).
         """
         cls = type(self)
         schema = cls.__schema__