Blame db/connection.py

cbf076
cbf076
import datetime
cbf076
import traceback
4656ad
import MySQLdb.cursors
4656ad
4656ad
from db.parser import parse
4656ad
4656ad
4656ad
class Cursor:
4656ad
  def __init__(self, connection, internal):
4656ad
    self.connection = connection
4656ad
    self.typebytype = self.connection.pool.server.dbtypebytype
4656ad
    self.typebychar = self.connection.pool.server.dbtypebychar
4656ad
    self.internal = internal
4656ad
    self.entered = None
4656ad
    self.iterator = None
4656ad
4656ad
  def get_internal(self):
4656ad
    return self.internal if self.entered is None else self.entered
4656ad
4656ad
  def __enter__(self):
4656ad
    self.entered = self.internal.__enter__()
4656ad
    return self
4656ad
4656ad
  def __exit__(self, exc_type, exc_value, traceback):
4656ad
    self.entered.__exit__(exc_type, exc_value, traceback)
4656ad
    self.entered = None
4656ad
4656ad
  def __iter__(self):
4656ad
    self.iterator = iter(self.get_internal())
4656ad
    return self
4656ad
4656ad
  def __next__(self):
4656ad
    data = next(self.iterator)
4656ad
    if type(data) is dict:
4656ad
      for k, v in data.items():
4656ad
        t = self.typebytype.get( type(v) )
4656ad
        if t: data[k] = t.from_db(self, v)
4656ad
    else:
4656ad
      orig = data
4656ad
      data = list()
4656ad
      for v in orig:
4656ad
        t = self.typebytype.get( type(v) )
4656ad
        data.append(t.from_db(self, v) if t else v)
4656ad
    return data
4656ad
  
4656ad
  def execute(self, sql = None, *args, **kvargs):
4656ad
    if args or kvargs:
4656ad
      sql = parse(self.typebychar, self.connection, sql, *args, **kvargs)
4656ad
    self.get_internal().execute(sql)
cbf076
cbf076
cbf076
class Connection:
cbf076
  def __init__(self, pool, internal, readonly = True):
cbf076
    self.pool = pool
cbf076
    self.internal = internal
cbf076
    self.readonly = readonly
cbf076
    self.finished = True
cbf076
    self.begin()
cbf076
4656ad
  def cursor(self, as_dict = False):
cbf076
    assert not self.finished
4656ad
    cursorclass = MySQLdb.cursors.DictCursor if as_dict else MySQLdb.cursors.Cursor
4656ad
    cursor = Cursor(self, self.internal.cursor(cursorclass))
4656ad
    return cursor
4656ad
  def cursor_list(self):
4656ad
    return self.cursor(False)
4656ad
  def cursor_dict(self):
4656ad
    return self.cursor(True)
4656ad
  
4656ad
  def query(self, as_dict, sql = None, *args, **kvargs):
4656ad
    with self.cursor(as_dict) as cursor:
4656ad
      cursor.execute(sql, *args, **kvargs)
4656ad
      return list(cursor)
4656ad
  def query_list(self, sql = None, *args, **kvargs):
4656ad
    return self.query(False, sql, *args, **kvargs)
4656ad
  def query_dict(self, sql = None, *args, **kvargs):
4656ad
    return self.query(True, sql, *args, **kvargs)
4656ad
4656ad
  def execute(self, sql = None, *args, **kvargs):
4656ad
    with self.cursor() as cursor:
4656ad
      cursor.execute(sql, *args, **kvargs)
cbf076
cbf076
  def insert_id(self, *args, **kwargs):
cbf076
    assert not self.finished
cbf076
    return self.internal.insert_id(*args, **kwargs)
cbf076
  
cbf076
  def escape(self, *args, **kwargs):
cbf076
    r = self.internal.escape(*args, **kwargs)
cbf076
    return r.decode("utf8") if type(r) is bytes else r
cbf076
cbf076
  def escape_string(self, *args, **kwargs):
cbf076
    r = self.internal.escape_string(*args, **kwargs)
cbf076
    return r.decode("utf8") if type(r) is bytes else r
cbf076
  
cbf076
  def begin(self):
cbf076
    assert self.finished
cbf076
    self.finished = False
cbf076
    if self.readonly:
4656ad
      self.execute("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ")
4656ad
      self.execute("START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT")
cbf076
    else:
4656ad
      self.execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")
4656ad
      self.execute("START TRANSACTION READ WRITE, WITH CONSISTENT SNAPSHOT")
4656ad
    self.now = datetime.datetime.now(datetime.timezone.utc)
cbf076
cbf076
  def commit(self):
cbf076
    assert not self.finished
cbf076
    self.internal.commit()
cbf076
    self.finished = True
cbf076
  
cbf076
  def rollback(self):
cbf076
    assert not self.finished
cbf076
    self.internal.rollback()
cbf076
    self.finished = True
cbf076
      
cbf076
  def release(self):
cbf076
    if not self.finished:
cbf076
      try: self.rollback()
cbf076
      except Exception as e:
cbf076
        print(traceback.format_exc())
cbf076
        print(e)