Add redisql/README.md
This commit is contained in:
157
redisql/README.md
Normal file
157
redisql/README.md
Normal file
@@ -0,0 +1,157 @@
|
||||
```python
|
||||
#
|
||||
import sqlite3
|
||||
import time
|
||||
|
||||
class SQLiteRedis:
|
||||
def __init__(self, db_name=':memory:'):
|
||||
self.conn = sqlite3.connect(db_name)
|
||||
self.cur = self.conn.cursor()
|
||||
self._create_tables()
|
||||
|
||||
def _create_tables(self):
|
||||
self.cur.execute('''CREATE TABLE IF NOT EXISTS kv_store
|
||||
(key TEXT PRIMARY KEY, value TEXT)''')
|
||||
self.cur.execute('''CREATE TABLE IF NOT EXISTS expiry
|
||||
(key TEXT PRIMARY KEY, expire_at INTEGER)''')
|
||||
self.conn.commit()
|
||||
self.cur.execute('''CREATE TABLE IF NOT EXISTS list_store
|
||||
(key TEXT, idx INTEGER, value TEXT,
|
||||
PRIMARY KEY (key, idx))''')
|
||||
self.conn.commit()
|
||||
self.cur.execute('''CREATE TABLE IF NOT EXISTS hash_store
|
||||
(key TEXT, field TEXT, value TEXT,
|
||||
PRIMARY KEY (key, field))''')
|
||||
self.conn.commit()
|
||||
|
||||
|
||||
def set(self, key, value):
|
||||
self.cur.execute("REPLACE INTO kv_store (key, value) VALUES (?, ?)",
|
||||
(key, value))
|
||||
self.conn.commit()
|
||||
|
||||
def get(self, key):
|
||||
self.cur.execute("SELECT value FROM kv_store WHERE key = ?", (key,))
|
||||
result = self.cur.fetchone()
|
||||
if result:
|
||||
return result[0]
|
||||
return None
|
||||
|
||||
def delete(self, key):
|
||||
self.cur.execute("DELETE FROM kv_store WHERE key = ?", (key,))
|
||||
self.cur.execute("DELETE FROM expiry WHERE key = ?", (key,))
|
||||
self.conn.commit()
|
||||
|
||||
def expire(self, key, seconds):
|
||||
expire_at = int(time.time()) + seconds
|
||||
self.cur.execute("REPLACE INTO expiry (key, expire_at) VALUES (?, ?)",
|
||||
(key, expire_at))
|
||||
self.conn.commit()
|
||||
|
||||
def ttl(self, key):
|
||||
self.cur.execute("SELECT expire_at FROM expiry WHERE key = ?", (key,))
|
||||
result = self.cur.fetchone()
|
||||
if result:
|
||||
ttl = result[0] - int(time.time())
|
||||
return max(ttl, 0)
|
||||
return -1
|
||||
|
||||
def _cleanup_expired(self):
|
||||
now = int(time.time())
|
||||
self.cur.execute("DELETE FROM kv_store WHERE key IN "
|
||||
"(SELECT key FROM expiry WHERE expire_at <= ?)", (now,))
|
||||
self.cur.execute("DELETE FROM expiry WHERE expire_at <= ?", (now,))
|
||||
self.conn.commit()
|
||||
|
||||
def close(self):
|
||||
self.conn.close()
|
||||
|
||||
def lpush(self, key, *values):
|
||||
for value in values:
|
||||
self.cur.execute("INSERT INTO list_store (key, idx, value) "
|
||||
"SELECT ?, COALESCE(MIN(idx), 0) - 1, ? "
|
||||
"FROM list_store WHERE key = ?", (key, value, key))
|
||||
self.conn.commit()
|
||||
return self.llen(key)
|
||||
|
||||
def rpush(self, key, *values):
|
||||
for value in values:
|
||||
self.cur.execute("INSERT INTO list_store (key, idx, value) "
|
||||
"SELECT ?, COALESCE(MAX(idx), -1) + 1, ? "
|
||||
"FROM list_store WHERE key = ?", (key, value, key))
|
||||
self.conn.commit()
|
||||
return self.llen(key)
|
||||
|
||||
def lpop(self, key):
|
||||
self.cur.execute("SELECT value FROM list_store WHERE key = ? "
|
||||
"ORDER BY idx ASC LIMIT 1", (key,))
|
||||
result = self.cur.fetchone()
|
||||
if result:
|
||||
self.cur.execute("DELETE FROM list_store WHERE key = ? "
|
||||
"AND idx = (SELECT MIN(idx) FROM list_store WHERE key = ?)",
|
||||
(key, key))
|
||||
self.conn.commit()
|
||||
return result[0]
|
||||
return None
|
||||
|
||||
def llen(self, key):
|
||||
self.cur.execute("SELECT COUNT(*) FROM list_store WHERE key = ?", (key,))
|
||||
return self.cur.fetchone()[0]
|
||||
|
||||
def lrange(self, key, start, stop):
|
||||
self.cur.execute("SELECT value FROM list_store WHERE key = ? "
|
||||
"ORDER BY idx ASC LIMIT ? OFFSET ?",
|
||||
(key, stop - start, start))
|
||||
return [row[0] for row in self.cur.fetchall()]
|
||||
|
||||
def hset(self, key, field, value):
|
||||
self.cur.execute("REPLACE INTO hash_store (key, field, value) VALUES (?, ?, ?)",
|
||||
(key, field, value))
|
||||
self.conn.commit()
|
||||
return 1
|
||||
|
||||
def hget(self, key, field):
|
||||
self.cur.execute("SELECT value FROM hash_store WHERE key = ? AND field = ?",
|
||||
(key, field))
|
||||
result = self.cur.fetchone()
|
||||
return result[0] if result else None
|
||||
|
||||
def hdel(self, key, *fields):
|
||||
deleted = 0
|
||||
for field in fields:
|
||||
self.cur.execute("DELETE FROM hash_store WHERE key = ? AND field = ?",
|
||||
(key, field))
|
||||
deleted += self.cur.rowcount
|
||||
self.conn.commit()
|
||||
return deleted
|
||||
|
||||
def hlen(self, key):
|
||||
self.cur.execute("SELECT COUNT(*) FROM hash_store WHERE key = ?", (key,))
|
||||
return self.cur.fetchone()[0]
|
||||
|
||||
def hgetall(self, key):
|
||||
self.cur.execute("SELECT field, value FROM hash_store WHERE key = ?", (key,))
|
||||
return dict(self.cur.fetchall())
|
||||
|
||||
|
||||
# 사용 예시
|
||||
r = SQLiteRedis()
|
||||
r.set('mykey', 'Hello, World!')
|
||||
print(r.get('mykey'))
|
||||
r.expire('mykey', 10)
|
||||
print(r.ttl('mykey'))
|
||||
|
||||
# LIST 사용
|
||||
r.lpush("mylist", "world", "hello")
|
||||
r.rpush("mylist", "!")
|
||||
print(r.lrange("mylist", 0, -1)) # ['hello', 'world', '!']
|
||||
print(r.lpop("mylist")) # 'hello'
|
||||
|
||||
# HASH 사용
|
||||
r.hset("myhash", "name", "John")
|
||||
r.hset("myhash", "age", "30")
|
||||
print(r.hget("myhash", "name")) # 'John'
|
||||
print(r.hgetall("myhash")) # {'name': 'John', 'age': '30'}
|
||||
#
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user