diff --git a/basic/compexec.py b/basic/compexec.py index e921120..df3e1e0 100644 --- a/basic/compexec.py +++ b/basic/compexec.py @@ -1,3 +1,9 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# --------------------------------------------------------------------------------------------------------- +# Author : Ulrich Carmesin +# Source : gitea.ucarmesin.de +# --------------------------------------------------------------------------------------------------------- # abstract class for testrunning-functions # --------------------------------------------- """ @@ -32,6 +38,7 @@ import basic.message import basic.program import inspect import os +import re import utils.db_abstract import basic.toolHandling import basic.component @@ -196,12 +203,14 @@ class Testexecuter(): sql_new += " "+attr[B.ATTR_DB_DATABASE]+"."+table print("sql_new "+sql_new) if (hasattr(job.par, B.PAR_DB_WHERE)): + # actual it parses only conjunct or disjunct normalform without parentesis parts = utils.db_abstract.parseSQLwhere(getattr(job.par, B.PAR_DB_WHERE), self.conf[B.DATA_NODE_DDL][table]) # Felder und Operationen # print(dbwhere) - sql_new += " WHERE "+getattr(job.par, B.PAR_DB_WHERE) + sql_new += " WHERE "+parts if sql_new[0:6] == "SELECT": - sql_new += " ORDER BY id" + ids = utils.db_abstract.getTechnicalIDFields(self.conf["ddl"][table]) + sql_new += " ORDER BY "+",".join(ids) print("sql_new "+sql_new) sql_new = sql_new.replace('!', "\'") if (hasattr(job.par, B.PAR_DB_PARTITION)) and (attr[B.ATTR_DB_PARTITION] != "n"): diff --git a/test/constants.py b/test/constants.py index 2aed407..ff8c576 100644 --- a/test/constants.py +++ b/test/constants.py @@ -1,3 +1,9 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# --------------------------------------------------------------------------------------------------------- +# Author : Ulrich Carmesin +# Source : gitea.ucarmesin.de +# --------------------------------------------------------------------------------------------------------- """ constants """ @@ -6,6 +12,8 @@ home = os.getcwd() prgdir = "" if home[-4:] == "test" and home[-6:] != "datest": home = home[0:-5] +if home[-10:] == "components": + home = home[0:-11] if home[-6:] == "datest": prgdir = home[-6:] home = home[0:-7] diff --git a/test/test_31db.py b/test/test_31db.py index ec25b17..af530f8 100644 --- a/test/test_31db.py +++ b/test/test_31db.py @@ -1,3 +1,9 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# --------------------------------------------------------------------------------------------------------- +# Author : Ulrich Carmesin +# Source : gitea.ucarmesin.de +# --------------------------------------------------------------------------------------------------------- import unittest import inspect import basic.program @@ -15,8 +21,8 @@ HOME_PATH = test.constants.HOME_PATH conf = {} # here you can select single testfunction for developping the tests # "test_toolhandling", "test_parseSql" -> test of components -TEST_FUNCTIONS = ["test_formatDbRows"] -#TEST_FUNCTIONS = ["test_formatDbRows"] +TEST_FUNCTIONS = ["test_formatDbRows", "test_getTechnicalIDFields"] +TEST_FUNCTIONS = ["test_getTechnicalIDFields"] class MyTestCase(unittest.TestCase): mymsg = "--------------------------------------------------------------" @@ -29,10 +35,6 @@ class MyTestCase(unittest.TestCase): if actfunction not in TEST_FUNCTIONS: return job = test.testtools.getJob() - args = {"application": "TEST", "environment": "ENV01", "modus": "unit", "loglevel": "debug", "tool": "config_tool", - "modus": "unit"} - job.par.setParameterArgs(args) - # "SELECT * FROM lofts" obj = utils.db_abstract.parseConditions("family like !%utz%! and state = !+reg+!") self.assertEqual(obj[0][3], "and") self.assertEqual(obj[0][1], "family") diff --git a/utils/db_abstract.py b/utils/db_abstract.py index 00c5493..b25b7f0 100644 --- a/utils/db_abstract.py +++ b/utils/db_abstract.py @@ -65,7 +65,6 @@ def getDbAttributes(comp, table): B.ATTR_DB_CONN_JAR: D.DEFAULT_DB_CONN_JAR } for attr in out.keys(): - print(attr) if (table in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB]) \ and (attr in comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][table]): out[attr] = comp.conf[B.SUBJECT_ARTS][B.TOPIC_NODE_DB][table][attr] @@ -180,10 +179,17 @@ def getTechnicalIDFields(ddl): if "T" in ddl[f][D.DDL_KEY]: keys[ddl[f][D.DDL_KEY]] = f for k in keys: - ids.append(k) - return ids + ids.append(keys[k]) + return ids +def isConditionInFields(cond, ddl): + a = cond.split(" ") + for x in a: + if x in ddl: + return True + return False + def formatDbRows(table, comp, rows): out = [] fields = comp.conf[B.DATA_NODE_DDL][table] diff --git a/utils/dbrel_tool.py b/utils/dbrel_tool.py new file mode 100644 index 0000000..4d5ee77 --- /dev/null +++ b/utils/dbrel_tool.py @@ -0,0 +1,102 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# --------------------------------------------------------------------------------------------------------- +# Author : Ulrich Carmesin +# Source : gitea.ucarmesin.de +# --------------------------------------------------------------------------------------------------------- +import basic.program +import utils.config_tool +import utils.db_abstract +import mysql.connector +import basic.constants as B + +class DbFcts(utils.db_abstract.DbFcts): + """ + This interface defines each necessary connection to any kind of database. + The specific technique how to connect to the concrete DBMS has to be implemented in the specific tool. + """ + + def __init__(self): + pass + + def selectRows(self, table): + """ method to select rows from a database + statement written in sql """ + tdata = {} + job = basic.program.Job.getInstance() + verify = -1+job.getDebugLevel("db_tool") + cmd = "SELECT * FROM "+table+";" + #mycursor = self.getConnector() + #mycursor.execute(cmd) + #myresult = mycursor.fetchall() + tdata[B.DATA_NODE_HEADER] = [] + for f in self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_HEADER]: + tdata[B.DATA_NODE_HEADER].append(f) + myresult = [] + for x in myresult: + print(x) + self.comp.m.logInfo(cmd) + return tdata + + def deleteRows(self, table): + """ method to delete rows from a database + statement written in sql """ + job = basic.program.Job.getInstance() + verify = -1+job.getDebugLevel("db_tool") + cmd = "DELETE FROM "+table+";" + self.comp.m.logInfo(cmd) + + def updateRows(self, statement): + """ method to delete rows from a database + statement written in sql """ + raise Exception(B.EXCEPT_NOT_IMPLEMENT) + + def insertRows(self, table, rows): + """ method to insert rows into a database + the rows will be interpreted by the ddl of the component + """ + job = basic.program.Job.getInstance() + verify = -1+job.getDebugLevel("db_tool") + cmd = "INSERT INTO "+table+";" + header = "" + for h in self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_HEADER]: + print(h) + header += ", "+h + cmd += " (" + header[1:]+" ) " + rowvalues = "" + for r in rows: + print("r-----------------") + print(r) + rowvalues = "" + cmd += "\n ( " + for h in self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_HEADER]: + print("h "+h) + if (h in r): + rowvalues += ", "+self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_DATA][h], r[h]) + else: + rowvalues += ", "+self.getDbValue(self.comp.conf[B.DATA_NODE_DDL][table][B.DATA_NODE_DATA][h], "") + print("rv " + rowvalues) + cmd += rowvalues[1:]+" )," + cmd = cmd[0:-1]+";" + self.comp.m.logInfo(cmd) + + def getConnector(self): + """ add-on-method to get the connector + this method should only called by the class itself """ + job = basic.program.Job.getInstance() + mydb = mysql.connector.connect( + host = "localhost", + user = "datest", + password = "Advent!2021", + database = "datest" + ) + return mysql + + @staticmethod + def execStatement(self, comp, conn, statement): + """ add-on-method to execute the statement + this method should only called by the class itself """ + raise Exception(B.EXCEPT_NOT_IMPLEMENT) + + +