# -*- coding:utf-8 -*-

"""
Author: qiaoxinjiu
Create Data: 2020/11/6 17:30
"""
import time
import re
from retrying import retry
from base_framework.public_tools import log
from base_framework.public_tools.db_dbutils_init import get_my_connection,get_pg_connection
from base_framework.public_tools.read_config import get_current_config, get_current_env
from base_framework.public_tools.huohua_dbs import HuoHuaDBS
obj_log = log.get_logger()


"""执行语句查询有结果返回结果没有返回0；增/删/改返回变更数据条数，没有返回0"""
# retry 参数说明
"""
stop_max_attempt_number					指定重试的次数，默认是5
stop_max_delay							指定重试超时时间，默认是100，单位是ms
wait_fixed							    指定每次重试的时间间隔，默认是1000，单位是ms
wait_random_min=None           			指定每次重试最小时间，默认为0
wait_random_max=None,					指定每次重试最大时间，默认为1000
wait_incrementing_start			        指定每次重试递增的开始时间
wait_incrementing_increment				指定每次重试时间的递增幅度
wait_exponential_multiplier				指定每次重试时间的递增幅度，跟上面的参数算法差异
wait_exponential_max					指定每次重试时间的递增幅度的最大值
retry_on_exception 						指定每次出现异常执行的函数
retry_on_result							指定程序运行正常执行的函数
wrap_exception                       	出现异常后返回的异常类型，True是返回原异常，False返回RetryError
stop_func								自定义停止重试的条件，传入参数是一个函数
wait_func 								自定义每次重试的时间间隔，传入参数是一个函数
wait_jitter_max							指定每次重试时间抖动值
stop									指定重试停止后，执行Retrying对象的成员函数
wait									指定重试间隔，执行Retrying对象的成员函数
"""


