# coding: UTF-8 # Copyright (c) 2020 Huawei Technologies Co.,Ltd. # # openGauss is licensed under Mulan PSL v2. # You can use this software according to the terms # and conditions of the Mulan PSL v2. # You may obtain a copy of Mulan PSL v2 at: # # http://license.coscl.org.cn/MulanPSL2 # # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, # WITHOUT WARRANTIES OF ANY KIND, # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. # See the Mulan PSL v2 for more details. # ---------------------------------------------------------------------------- import os from gspylib.inspection.common import SharedFuncs from gspylib.inspection.common.CheckItem import BaseItem from gspylib.inspection.common.CheckResult import ResultStatus from gspylib.common.Common import DefaultValue from gspylib.common.ErrorCode import ErrorCode from domain_utils.sql_handler.sql_executor import SqlExecutor class CheckTableSkew(BaseItem): def __init__(self): super(CheckTableSkew, self).__init__(self.__class__.__name__) def doCheck(self): security_mode_value = DefaultValue.getSecurityMode() if (security_mode_value == "on"): secMode = True else: secMode = False if (self.cluster.isSingleInstCluster()): if (secMode): finalresult = "" dbList = [] sqlList = [] sqlPath = os.path.realpath( os.path.join(os.path.split(os.path.realpath(__file__))[0], "../../lib/checkblacklist/")) sqlFileName = os.path.join(sqlPath, "GetTableSkew.sql") if (os.path.exists(sqlFileName)): try: with open(sqlFileName, "r") as fp: lines = fp.read() sqlList = lines.split("--sqlblock") sqlList.pop() except Exception as e: raise Exception(ErrorCode.GAUSS_502["GAUSS_50204"] % ("file:%s,Error:%s" % (sqlFileName, str(e)))) else: raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % ("sql file:%s" % sqlFileName)) sqldb = "select datname from pg_database;" (status, result, error) = SqlExecutor.excuteSqlOnLocalhost( self.port, sqldb) if (status != 2): raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % sqldb + (" Error:%s" % error)) recordsCount = len(result) for i in range(0, recordsCount): dbList.append(result[i][0]) dbList.remove("template0") dbList.remove("template1") for db in dbList: schemaTable = [] for sql in sqlList: sql = "set client_min_messages='error';\n" + sql SqlExecutor.excuteSqlOnLocalhost(self.port, sql, db) sql = "SELECT schemaname , tablename FROM " \ "PUBLIC.pgxc_analyzed_skewness WHERE " \ "skewness_tuple > 100000;" (status, result, error) = SqlExecutor.excuteSqlOnLocalhost(self.port, sql, db) if (status != 2): raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % sql + (" Error:%s" % error)) else: for i in iter(result): schema = i[0] table = i[1] schemaTable.append("%s.%s" % (schema, table)) if (schemaTable): finalresult += "%s:\n%s\n" % ( db, "\n".join(schemaTable)) if (finalresult): self.result.rst = ResultStatus.WARNING self.result.val = "The result is not ok:\n%s" % finalresult else: self.result.rst = ResultStatus.OK self.result.val = "Data is well distributed" else: finalresult = "" sqlPath = os.path.realpath( os.path.join(os.path.split(os.path.realpath(__file__))[0], "../../lib/checkblacklist/")) sqlFileName = os.path.join(sqlPath, "GetTableSkew.sql") sqldb = "select datname from pg_database;" output = SharedFuncs.runSqlCmd(sqldb, self.user, "", self.port, self.tmpPath, "postgres", self.mpprcFile) dbList = output.split("\n") dbList.remove("template0") dbList.remove("template1") for db in dbList: db = db.replace("$", "\\$") cmd = "gsql -d %s -p %s -f %s" % ( db, self.port, sqlFileName) tmpout = "" output = SharedFuncs.runShellCmd(cmd, self.user, self.mpprcFile) if (output.find("(0 rows)") < 0): tmpresult = output.splitlines() idxS = 0 idxE = 0 for idx in range(len(tmpresult)): if (not tmpresult[idx].find("---+---") < 0): idxS = idx - 1 if (tmpresult[idx].find("row)") > 0 or tmpresult[ idx].find("rows)") > 0): idxE = idx for i in range(idxS, idxE): tmpout += "%s\n" % tmpresult[i] finalresult += "%s:\n%s\n" % (db, tmpout) if (finalresult): self.result.rst = ResultStatus.WARNING self.result.val = "Data is not well distributed:\n%s" \ % finalresult else: self.result.rst = ResultStatus.OK self.result.val = "Data is well distributed" else: self.result.rst = ResultStatus.NA self.result.val = "First cn is not in this host"