2to3 conversion for osm_ro
[osm/RO.git] / osm_ro / db_base.py
index 4a87721..42e072b 100644 (file)
@@ -29,7 +29,7 @@ __date__ ="$4-Apr-2016 10:05:01$"
 
 import MySQLdb as mdb
 import uuid as myUuid
-import  utils as af
+from . import  utils as af
 import json
 #import yaml
 import time
@@ -65,7 +65,7 @@ def _convert_datetime2str(var):
     It enters recursively in the dict var finding this kind of variables
     '''
     if type(var) is dict:
-        for k,v in var.items():
+        for k,v in list(var.items()):
             if type(v) is datetime.datetime:
                 var[k]= v.strftime('%Y-%m-%dT%H:%M:%S')
             elif type(v) is dict or type(v) is list or type(v) is tuple: 
@@ -85,7 +85,7 @@ def _convert_bandwidth(data, reverse=False, logger=None):
         None
     '''
     if type(data) is dict:
-        for k in data.keys():
+        for k in list(data.keys()):
             if type(data[k]) is dict or type(data[k]) is tuple or type(data[k]) is list:
                 _convert_bandwidth(data[k], reverse, logger)
         if "bandwidth" in data:
@@ -120,7 +120,7 @@ def _convert_str2boolean(data, items):
         None
     '''
     if type(data) is dict:
-        for k in data.keys():
+        for k in list(data.keys()):
             if type(data[k]) is dict or type(data[k]) is tuple or type(data[k]) is list:
                 _convert_str2boolean(data[k], items)
             if k in items:
@@ -271,16 +271,22 @@ class db_base():
             return json.dumps(str(data))
     
     def __tuple2db_format_set(self, data):
-        '''Compose the needed text for a SQL SET, parameter 'data' is a pair tuple (A,B),
+        """Compose the needed text for a SQL SET, parameter 'data' is a pair tuple (A,B),
         and it returns the text 'A="B"', where A is a field of a table and B is the value 
         If B is None it returns the 'A=Null' text, without surrounding Null by quotes
         If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
         and it ensures internal quotes of B are escaped.
-        '''
-        if data[1]==None:
+        B can be also a dict with special keys:
+            {"INCREMENT": NUMBER}, then it produce "A=A+NUMBER"
+        """
+        if data[1] == None:
             return str(data[0]) + "=Null"
         elif isinstance(data[1], str):
             return str(data[0]) + '=' + json.dumps(data[1])
+        elif isinstance(data[1], dict):
+            if "INCREMENT" in data[1]:
+                return "{A}={A}{N:+d}".format(A=data[0], N=data[1]["INCREMENT"])
+            raise db_base_Exception("Format error for UPDATE field")
         else:
             return str(data[0]) + '=' + json.dumps(str(data[1]))
     
@@ -314,7 +320,7 @@ class db_base():
     
     def __remove_quotes(self, data):
         '''remove single quotes ' of any string content of data dictionary'''
-        for k,v in data.items():
+        for k,v in list(data.items()):
             if type(v) == str:
                 if "'" in v: 
                     data[k] = data[k].replace("'","_")
@@ -328,16 +334,40 @@ class db_base():
         Return: the number of updated rows, exception if error
         '''
                 #gettting uuid 
-        values = ",".join(map(self.__tuple2db_format_set, UPDATE.iteritems() ))
+        values = ",".join(map(self.__tuple2db_format_set, iter(UPDATE.items()) ))
         if modified_time:
             values += ",modified_at={:f}".format(modified_time)
         cmd= "UPDATE " + table +" SET " + values +\
-            " WHERE " + " and ".join(map(self.__tuple2db_format_where, WHERE.iteritems() ))
+            " WHERE " + " and ".join(map(self.__tuple2db_format_where, iter(WHERE.items()) ))
         self.logger.debug(cmd)
         self.cur.execute(cmd) 
         return self.cur.rowcount
-    
-    def _new_row_internal(self, table, INSERT, add_uuid=False, root_uuid=None, created_time=0):
+
+    def _new_uuid(self, root_uuid=None, used_table=None, created_time=0):
+        """
+        Generate a new uuid. It DOES NOT begin or end the transaction, so self.con.cursor must be created
+        :param root_uuid: master uuid of the transaction
+        :param used_table: the table this uuid is intended for
+        :param created_time: time of creation
+        :return: the created uuid
+        """
+
+        uuid = str(myUuid.uuid1())
+        # defining root_uuid if not provided
+        if root_uuid is None:
+            root_uuid = uuid
+        if created_time:
+            created_at = created_time
+        else:
+            created_at = time.time()
+        # inserting new uuid
+        cmd = "INSERT INTO uuids (uuid, root_uuid, used_at, created_at) VALUES ('{:s}','{:s}','{:s}', {:f})".format(
+            uuid, root_uuid, used_table, created_at)
+        self.logger.debug(cmd)
+        self.cur.execute(cmd)
+        return uuid
+
+    def _new_row_internal(self, table, INSERT, add_uuid=False, root_uuid=None, created_time=0, confidential_data=False):
         ''' Add one row into a table. It DOES NOT begin or end the transaction, so self.con.cursor must be created
         Attribute 
             INSERT: dictionary with the key:value to insert
@@ -370,10 +400,15 @@ class db_base():
             self.cur.execute(cmd)
         #insertion
         cmd= "INSERT INTO " + table +" SET " + \
