Esempio n. 1
0
 async def _execute_trans(self, sql: TCL) -> result.Result:
     try:
         if sql.is_start:
             if self._trans:
                 raise Exception("Transactions cannot be nested.")
             self._trans = self._create_trans(sql.trans_args)
             await self._trans.begin(sql)
             return result.OK(0, 0, 0, 0, '', False)
         elif sql.is_commit:
             if self._trans:
                 await self._trans.commit(sql)
                 await self._trans.close()
                 self._trans = None
             return result.OK(0, 0, 0, 0, '', False)
         elif sql.is_rollback:
             if self._trans:
                 await self._trans.rollback(sql)
                 await self._trans.close()
                 self._trans = None
             return result.OK(0, 0, 0, 0, '', False)
         else:
             return result.Error(1000, "unknown what to do.")
     except Exception as e:
         await self._trans.close()
         self._trans = None
         return result.Error(1000, str(e))
Esempio n. 2
0
 async def rollback(self, sql: TCL) -> Optional[result.Result]:
     r = await self.a2pc_client.rollback(self.xid)
     if r.status == 0:
         self.status = TransStatus.END
         return result.OK(0, 0, 0, 0, "", False)
     else:
         return result.Error(r.status, r.msg)
Esempio n. 3
0
 async def begin(self, sql: TCL) -> Optional[result.Result]:
     self.status = TransStatus.BEGINNING
     r = await self.a2pc_client.begin()
     if r.status == 0:
         self.xid = r.xid
     else:
         return result.Error(r.status, r.msg)
     self.status = TransStatus.ACTIVE
Esempio n. 4
0
 async def query(self, sql) -> result.Result:
     try:
         await self._ensure_connected()
         await self._conn.query(sql)
         self._result = self._conn._result
         return self.read_result()
     except MySQLError as e:
         return result.Error(e.args[0], e.args[1])
Esempio n. 5
0
 async def batch(self, sql) -> Union[DictCursor, result.Error]:
     try:
         await self._ensure_connected()
         cur = await self._conn.cursor()
         await cur.execute(sql)
         self._result = cur._result
         return cur
     except MySQLError as e:
         return result.Error(10003, str(e))
Esempio n. 6
0
 async def _execute_ending(self, r: List[Union[result.Result,
                                               A2PCResponse]],
                           node: List[DBTableStrategyBackend], sql: DMLW):
     lock = r[-1]
     r = r[:-1]
     ending_sql = "COMMIT"
     return_v = None
     if not isinstance(lock, A2PCResponse):
         ending_sql = "ROLLBACK"
         return_v = result.Error(
             1000,
             "{} acquire lock fail: {}".format(str(sql.raw), str(lock)))
     elif lock.status != 0:
         logger.warning("{} acquire lock fail: {}".format(
             str(sql.raw), lock.msg))
         ending_sql = "ROLLBACK"
         return_v = result.Error(
             1000,
             "{} acquire lock fail: {}".format(str(sql.raw), lock.msg))
     if any([isinstance(i, result.Error) for i in r]):
         errors = [i for i in r if isinstance(i, result.Error)]
         for i in errors:
             logger.warning("{} error with code[{}],msg: {}".format(
                 str(sql.raw), i.error_code, i.message))
         ending_sql = "ROLLBACK"
         return_v = errors[0]
     c = []
     for i in node:
         c.append(self._execute_ending_sql(ending_sql, i))
     # 如果在 rollback 的时候异常,抛错给 app,即使数据库没有 rollback,
     # 也会在超时机制下回滚。 backend 遇到异常会关闭 session 触发 mysql
     # 的超时
     # 如果在 commit 的时候出现异常,返回错误给客户端,客户端可以重试,
     # 成功就走正常流程,或者选择回滚,回滚就走事务回滚流程
     await asyncio.gather(*c)
     if ending_sql == "ROLLBACK":
         return return_v  # type: ignore
     return result.OK(1, 0, 2, 0, "", False)
Esempio n. 7
0
 async def execute_dml(self, sql: DML) -> result.Result:
     if not sql.table:
         return await self.execute_other(sql)
     table = self.db.get_table(str(sql.table))
     if not table.is_allow_write_sql(sql):
         return result.Error(
             1034, "current zone dont allowed execute this sql{}".format(
                 str(sql.raw)))
     if isinstance(sql, Select):
         return await self.execute_select(sql)
     elif isinstance(sql, Insert):
         return await self.execute_insert(sql)
     elif isinstance(sql, Update):
         return await self.execute_update(sql)
     elif isinstance(sql, Delete):
         return await self.execute_delete(sql)
     else:
         return await self.execute_other(sql)