Setting tag plcapi-5.4-2
[plcapi.git] / PLC / PostgreSQL.py
index 09132e2..e04b02b 100644 (file)
@@ -1,13 +1,10 @@
 #
 #
-# PostgreSQL database interface. Sort of like DBI(3) (Database
-# independent interface for Perl).
+# PostgreSQL database interface. 
+# Sort of like DBI(3) (Database independent interface for Perl).
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
-# $URL$
-#
 
 import psycopg2
 import psycopg2.extensions
 
 import psycopg2
 import psycopg2.extensions
@@ -15,15 +12,17 @@ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
 # UNICODEARRAY not exported yet
 psycopg2.extensions.register_type(psycopg2._psycopg.UNICODEARRAY)
 
 # UNICODEARRAY not exported yet
 psycopg2.extensions.register_type(psycopg2._psycopg.UNICODEARRAY)
 
-import pgdb
+import types
 from types import StringTypes, NoneType
 import traceback
 import commands
 import re
 from pprint import pformat
 
 from types import StringTypes, NoneType
 import traceback
 import commands
 import re
 from pprint import pformat
 
-from PLC.Debug import profile, log
+from PLC.Logger import logger
+from PLC.Debug import profile
 from PLC.Faults import *
 from PLC.Faults import *
+from datetime import datetime as DateTimeType
 
 class PostgreSQL:
     def __init__(self, api):
 
 class PostgreSQL:
     def __init__(self, api):
@@ -59,23 +58,50 @@ class PostgreSQL:
             self.connection.close()
             self.connection = None
 
             self.connection.close()
             self.connection = None
 
-    # join insists on getting strings
-    @classmethod
-    def quote_string(self, value):
-        return str(PostgreSQL.quote(value))
+    @staticmethod
+    # From pgdb, and simplify code
+    def _quote(x):
+        if isinstance(x, DateTimeType):
+            x = str(x)
+        elif isinstance(x, unicode):
+            x = x.encode( 'utf-8' )
+    
+        if isinstance(x, types.StringType):
+            x = "'%s'" % str(x).replace("\\", "\\\\").replace("'", "''")
+        elif isinstance(x, (types.IntType, types.LongType, types.FloatType)):
+            pass
+        elif x is None:
+            x = 'NULL'
+        elif isinstance(x, (types.ListType, types.TupleType, set)):
+            x = 'ARRAY[%s]' % ', '.join(map(lambda x: str(_quote(x)), x))
+        elif hasattr(x, '__pg_repr__'):
+            x = x.__pg_repr__()
+        else:
+            raise PLCDBError, 'Cannot quote type %s' % type(x)
+        return x
+
 
 
-    @classmethod
     def quote(self, value):
         """
         Returns quoted version of the specified value.
         """
     def quote(self, value):
         """
         Returns quoted version of the specified value.
         """
-
-        # The pgdb._quote function is good enough for general SQL
-        # quoting, except for array types.
-        if isinstance(value, (list, tuple, set)):
-            return "ARRAY[%s]" % ", ".join(map (PostgreSQL.quote_string, value))
-        else:
-            return pgdb._quote(value)
+        return PostgreSQL._quote (value)
+
+# following is an unsuccessful attempt to re-use lib code as much as possible
+#    def quote(self, value):
+#        # The pgdb._quote function is good enough for general SQL
+#        # quoting, except for array types.
+#        if isinstance (value, (types.ListType, types.TupleType, set)):
+#            'ARRAY[%s]' % ', '.join( [ str(self.quote(x)) for x in value ] )
+#        else:
+#            try:
+#                # up to PyGreSQL-3.x, function was pgdb._quote
+#                import pgdb
+#                return pgdb._quote(value)
+#            except:
+#                # with PyGreSQL-4.x, use psycopg2's adapt
+#                from psycopg2.extensions import adapt
+#                return adapt (value)
 
     @classmethod
     def param(self, name, value):
 
     @classmethod
     def param(self, name, value):