class MySqLHelper:
    """
        mysql数据库操作
    """
    def __init__(self):
        self.db = get_my_connection()  # 从数据池中获取连接
        self.current_business = get_current_config(section='run_evn_name', key='current_business')
        self.current_evn = get_current_env()
        self.qa_db_to_sim_instance_name = {}
        self.sim_dbs = HuoHuaDBS()

    # def __new__(cls, *args, **kwargs):
    #     if not hasattr(cls, 'inst'):  # 单例
    #         cls.inst = super(MySqLHelper, cls).__new__(cls, *args, **kwargs)
    #     return cls.inst


    # 封装执行命令
    def execute(self, sql, param=None, auto_close=False, choose_db=None):
        """
        | 功能说明： | 执行具体的sql语句 |
        | 输入参数： | sql | 待执行的sql语句 |
        |           | param=None | sql语句中where后跟的参数，也可直接写在sql语句中 |
        |           | auto_close=True | 是否自动关闭数据库连接，默认：自动关闭 |
        | 返回参数： | conn，cursor，count | 连接，游标，行数 |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        if self.current_evn.lower() == "sim":
            raise Exception("SIM环境请直接使用huohua_dbs.py中的函数")

        # if 'sparkatp' in sql or 'push_service' in sql : # 自动化和信息化的数据都走huohua
        #     choose_db = 'hh.qa'
        # if "account." in sql or "emp." in sql or "sso." in sql:
        #     choose_db = 'hh.qa'

        cursor, conn = self.db.getconn(choose_db=choose_db)  # 从连接池获取连接
        try:
            # count : 为改变的数据条数
            if param:
                count = cursor.execute(sql, param)
            else:
                count = cursor.execute(sql)
            conn.commit()
            if auto_close:
                self.close(cursor, conn)
        except Exception as e:
            obj_log.error(e)
            raise ValueError("数据库操作失败，SQL语句：{}".format(sql))
        return cursor, conn, count

    # 释放连接
    @staticmethod
    def close(cursor, conn):
        """
        | 功能说明： | 关闭数据库连接 |
        | 输入参数： | cursor | 游标 |
        |           | conn | 连接 |
        | 返回参数： | 无 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        函数位置：Public/Common/mysql_api.py
        """
        cursor.close()
        conn.close()

    # 查询所有
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def select_all(self, sql, param=None, choose_db=None, show_log=True):
        """
        | 功能说明： | 查询数据库 | 并返回所有结果 |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | 查询语句中where条件后的参数，也可直接写入sql语句中 |
        | 返回参数： | 所有查询结果 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        函数位置：Public/Common/mysql_api.py
        """
        if self.current_evn.lower() == "sim":
            return self.sim_dbs.dbs_select(sql_content=sql)

        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))
        if show_log:
            if param is not None:
                obj_log.info('SQL语句：{}|{}'.format(sql, param))
            else:
                obj_log.info('SQL语句：{}'.format(sql))

        try:
            cursor, conn, count = self.execute(sql, param, choose_db=choose_db)
            res = cursor.fetchall()
            if show_log:
                obj_log.info('数据库查询结果：{}'.format(res))
            return res
        except Exception as e:
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    def select_all_as_list(self, sql, choose_db=None):
        """
        | 功能说明： | 查询数据库 | 功能同select_all,仅返回结果为list |
        | 输入参数： | sql | 待执行的查询语句 |
        | 返回参数： | 所有查询结果，类型：list |  |
        | 作者信息： | 吴勇刚     | 2021/11/22 |
        函数位置：Public/Common/mysql_api.py
        """
        if self.current_evn.lower() == "sim":
            return self.sim_dbs.dbs_select(sql_content=sql, r_type='list')

        try:
            cursor, conn, count = self.execute(sql, choose_db=choose_db)
            res = cursor.fetchall()
            has_data = False  # 以下代码是防止返回空值列表添加的
            for item in res:
                for key in item:
                    if item[key]:
                        has_data = True  # 有一个值非空即可
                        break
            if not has_data:
                return []  # 以上代码是防止返回空值列表添加的
            res_list = []
            for index in range(len(res)):
                if len(res[index]) > 1:
                    res_row = []
                    for key in res[index]:
                        res_row.append(res[index][key])
                    res_list.append(res_row)
                else:
                    for key in res[index]:
                        res_list.append(res[index][key])
            return res_list
        except Exception as e:
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 查询单条
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def select_one(self, sql, param=None, choose_db=None):
        """
        | 功能说明： | 查询数据库，并返第一行 |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | 查询语句中where条件后的参数，也可直接写入sql语句中 |
        | 返回参数： | 返回第一条查询结果 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        函数位置：Public/Common/mysql_api.py
        """
        if self.current_evn.lower() == "sim":
            if 'limit' not in sql.lower():
                sql = sql.split(';')[0] + ' limit 1;'
            sim_data = self.sim_dbs.dbs_select(sql_content=sql)
            if sim_data:
                return sim_data[0]
            else:
                return {}
        try:
            cursor, conn, count = self.execute(sql, param, choose_db=choose_db)
            res = cursor.fetchone()
            return res
        except Exception as e:
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 增加
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def insert_one(self, sql, param=None, choose_db=None, log_level='info'):
        """
        | 功能说明： | insert一行数据 |
        | 输入参数： | sql | 待执行的查询语句 |
        |          | param=None | sql语句中where条件后的参数，也可直接写入sql语句中 |
        |          | log_level='info' | 日志级别：info-全量日志，否则，仅输入报错日志 |
        | 返回参数： | 无 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        if self.current_evn.lower() == "sim":
            return self.sim_dbs.dbs_execute_sql(sql_content=sql)

        if log_level.lower() == 'info':
            if param is not None:
                obj_log.info('SQL语句：{}|{}'.format(sql, param))
            else:
                obj_log.info('SQL语句：{}'.format(sql))
        try:
            cursor, conn, count = self.execute(sql, param, choose_db=choose_db)
            # _id = cursor.lastrowid()  # 获取当前插入数据的主键id，该id应该为自动生成为好
            conn.commit()
            self.close(cursor, conn)
            if log_level.lower() == 'info':
                obj_log.info('插入数据库条数：{}'.format(count))
            return count
            # 防止表中没有id返回0
            # if _id == 0:
            #     return True
            # return _id
        except Exception as e:
            conn.rollback()
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 插入后返回插入ID
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def insert_many_extension(self, sql, param=None, choose_db=None):
        """
        | 功能说明： | insert一行数据，并返回插入行的主键ID |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | sql语句中where条件后的参数，也可直接写入sql语句中 |
        | 返回参数： | insert_count | 插入的条数 |
                   | last_id | 插入最近一条的ID |
                   | insert_id | 插入的第一条数据的主键ID（参数param的的第一条） |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        return_dict = dict()
        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))
        cursor, conn = self.db.getconn(choose_db=choose_db)
        try:
            count = cursor.executemany(sql, eval(str(param)))
            # last_id = cursor.lastrowid  # 获取最新插入数据的主键id
            insert_id = cursor._result.insert_id   # 获取本次插入数据的主键id
            # insert_id_list = list(range(insert_id, insert_id+count))   # 获取最新插入数据的主键id_list
            conn.commit()
            self.close(cursor, conn)
            obj_log.info('插入数据库条数：{}'.format(count))
            return_dict['insert_count'] = count
            # return_dict['last_id'] = last_id
            return_dict['insert_id'] = insert_id
            return return_dict
        except Exception as e:
            conn.rollback()
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 插入后返回插入ID
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def insert_one_extension(self, sql, param=None, choose_db=None):
        """
        | 功能说明： | insert一行数据，并返回插入行的ID |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | sql语句中where条件后的参数，也可直接写入sql语句中 |
        | 返回参数： | insert_count | 插入的条数 |
                   | last_id | 插入最近一条的ID |
                   | insert_id | 插入数据的ID |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        return_dict = dict()
        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))
        try:
            cursor, conn, count = self.execute(sql, param, choose_db=choose_db)
            # last_id = cursor.lastrowid  # 获取最新插入数据的主键id
            insert_id = cursor._result.insert_id  # 获取本次插入数据的主键id
            # insert_id_list = list(range(insert_id, insert_id+count))   # 获取最新插入数据的主键id_list
            conn.commit()
            self.close(cursor, conn)
            obj_log.info('插入数据库条数：{}'.format(count))
            return_dict['insert_count'] = count
            # return_dict['last_id'] = last_id
            return_dict['insert_id'] = insert_id
            return return_dict
        except Exception as e:
            conn.rollback()
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 增加多行
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def insert_many(self, sql, param=None, choose_db=None):
        """
        | 功能说明： | insert多行数据 |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | sql语句中where条件后的参数，必须是元组或列表[(),()]或（（），（）） |
        | 返回参数： | 无 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))
        cursor, conn = self.db.getconn(choose_db=choose_db)
        try:
            count = cursor.executemany(sql, eval(str(param)))
            conn.commit()
            self.close(cursor, conn)
            obj_log.info('插入数据库条数：{}'.format(count))
            return count
        except Exception as e:
            conn.rollback()
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 删除
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def delete(self, sql, param=None, choose_db=None):
        """
        | 功能说明： | 删除数据库记录 |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | sql语句中where条件后的参数，也可直接写入sql语句中 |
        | 返回参数： | 无 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        if self.current_evn.lower() == "sim":
            return self.sim_dbs.dbs_execute_sql(sql_content=sql)

        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))
        try:
            cursor, conn, count = self.execute(sql, param, choose_db=choose_db)
            self.close(cursor, conn)
            obj_log.info('删除数据库条数：{}'.format(count))
            return count
        except Exception as e:
            conn.rollback()
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    # 更新
    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def update(self, sql, param=None, choose_db=None):
        """
        | 功能说明： | 更新数据库记录 |
        | 输入参数： | sql | 待执行的查询语句 |
        |           | param=None | sql语句中where条件后的参数，也可直接写入sql语句中 |
        | 返回参数： | 无 |  |
        | 作者信息： | 林于棚     | 2020/11/26 21:11 |
        | 函数位置： | Public/Common/mysql_api.py ||
        """
        if self.current_evn.lower() == "sim":
            return self.sim_dbs.dbs_execute_sql(sql_content=sql)

        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))
        try:
            cursor, conn, count = self.execute(sql, param, choose_db=choose_db)
            conn.commit()
            self.close(cursor, conn)
            obj_log.info('更新数据库条数：{}'.format(count))
            return count
        except Exception as e:
            conn.rollback()
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    def check_result_exist(self, *select_statement, retry_count=3):
        """
        | 功能说明： | 验证select语句查询的结果存在 |
        | 输入参数： | select_statement | select查询语句，可以多个 |
        |          | retry_count | 重试次数，默认3次 |
        | 返回参数： | 无 | 结果存在则pass，否则failed  |
        | 作者信息： | 吴勇刚     | 2020.12.16      |
        函数位置：Public/Common/mysql_api.py
        举例说明：
        | check_result_exist | [sql1，sql2] |
        """
        # retry_count = 3
        start = 0
        flag = 0
        while start <= retry_count:
            for sql in select_statement:
                res = self.select_all(sql=sql)
                if not res:
                    if start == retry_count:
                        obj_log.info('the result is not exist,but expect at least one')
                        raise RuntimeError(u'No results, when exec sql: %s' % sql)
                    else:
                        obj_log.info('the result is not exist,retry {}'.format(start+1))
                        start += 1
                        time.sleep(1)
                else:
                    obj_log.info('find [{0}] results when exec ：{1}'.format(len(res), sql))
                    flag += 1
                    break
            if flag > 0:
                break

    def check_result_not_exist(self, *select_statement):
        """
        | 功能说明： | 验证select语句查询的结果不存在 |
        | 输入参数： | select_statement | select查询语句列表 |
        | 返回参数： | 无 | 结果不存在则pass，否则failed  |
        | 作者信息： | 吴勇刚     | 2020.12.16      |
        函数位置：Public/Common/mysql_api.py
        举例说明：
        | check_result_not_exist | [sql1，sql2] |
        """
        for sql in select_statement:
            res = self.select_all(sql=sql)
            if res:
                obj_log.info('find [{0}] results, but expect 0'.format(len(res)))
                raise RuntimeError(u'the result exist, when exec sql: %s' % sql)
            else:
                obj_log.info('the result is not exist, this step pass...')

    def row_count(self, selectStatement, param=None):
        """
        Uses the input `selectStatement` to query the database and returns the number of rows from the query.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |
        |  2 | Jerry       | Schneider |

        When you do the following:
        | ${rowCount} | Row Count | SELECT * FROM person |
        | Log | ${rowCount} |

        You will get the following:
        2

        Also, you can do something like this:
        | ${rowCount} | Row Count | SELECT * FROM person WHERE id = 2 |
        | Log | ${rowCount} |

        And get the following
        1
        """
        try:
            cursor, conn, count = self.execute(selectStatement, param)
            self.close(cursor, conn)
            return count
        except Exception as e:
            print("error_msg:", e.args)
            self.close(cursor, conn)

    # 数据库断言
    def kw_check_if_exists_in_database(self, selectStatement, choose_db=None):
        """
        Check if any row would be returned by given the input `selectStatement`. If there are no results, then this will
        throw an AssertionError. Set optional input `sansTran` to True to run command without an explicit transaction
        commit or rollback.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |

        When you have the following assertions in your robot
        | Check If Exists In Database | SELECT id FROM person WHERE first_name = 'Franz Allan' |
        | Check If Exists In Database | SELECT id FROM person WHERE first_name = 'John' |

        Then you will get the following:
        | Check If Exists In Database | SELECT id FROM person WHERE first_name = 'Franz Allan' | # PASS |
        | Check If Exists In Database | SELECT id FROM person WHERE first_name = 'John' | # FAIL |

        """
        obj_log.info(
            'Executing : Check If Exists In Database  |  %s ' %
            selectStatement)
        if not self.select_one(selectStatement, choose_db=choose_db):
            raise AssertionError("Expected to have have at least one row from '%s' "
                                 "but got 0 rows." % selectStatement)
        else:
            return True

    def kw_check_if_not_exists_in_database(self, selectStatement, choose_db=None):
        """
        This is the negation of `check_if_exists_in_database`.

        Check if no rows would be returned by given the input `selectStatement`. If there are any results, then this
        will throw an AssertionError. Set optional input `sansTran` to True to run command without an explicit
        transaction commit or rollback.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |

        When you have the following assertions in your robot
        | Check If Not Exists In Database | SELECT id FROM person WHERE first_name = 'John' |
        | Check If Not Exists In Database | SELECT id FROM person WHERE first_name = 'Franz Allan' |

        Then you will get the following:
        | Check If Not Exists In Database | SELECT id FROM person WHERE first_name = 'John' | # PASS |
        | Check If Not Exists In Database | SELECT id FROM person WHERE first_name = 'Franz Allan' | # FAIL |

        """
        obj_log.info(
            'Executing : Check If Not Exists In Database  |  %s ' %
            selectStatement)
        queryResults = self.select_one(selectStatement, choose_db=choose_db)
        if queryResults:
            raise AssertionError("Expected to have have no rows from '%s' "
                                 "but got some rows : %s." % (selectStatement, queryResults))
        else:
            return True

    def kw_row_count_is_0(self, selectStatement):
        """
        Check if any rows are returned from the submitted `selectStatement`. If there are, then this will throw an
        AssertionError. Set optional input `sansTran` to True to run command without an explicit transaction commit or
        rollback.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |

        When you have the following assertions in your robot
        | Row Count is 0 | SELECT id FROM person WHERE first_name = 'Franz Allan' |
        | Row Count is 0 | SELECT id FROM person WHERE first_name = 'John' |

        Then you will get the following:
        | Row Count is 0 | SELECT id FROM person WHERE first_name = 'Franz Allan' | # FAIL |
        | Row Count is 0 | SELECT id FROM person WHERE first_name = 'John' | # PASS |
        """
        obj_log.info('Executing : Row Count Is 0  |  %s ' % selectStatement)
        num_rows = self.row_count(selectStatement)
        if num_rows > 0:
            raise AssertionError("Expected zero rows to be returned from '%s' "
                                 "but got rows back. Number of rows returned was %s" % (selectStatement, num_rows))
        else:
            return True

    def kw_row_count_is_equal_to_x(self, selectStatement, numRows):
        """
        Check if the number of rows returned from `selectStatement` is equal to the value submitted. If not, then this
        will throw an AssertionError. Set optional input `sansTran` to True to run command without an explicit
        transaction commit or rollback.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |
        |  2 | Jerry       | Schneider |

        When you have the following assertions in your robot
        | Row Count Is Equal To X | SELECT id FROM person | 1 |
        | Row Count Is Equal To X | SELECT id FROM person WHERE first_name = 'John' | 0 |

        Then you will get the following:
        | Row Count Is Equal To X | SELECT id FROM person | 1 | # FAIL |
        | Row Count Is Equal To X | SELECT id FROM person WHERE first_name = 'John' | 0 | # PASS |
        """
        obj_log.info(
            'Executing : Row Count Is Equal To X  |  %s  |  %s ' %
            (selectStatement, numRows))
        num_rows = self.row_count(selectStatement)
        if num_rows != int(str(numRows).encode('ascii')):
            raise AssertionError("Expected same number of rows to be returned from '%s' "
                                 "than the returned rows of %s" % (selectStatement, num_rows))
        else:
            return True

    def kw_row_count_is_greater_than_x(self, selectStatement, numRows):
        """
        Check if the number of rows returned from `selectStatement` is greater than the value submitted. If not, then
        this will throw an AssertionError. Set optional input `sansTran` to True to run command without an explicit
        transaction commit or rollback.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |
        |  2 | Jerry       | Schneider |

        When you have the following assertions in your robot
        | Row Count Is Greater Than X | SELECT id FROM person | 1 |
        | Row Count Is Greater Than X | SELECT id FROM person WHERE first_name = 'John' | 0 |

        Then you will get the following:
        | Row Count Is Greater Than X | SELECT id FROM person | 1 | # PASS |
        | Row Count Is Greater Than X | SELECT id FROM person WHERE first_name = 'John' | 0 | # FAIL |
        """
        obj_log.info(
            'Executing : Row Count Is Greater Than X  |  %s  |  %s ' %
            (selectStatement, numRows))
        num_rows = self.row_count(selectStatement)
        if num_rows <= int(numRows.encode('ascii')):
            raise AssertionError("Expected more rows to be returned from '%s' "
                                 "than the returned rows of %s" % (selectStatement, num_rows))
        else:
            return True

    def kw_row_count_is_less_than_x(self, selectStatement, numRows):
        """
        Check if the number of rows returned from `selectStatement` is less than the value submitted. If not, then this
        will throw an AssertionError. Set optional input `sansTran` to True to run command without an explicit
        transaction commit or rollback.

        For example, given we have a table `person` with the following data:
        | id | first_name  | last_name |
        |  1 | Franz Allan | See       |
        |  2 | Jerry       | Schneider |

        When you have the following assertions in your robot
        | Row Count Is Less Than X | SELECT id FROM person | 3 |
        | Row Count Is Less Than X | SELECT id FROM person WHERE first_name = 'John' | 1 |

        Then you will get the following:
        | Row Count Is Less Than X | SELECT id FROM person | 3 | # PASS |
        | Row Count Is Less Than X | SELECT id FROM person WHERE first_name = 'John' | 1 | # FAIL |
        """
        obj_log.info(
            'Executing : Row Count Is Less Than X  |  %s  |  %s ' %
            (selectStatement, numRows))
        num_rows = self.row_count(selectStatement)
        if num_rows >= int(numRows.encode('ascii')):
            raise AssertionError("Expected less rows to be returned from '%s' "
                                 "than the returned rows of %s" % (selectStatement, num_rows))
        else:
            return True

    def kw_table_must_exist(self, tableName):
        """
        Check if the table given exists in the database. Set optional input `sansTran` to True to run command without an
        explicit transaction commit or rollback.

        For example, given we have a table `person` in a database

        When you do the following:
        | Table Must Exist | person |

        Then you will get the following:
        | Table Must Exist | person | # PASS |
        | Table Must Exist | first_name | # FAIL |
        """
        obj_log.info('Executing : Table Must Exist  |  %s ' % tableName)
        if self.db_api_module_name in ["cx_Oracle"]:
            selectStatement = (
                "SELECT * FROM all_objects WHERE object_type IN ('TABLE','VIEW') AND owner = SYS_CONTEXT('USERENV', 'SESSION_USER') AND object_name = UPPER('%s')" %
                tableName)
        elif self.db_api_module_name in ["sqlite3"]:
            selectStatement = (
                "SELECT name FROM sqlite_master WHERE type='table' AND name='%s' COLLATE NOCASE" %
                tableName)
        elif self.db_api_module_name in ["ibm_db", "ibm_db_dbi"]:
            selectStatement = (
                "SELECT name FROM SYSIBM.SYSTABLES WHERE type='T' AND name=UPPER('%s')" %
                tableName)
        else:
            selectStatement = (
                "SELECT * FROM information_schema.tables WHERE table_name='%s'" %
                tableName)
        num_rows = self.row_count(selectStatement)
        if num_rows == 0:
            raise AssertionError(
                "Table '%s' does not exist in the db" %
                tableName)

    # @retry(stop_max_attempt_number=5, wait_fixed=3000)
    def select_all_as_generator(self, sql, param=None, choose_db=None):
        if param is not None:
            obj_log.info('SQL语句：{}|{}'.format(sql, param))
        else:
            obj_log.info('SQL语句：{}'.format(sql))

        try:
            cursor, conn, counts = self.execute(sql, param, choose_db=choose_db)
            for count in range(counts):
                item = cursor.fetchone()
                obj_log.info(item)
                yield item
        except Exception as e:
            self.close(cursor, conn)
            raise RuntimeError(e.args)

    def get_qa_to_sim_dbs(self):
        get_sql = "select qa_db,sim_instance from sparkatp.qa_db_mapping_sim_dbs where  status=1 and is_delete=0"
        res_info = self.sim_dbs.dbs_query_by_db_name("qadb-slave", "sparkatp", get_sql, limit_num=1000)
        print(res_info)
        for item in res_info:
            self.qa_db_to_sim_instance_name.update({item[0]: item[1]})
        return self.qa_db_to_sim_instance_name

    def get_instance_name(self, sql_str):
        db_name = sql_str.split(".")[0].split(" ")[-1].replace("`", "").replace(" ", "")
        return self.qa_db_to_sim_instance_name.get(db_name)


if __name__ == '__main__':
    db = MySqLHelper()
    # sql = "select id,name,code from peppa.grade_group where course_level in (0, 1, 2, 3) order by id asc;"
    # sql = "  DELETE FROM classes.timetable_plan_teacher WHERE teacher_id in (SELECT id FROM `teach_teacher`.`teacher_profile` WHERE name='666000排课' AND nickname='666000排课');"
    # print("【原始sql】：{}".format(sql))
    # res = db.update_db_name(sql=sql)
    # print(res)
    sql = "SELECT * FROM account.account;"
    res = db.select_one(sql=sql)
    print(res)


