text: #!/usr/local/bin/python3.6
  # -*- coding:utf-8 -*-
  # ========================================
  # Description :
  #    兼容多数据库 Loader
  # Created : 2020.10.22
  # Author : Chalk Yu
  # ========================================
  from __future__ import absolute_import
  from .extends import SqlParser, OrmLoader
  import os
  from sqlalchemy import create_engine
  from sqlalchemy.orm import sessionmaker, relationship, scoped_session
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy.pool import NullPool
  from ..tool import FormatMsg
  from ..screws import Store
  
  
  class loader(OrmLoader, SqlParser):
      def __init__(self):
          super().__init__()
  
      def connect(self, dbConf=None):
          dbAccess = Store({
              'DB_DRIVER': self.DB_DRIVER,
              'DB_USER': self.DB_USER,
              'DB_PASSWORD': self.DB_PASSWORD,
              'DB_HOST': self.DB_HOST,
              'DB_PORT': self.DB_PORT,
              'DB_DATABASE': self.DB_DATABASE,
              'ENCODING': self.ENCODING,
              'ALLOW_ROLLBACK': self.ALLOW_ROLLBACK,
              'AUTO_COMMIT': self.AUTO_COMMIT,
              'SQLALCHEMY_ARGS': self.SQLALCHEMY_ARGS
          })
          if dbConf != None:
              dbAccess = dbConf
  
          conn_str = ''
          if dbAccess.DB_DRIVER == "postgres":
              conn_str = 'postgresql+psycopg2://%s:%s@%s:%s/%s' % (
                  dbAccess.DB_USER, dbAccess.DB_PASSWORD, dbAccess.DB_HOST, dbAccess.DB_PORT, dbAccess.DB_DATABASE)
          elif dbAccess.DB_DRIVER == "mysql":
              conn_str = 'mysql+pymysql://%s:%s@%s:%s/%s' % (
                  dbAccess.DB_USER, dbAccess.DB_PASSWORD, dbAccess.DB_HOST, dbAccess.DB_PORT, dbAccess.DB_DATABASE)
          elif dbAccess.DB_DRIVER == "oracle":
              conn_str = 'oracle+cx_oracle://%s:%s@%s:%s/%s' % (
                  dbAccess.DB_USER, dbAccess.DB_PASSWORD, dbAccess.DB_HOST, dbAccess.DB_PORT, dbAccess.DB_DATABASE)
          elif dbAccess.DB_DRIVER == "mssql":
              conn_str = 'mssql+pymssql://%s:%s@%s:%s/%s' % (
                  dbAccess.DB_USER, dbAccess.DB_PASSWORD, dbAccess.DB_HOST, dbAccess.DB_PORT, dbAccess.DB_DATABASE)
          elif dbAccess.DB_DRIVER == "sqlite":
              conn_str = 'sqlite:///%s' % dbAccess.SQLITE_PATH
          else:
              raise Exception(
                  FormatMsg("DB Driver must be one of postgres/mysql."))
          # 连接数据库
          if conn_str != '':
              # sqlalchemy扩展参数
              engine = None
              if dbAccess.SQLALCHEMY_ARGS and type(dbAccess.SQLALCHEMY_ARGS.create_engine) == dict:
                  if dbAccess.SQLALCHEMY_ARGS.create_engine['poolclass'] == None:
                      dbAccess.SQLALCHEMY_ARGS.create_engine['poolclass'] = NullPool
                  if dbAccess.SQLALCHEMY_ARGS.create_engine['encoding'] == None:
                      dbAccess.SQLALCHEMY_ARGS.create_engine['encoding'] = dbAccess.ENCODING
                  engine = create_engine(
                      conn_str, **dbAccess.SQLALCHEMY_ARGS.create_engine)
              else:
                  engine = create_engine(
                      conn_str, poolclass=NullPool, encoding=dbAccess.ENCODING)
              #
              sessionFacory = None
              if dbAccess.SQLALCHEMY_ARGS and type(dbAccess.SQLALCHEMY_ARGS.sessionmaker) == dict:
                  if dbAccess.SQLALCHEMY_ARGS.sessionmaker['autoflush'] == None:
                      dbAccess.SQLALCHEMY_ARGS.sessionmaker['autoflush'] = True
                  sessionFacory = sessionmaker(
                      bind=engine, **dbAccess.SQLALCHEMY_ARGS.sessionmaker)
              else:
                  sessionFacory = sessionmaker(bind=engine, autoflush=True)
              #
              __connection__ = None
              if dbAccess.SQLALCHEMY_ARGS and type(dbAccess.SQLALCHEMY_ARGS.scoped_session) == dict:
                  __connection__ = scoped_session(
                      sessionFacory, **dbAccess.SQLALCHEMY_ARGS.scoped_session)
              else:
                  __connection__ = scoped_session(sessionFacory)
              #
              return __connection__
  
      def execute(self, conn, sqlStr, sqlAction):
          # self._SqlAction_ = sqlAction
          try:
              cur = conn.execute(sqlStr)
              self.logging("DEBUG", FormatMsg("SQL execute success."))
              return cur
          except Exception as exc:
              self.logging("ERROR", FormatMsg("SQL execute error."))
              raise Exception("%s: %s" % (exc.__class__.__name__, exc))
  
      def close(self, conn):
          conn.close()
  
      def commit(self, conn):
          conn.commit()
  
      def rollback(self, conn):
          conn.rollback()
  
      def inject(self, conn, sqlAction, cursor, bean, resultCreater):
          if(cursor == None):
              raise Exception(
                  FormatMsg("The 'cursor' returned by the 'execute' function cannot be 'None'."))
          if sqlAction == 'SELECT':
              res = resultCreater(list)(cursor=cursor, count=None)
              rowcount = 0
              for record in cursor:
                  res.append(bean(*record))
                  rowcount += 1
              res.count = rowcount
              return res
          elif sqlAction == 'INSERT':
              res = resultCreater()(cursor=cursor, count=None)
              return res
          elif sqlAction == 'UPDATE':
              res = resultCreater()(cursor=cursor, count=None)
              return res
          elif sqlAction == 'DELETE':
              res = resultCreater()(cursor=cursor, count=None)
              return res
          elif sqlAction == 'TRUNCATE':
              res = resultCreater()(cursor=cursor, count=None)
              return res
          else:
              raise Exception(FormatMsg(
                  f'The sql action must be one of SELECT, INSERT, UPDATE, DELETE, TRUNCATE.'))
  