import psycopg2 as psy import regles def verifRegle(co): ''' verifRegle takes a connection to a database, from which it'll go through the data in the current transaction to see if the data correlate to a possible rule violation. ''' cur=co.cursor() cur.execute('''SELECT type,addresse,valeur FROM Status ORDER BY type,addresse;''') res=cur.fetchall() # res contains all the data from the current transaction. The entirety of the status table is loaded. dataState={} for row in res: dataState[(row[0],int(row[1]))]=int(row[2]) # the dictionnary dataState is a litteral representation of the database, with the key being a tuple of the address and the type of data, # dataState's values are the values of the statuses. listRules=regles.getRegles() # listRules contains all the rules created in regles.py, and getRegles is called to get a copy of the rules' list. for rule in listRules: # we check each rule one by one, to see if they aren't violated ruleWarning=0 condition=len(rule[0]) for i in rule[0]: if (i[0],i[1]) in dataState: if dataState[(i[0],i[1])]==i[2]: ruleWarning+=1 # we first verify if the conditions aren't violated. if ruleWarning>=condition: # if all the conditions of the rule are matched, we check to see if the request tries to update the forbidden value. if (rule[1][0],rule[1][1]) in dataState: if dataState[(rule[1][0],rule[1][1])]==rule[1][2]: return False # The boolean False is returned in the case where one rule is violated. return True # If True is returned, it's because there's no rule that is violated, so the request isn't problematic for the system. def ecritureBDD(lStatus,connec): ''' ecritureBDD is the function that is called to upsert (insert or update) the values of the status given in lStatus connec contains the information needed to create a connection to the database ''' co = None try: co = psy.connect(host=connec[0],database=connec[1],user=connec[2],password=connec[3]) # the connection to the database is now created in co. cur = co.cursor() # cur is a cursor on the connection to the database, it lets us perform actions on co's transaction. for i in lStatus: cur.execute("INSERT INTO Status VALUES (%s,%s,%s ) ON CONFLICT (addresse,type) DO UPDATE SET valeur=%s;",(i[1],i[0],i[2],i[2])) # each statuses in lStatus is now upserted in the database on the current transaction, until commited, they aren't actually inside the database. if verifRegle(co)!=True: # verifRegle is executed with the current connection, so it has access to the transaction in order to verify if rules are violated. print("A rule has been violated. The system is endangered. The database hasn't been updated.") # A message is shown to the user to make him aware of the rule that is violated. # a co.rollback() would be called if we managed to block the client request in order to prevent the server to be updated. co.commit() cur.close() except(Exception,psy.DatabaseError) as error: print(error) # In case of an exception, like the failure of the creation of the connection, details are shown to tell the user about it. finally: if co is not None: co.close()