def hset(self, key, field, value): result = 0 if self._db.get(KEY_CODEC.encode_hash_field(key, field)) is None: result = 1 hash_length = int(self._db.get(KEY_CODEC.encode_hash(key), '0')) with self._db.write_batch() as batch: batch.put(KEY_CODEC.encode_hash(key), bytes(hash_length + 1)) batch.put(KEY_CODEC.encode_hash_field(key, field), value) return result
def hsetnx(self, key, field, value): # only set if not set before if self._db.get(KEY_CODEC.encode_hash_field(key, field)) is None: hash_length = int(self._db.get(KEY_CODEC.encode_hash(key), '0')) with self._db.write_batch() as batch: batch.put(KEY_CODEC.encode_hash(key), bytes(hash_length + 1)) batch.put(KEY_CODEC.encode_hash_field(key, field), value) return 1 else: return 0
def hvals(self, key): result = [] if self._db.get(KEY_CODEC.encode_hash(key)) is not None: for _, db_value in self._get_db_iterator( KEY_CODEC.get_min_hash_field(key)): result.append(db_value) return result
def hdel(self, key, *fields): result = 0 key_id, hash_length = self._get_hash_key_id_and_length(key) # safe guard if hash_length == 0: return result batch = self._db.write_batch() for field in fields: if self._db.get(KEY_CODEC.encode_hash_field(key_id, field)) is not None: result += 1 hash_length -= 1 batch.delete(KEY_CODEC.encode_hash_field(key_id, field)) if hash_length == 0: # remove empty hashes from keyspace self.delete(key) else: batch.put( KEY_CODEC.encode_hash(key), KEY_CODEC.encode_key_id_and_length(key, key_id, hash_length)) batch.write() return result
def _delete_db_hash(self, key): # there are two sets of db keys for hashes: # * hash # * hash fields with self._db.write_batch() as batch: batch.delete(KEY_CODEC.encode_hash(key)) for db_key, _ in self._get_db_iterator( KEY_CODEC.get_min_hash_field(key)): batch.delete(db_key)
def hgetall(self, key): result = [] if self._db.get(KEY_CODEC.encode_hash(key)) is not None: for db_key, db_value in self._get_db_iterator( KEY_CODEC.get_min_hash_field(key)): _, length, field_key = KEY_CODEC.decode_key(db_key) field = field_key[length:] result.append(field) result.append(db_value) return result
def type(self, key): if self._db.get(KEY_CODEC.encode_string(key)) is not None: return 'string' if self._db.get(KEY_CODEC.encode_set(key)) is not None: return 'set' if self._db.get(KEY_CODEC.encode_hash(key)) is not None: return 'hash' if self._db.get(KEY_CODEC.encode_zset(key)) is not None: return 'zset' return 'none'
def _delete_db_hash(self, key): # there are two sets of db keys for hashes: # * hash # * hash fields # # currently the `hash` key is immediately deleted and the other keys # will be collected by gc.KeyGarbageCollector() key_id, _ = self._get_hash_key_id_and_length(key) with self._db.write_batch() as batch: batch.delete(KEY_CODEC.encode_hash(key)) batch.put(KEY_CODEC.encode_deleted_hash(key_id), bytes(''))
def hset(self, key, field, value): result = 0 key_id, hash_length = self._get_hash_key_id_and_length(key) if self._db.get(KEY_CODEC.encode_hash_field(key_id, field)) is None: result = 1 with self._db.write_batch() as batch: batch.put( KEY_CODEC.encode_hash(key), KEY_CODEC.encode_key_id_and_length(key, key_id, hash_length + result)) batch.put(KEY_CODEC.encode_hash_field(key_id, field), value) return result
def hsetnx(self, key, field, value): key_id, hash_length = self._get_hash_key_id_and_length(key) # only set if not set before if self._db.get(KEY_CODEC.encode_hash_field(key_id, field)) is None: with self._db.write_batch() as batch: batch.put( KEY_CODEC.encode_hash(key), KEY_CODEC.encode_key_id_and_length(key, key_id, hash_length + 1)) batch.put(KEY_CODEC.encode_hash_field(key_id, field), value) return 1 else: return 0
def rename(self, old_name, new_name): if self.exists(old_name): if old_name == new_name: return # replace the key that holds the key ID and don't touch the rest key_type = self.type(old_name) if key_type == 'zset': old_db_key = KEY_CODEC.encode_zset(old_name) new_db_key = KEY_CODEC.encode_zset(new_name) elif key_type == 'hash': old_db_key = KEY_CODEC.encode_hash(old_name) new_db_key = KEY_CODEC.encode_hash(new_name) elif key_type == 'set': old_db_key = KEY_CODEC.encode_set(old_name) new_db_key = KEY_CODEC.encode_set(new_name) elif key_type == 'string': old_db_key = KEY_CODEC.encode_string(old_name) new_db_key = KEY_CODEC.encode_string(new_name) else: raise DredisError("invalid key type") self._replace_db_key(new_db_key, old_db_key) else: raise NoKeyError()
def delete(self, *keys): result = 0 for key in keys: if self._db.get(KEY_CODEC.encode_string(key)) is not None: self._delete_db_string(key) result += 1 elif self._db.get(KEY_CODEC.encode_set(key)) is not None: self._delete_db_set(key) result += 1 elif self._db.get(KEY_CODEC.encode_hash(key)) is not None: self._delete_db_hash(key) result += 1 elif self._db.get(KEY_CODEC.encode_zset(key)) is not None: self._delete_db_zset(key) result += 1 return result
def hlen(self, key): result = self._db.get(KEY_CODEC.encode_hash(key)) if result is None: return 0 else: return int(result)
def _get_hash_key_id_and_length(self, key): db_value = self._db.get(KEY_CODEC.encode_hash(key)) return KEY_CODEC.decode_key_id_and_length(key, db_value)