-            ",".join(map(self.__tuple2db_format_set, INSERT.iteritems() )) 
+            ",".join(map(self.__tuple2db_format_set, iter(INSERT.items()) )) 
         if created_time:
             cmd += ",created_at=%f" % created_time
-        self.logger.debug(cmd)
+        if confidential_data:
+            index = cmd.find("SET")
+            subcmd = cmd[:index] + 'SET...'
+            self.logger.debug(subcmd)
+        else:
+            self.logger.debug(cmd)
         self.cur.execute(cmd)
         self.cur.rowcount
         return uuid
@@ -385,7 +420,7 @@ class db_base():
         rows = self.cur.fetchall()
         return rows
     
-    def new_row(self, table, INSERT, add_uuid=False, created_time=0):
+    def new_row(self, table, INSERT, add_uuid=False, created_time=0, confidential_data=False):
         ''' Add one row into a table.
         Attribute 
             INSERT: dictionary with the key: value to insert
@@ -402,7 +437,7 @@ class db_base():
             try:
                 with self.con:
                     self.cur = self.con.cursor()
-                    return self._new_row_internal(table, INSERT, add_uuid, None, created_time)
+                    return self._new_row_internal(table, INSERT, add_uuid, None, created_time, confidential_data)
                     
             except (mdb.Error, AttributeError) as e:
                 self._format_error(e, tries)
@@ -466,11 +501,11 @@ class db_base():
         #print 'from_', from_
         if 'WHERE' in sql_dict and len(sql_dict['WHERE']) > 0:
             w=sql_dict['WHERE']
-            where_ = "WHERE " + " AND ".join(map(self.__tuple2db_format_where, w.iteritems())) 
+            where_ = "WHERE " + " AND ".join(map(self.__tuple2db_format_where, iter(w.items()))) 
         else: where_ = ""
         if 'WHERE_NOT' in sql_dict and len(sql_dict['WHERE_NOT']) > 0: 
             w=sql_dict['WHERE_NOT']
-            where_2 = " AND ".join(map(self.__tuple2db_format_where_not, w.iteritems()))
+            where_2 = " AND ".join(map(self.__tuple2db_format_where_not, iter(w.items())))
             if len(where_)==0:   where_ = "WHERE " + where_2
             else:                where_ = where_ + " AND " + where_2
         #print 'where_', where_
@@ -516,7 +551,7 @@ class db_base():
             'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
             'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional)
             'LIMIT':     limit of number of rows (Optional)
-            'ORDER_BY':  list or tuple of fields to order
+            'ORDER_BY':  list or tuple of fields to order, add ' DESC'  to each item if inverse order is required
         Return: a list with dictionaries at each row
         '''
         #print sql_dict
@@ -528,14 +563,14 @@ class db_base():
         where_or = ""
         w=sql_dict.get('WHERE')
         if w:
-            where_and = " AND ".join(map(self.__tuple2db_format_where, w.iteritems() ))
+            where_and = " AND ".join(map(self.__tuple2db_format_where, iter(w.items()) ))
         w=sql_dict.get('WHERE_NOT')
         if w: 
             if where_and: where_and += " AND "
-            where_and += " AND ".join(map(self.__tuple2db_format_where_not, w.iteritems() ) )
+            where_and += " AND ".join(map(self.__tuple2db_format_where_not, iter(w.items()) ) )
         w=sql_dict.get('WHERE_OR')
         if w:
-            where_or =  " OR ".join(map(self.__tuple2db_format_where, w.iteritems() ))
+            where_or =  " OR ".join(map(self.__tuple2db_format_where, iter(w.items()) ))
         if where_and and where_or:
             if sql_dict.get("WHERE_AND_OR") == "AND":
                 where_ = "WHERE " + where_and + " AND (" + where_or + ")"
@@ -549,7 +584,7 @@ class db_base():
             where_ = ""
         #print 'where_', where_
         limit_ = "LIMIT " + str(sql_dict['LIMIT']) if 'LIMIT' in sql_dict else ""
-        order_ = "ORDER BY " + ",".join(map(str,sql_dict['SELECT'])) if 'ORDER_BY' in sql_dict else ""
+        order_ = "ORDER BY " + ",".join(map(str,sql_dict['ORDER_BY'])) if 'ORDER_BY' in sql_dict else ""
         
         #print 'limit_', limit_
         cmd =  " ".join( (select_, from_, where_, limit_, order_) )
@@ -584,7 +619,7 @@ class db_base():
         what = 'uuid' if af.check_valid_uuid(uuid_name) else 'name'
         cmd =  " SELECT * FROM {} WHERE {}='{}'".format(table, what, uuid_name)
         if WHERE_OR:
-            where_or =  " OR ".join(map(self.__tuple2db_format_where, WHERE_OR.iteritems() ))
+            where_or =  " OR ".join(map(self.__tuple2db_format_where, iter(WHERE_OR.items()) ))
             if WHERE_AND_OR == "AND":
                 cmd += " AND (" + where_or + ")"
             else:
@@ -622,7 +657,7 @@ class db_base():
                     rows = self.cur.fetchall()
                     return self.cur.rowcount, rows
             except (mdb.Error, AttributeError) as e:
-                print "nfvo_db.get_uuid DB Exception %d: %s" % (e.args[0], e.args[1])
+                print("nfvo_db.get_uuid DB Exception %d: %s" % (e.args[0], e.args[1]))
                 r,c = self._format_error(e)
                 if r!=-HTTP_Request_Timeout or retry_==1: return r,c