@@ -110,13 +136,13 @@ class PostgreSQL:
         return self.rowcount
 
     def next_id(self, table_name, primary_key):
         return self.rowcount
 
     def next_id(self, table_name, primary_key):
-       sequence = "%(table_name)s_%(primary_key)s_seq" % locals()      
-       sql = "SELECT nextval('%(sequence)s')" % locals()
-       rows = self.selectall(sql, hashref = False)
-       if rows: 
-           return rows[0][0]
-               
-       return None 
+        sequence = "%(table_name)s_%(primary_key)s_seq" % locals()
+        sql = "SELECT nextval('%(sequence)s')" % locals()
+        rows = self.selectall(sql, hashref = False)
+        if rows:
+            return rows[0][0]
+
+        return None
 
     def last_insert_id(self, table_name, primary_key):
         if isinstance(self.lastrowid, int):
 
     def last_insert_id(self, table_name, primary_key):
         if isinstance(self.lastrowid, int):
@@ -128,7 +154,7 @@ class PostgreSQL:
 
         return None
 
 
         return None
 
-    # modified for psycopg2-2.0.7 
+    # modified for psycopg2-2.0.7
     # executemany is undefined for SELECT's
     # see http://www.python.org/dev/peps/pep-0249/
     # accepts either None, a single dict, a tuple of single dict - in which case it execute's
     # executemany is undefined for SELECT's
     # see http://www.python.org/dev/peps/pep-0249/
     # accepts either None, a single dict, a tuple of single dict - in which case it execute's
@@ -150,21 +176,22 @@ class PostgreSQL:
 
             if not params:
                 if self.debug:
 
             if not params:
                 if self.debug:
-                    print >> log,'execute0',query
+                    logger.debug('execute0: {}'.format(query))
                 cursor.execute(query)
                 cursor.execute(query)
-            elif isinstance(params,dict):
+            elif isinstance(params, dict):
                 if self.debug:
                 if self.debug:
-                    print >> log,'execute-dict: params',params,'query',query%params
-                cursor.execute(query,params)
+                    logger.debug('execute-dict: params {} query {}'
+                                 .format(params, query%params))
+                cursor.execute(query, params)
             elif isinstance(params,tuple) and len(params)==1:
                 if self.debug:
             elif isinstance(params,tuple) and len(params)==1:
                 if self.debug:
-                    print >> log,'execute-tuple',query%params[0]
+                    logger.debug('execute-tuple {}'.format(query%params[0]))
                 cursor.execute(query,params[0])
             else:
                 param_seq=(params,)
                 if self.debug:
                     for params in param_seq:
                 cursor.execute(query,params[0])
             else:
                 param_seq=(params,)
                 if self.debug:
                     for params in param_seq:
-                        print >> log,'executemany',query%params
+                        logger.debug('executemany {}'.format(query%params))
                 cursor.executemany(query, param_seq)
             (self.rowcount, self.description, self.lastrowid) = \
                             (cursor.rowcount, cursor.description, cursor.lastrowid)
                 cursor.executemany(query, param_seq)
             (self.rowcount, self.description, self.lastrowid) = \
                             (cursor.rowcount, cursor.description, cursor.lastrowid)
@@ -174,12 +201,8 @@ class PostgreSQL:
             except:
                 pass
             uuid = commands.getoutput("uuidgen")
             except:
                 pass
             uuid = commands.getoutput("uuidgen")
-            print >> log, "Database error %s:" % uuid
-            print >> log, e
-            print >> log, "Query:"
-            print >> log, query
-            print >> log, "Params:"
-            print >> log, pformat(params)
+            message = "Database error {}: - Query {} - Params {}".format(uuid, query, pformat(params))
+            logger.exception(message)
             raise PLCDBError("Please contact " + \
                              self.api.config.PLC_NAME + " Support " + \
                              "<" + self.api.config.PLC_MAIL_SUPPORT_ADDRESS + ">" + \
             raise PLCDBError("Please contact " + \
                              self.api.config.PLC_NAME + " Support " + \
                              "<" + self.api.config.PLC_MAIL_SUPPORT_ADDRESS + ">" + \