simulate database‐style features like transactions and commits by implementing a transaction mechanism within your `InMemoryDatabase` class - unix1998/technical_notes GitHub Wiki

simulate database-style features like transactions and commits by implementing a transaction mechanism within your InMemoryDatabase class.

class InMemoryDatabase:
    def __init__(self):
        self.db = {}
        self.transaction_db = None  # Temporary storage for transactions

    def set(self, key, value):
        if not isinstance(value, int):
            raise ValueError("Value must be an integer.")
        if self.transaction_db is not None:
            self.transaction_db[key] = value
        else:
            self.db[key] = value

    def get(self, key):
        if self.transaction_db is not None and key in self.transaction_db:
            return self.transaction_db.get(key, "Key not found.")
        return self.db.get(key, "Key not found.")

    def delete(self, key):
        if self.transaction_db is not None:
            if key in self.transaction_db:
                del self.transaction_db[key]
            else:
                return "Key not found."
        else:
            if key in self.db:
                del self.db[key]
            else:
                return "Key not found."

    def size(self):
        if self.transaction_db is not None:
            return len(self.transaction_db)
        return len(self.db)

    def begin_transaction(self):
        if self.transaction_db is None:
            self.transaction_db = self.db.copy()
        else:
            raise Exception("Transaction already in progress.")

    def commit_transaction(self):
        if self.transaction_db is not None:
            self.db = self.transaction_db
            self.transaction_db = None
        else:
            raise Exception("No transaction in progress.")

    def rollback_transaction(self):
        if self.transaction_db is not None:
            self.transaction_db = None
        else:
            raise Exception("No transaction in progress.")

# Example usage
db = InMemoryDatabase()

# Insert key-value pairs in a loop
for i in range(1, 1001):
    key = f"key{i:04d}"
    value = 1000 + i
    db.set(key, value)

# Check the size of the database
print(db.size())  # Output: 1000

# Retrieve some values
print(db.get("key0001"))  # Output: 1001
print(db.get("key1000"))  # Output: 2000
print(db.get("key1001"))  # Output: Key not found.

# Begin a transaction
db.begin_transaction()

# Update some values within the transaction
db.set("key0001", 9999)
db.set("key1000", 8888)

# Retrieve values within the transaction
print(db.get("key0001"))  # Output: 9999
print(db.get("key1000"))  # Output: 8888

# Rollback the transaction
db.rollback_transaction()

# Retrieve values after rollback
print(db.get("key0001"))  # Output: 1001
print(db.get("key1000"))  # Output: 2000

# Begin another transaction
db.begin_transaction()

# Update some values within the transaction
db.set("key0001", 9999)
db.set("key1000", 8888)

# Commit the transaction
db.commit_transaction()

# Retrieve values after commit
print(db.get("key0001"))  # Output: 9999
print(db.get("key1000"))  # Output: 8888

# Print first 5 keys and values to verify
for i in range(1, 6):
    key = f"key{i:04d}"
    print(f"{key}: {db.get(key)}")

# Print last 5 keys and values to verify
for i in range(996, 1001):
    key = f"key{i:04d}"
    print(f"{key}: {db.get(key)}")

In this version:

  • transaction_db is a temporary storage dictionary used during transactions.
  • begin_transaction initializes a transaction by copying the current state of db to transaction_db.
  • commit_transaction applies the changes in transaction_db to db and clears transaction_db.
  • rollback_transaction discards the changes in transaction_db and clears transaction_db.

During a transaction, any set, get, or delete operations will affect transaction_db instead of db. Once the transaction is committed or rolled back, the changes are either applied to db or discarded, respectively.