Feature 1413 resiliency to single component failure
[osm/RO.git] / osm_ro / db_base.py
index 10f9404..badf508 100644 (file)
@@ -265,18 +265,28 @@ class db_base():
         '''
         if data==None:
             return 'Null'
+        elif isinstance(data[1], str):
+            return json.dumps(data)
         else:
             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]))
     
@@ -289,24 +299,10 @@ class db_base():
         '''
         if data[1]==None:
             return str(data[0]) + " is Null"
-        
-#         if type(data[1]) is tuple:  #this can only happen in a WHERE_OR clause
-#             text =[]
-#             for d in data[1]:
-#                 if d==None:
-#                     text.append(str(data[0]) + " is Null")
-#                     continue
-#                 out=str(d)
-#                 if "'" not in out:
-#                     text.append( str(data[0]) + "='" + out + "'" )
-#                 elif '"' not in out:
-#                     text.append( str(data[0]) + '="' + out + '"' )
-#                 else:
-#                     text.append( str(data[0]) + '=' + json.dumps(out) )
-#             return " OR ".join(text)
-
-        out=str(data[1])
-        return str(data[0]) + '=' + json.dumps(out)
+        elif isinstance(data[1], str):
+            return str(data[0]) + '=' + json.dumps(data[1])
+        else:
+            return str(data[0]) + '=' + json.dumps(str(data[1]))
 
     def __tuple2db_format_where_not(self, data):
         '''Compose the needed text for a SQL WHERE(not). parameter 'data' is a pair tuple (A,B),
@@ -317,8 +313,10 @@ class db_base():
         '''
         if data[1]==None:
             return str(data[0]) + " is not Null"
-        out=str(data[1])
-        return str(data[0]) + '<>' + json.dumps(out)
+        elif isinstance(data[1], str):
+            return str(data[0]) + '<>' + json.dumps(data[1])
+        else:
+            return str(data[0]) + '<>' + json.dumps(str(data[1]))
     
     def __remove_quotes(self, data):
         '''remove single quotes ' of any string content of data dictionary'''
@@ -344,7 +342,31 @@ class db_base():
         self.logger.debug(cmd)
         self.cur.execute(cmd) 
         return self.cur.rowcount
-    
+
+    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):
         ''' Add one row into a table. It DOES NOT begin or end the transaction, so self.con.cursor must be created
         Attribute 
@@ -524,7 +546,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
@@ -557,7 +579,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_) )