############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## database_type='Psycopg' __doc__='''%s Database Connection $Id: DA.py 906 2005-10-01 00:11:58Z fog $''' % database_type __version__='$Revision: 1.20.2.14 $'[11:-2] __psycopg_versions__ = ('1.1.17','1.1.18', '1.1.19', '1.1.20', '1.1.21') from db import DB import Shared.DC.ZRDB.Connection, sys, DABase, time from Globals import HTMLFile, ImageFile from ExtensionClass import Base from string import find, join, split, rindex try: import psycopg from psycopg import new_type, register_type, \ DATETIME, TIME, DATE, INTERVAL, STRING except StandardError, err: print err try: from DateTime import DateTime except StandardError, err: print err try: from App.Dialogs import MessageDialog except: pass import time manage_addZPsycopgConnectionForm = HTMLFile('connectionAdd', globals()) def manage_addZPsycopgConnection(self, id, title, connection_string, zdatetime=None, tilevel=2, check=None, REQUEST=None): """Add a DB connection to a folder""" self._setObject(id, Connection(id, title, connection_string, zdatetime, check, tilevel)) if REQUEST is not None: return self.manage_main(self,REQUEST) # Convert an ISO timestamp string from postgres to a DateTime (zope version) # object. def cast_DateTime(str): if str: # this will split us into [date, time, GMT/AM/PM(if there)] dt = split(str, ' ') if len(dt) > 1: # we now should split out any timezone info dt[1] = split(dt[1], '-')[0] dt[1] = split(dt[1], '+')[0] s = split(join(dt[:2], ' '), '.')[0] else: s = dt[0] if s =='infinity': return 'infinity' elif s == '-infinity': return '-infinity' else: return DateTime(s) # Convert an ISO date string from postgres to a DateTime(zope version) # object. def cast_Date(str): if str == 'infinity': return 'infinity' elif str == '-infinity': return '-infinity' elif str: return DateTime(str) # Convert a time string from postgres to a DateTime(zope version) object. # WARNING: We set the day as today before feeding to DateTime so # that it has the same DST settings. def cast_Time(str): if str: return DateTime(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())[:3]+ time.strptime(str[:8], "%H:%M:%S")[3:])) # Convert a time string from postgres to a DateTime(zope version) object. # WARNING: We set the day as the epoch day (1970-01-01) since this # DateTime does not support time deltas. (EXPERIMENTAL USE WITH CARE!) def cast_Interval(str): return str # Convert a string to Unicode. Factory function as we depend on the encoding. def cast_String_factory(encoding): def cast_String(s): if s is not None: return unicode(s, encoding) else: return s return cast_String class Connection(DABase.Connection): "The connection class." database_type = database_type id = '%s_database_connection' % database_type meta_type = title = 'Z %s Database Connection' % database_type icon = 'misc_/Z%sDA/conn' % database_type def __init__(self, id, title, connection_string, zdatetime, check=None, tilevel=2, encoding='UTF-8', ustrings=0): self.zdatetime=zdatetime self.id=str(id) self.edit(title, connection_string, zdatetime, check=check, tilevel=tilevel, encoding=encoding, ustrings=ustrings) def edit(self, title, connection_string, zdatetime, check=1, tilevel=2, encoding='UTF-8', ustrings=0): self.title=title self.connection_string=connection_string self.zdatetime=zdatetime self.tilevel=tilevel self.encoding=encoding self.ustrings=ustrings self.set_type_casts() if check: self.connect(connection_string) manage_properties=HTMLFile('connectionEdit', globals()) def manage_edit(self, title, connection_string, zdatetime=None, check=None, tilevel=2, encoding='UTF-8', ustrings=0, REQUEST=None): """Change connection """ self.edit(title, connection_string, zdatetime, check=check, tilevel=tilevel, encoding=encoding, ustrings=ustrings) if REQUEST is not None: return MessageDialog( title='Edited', message='%s has been edited.' % self.id, action ='./manage_main', ) def set_type_casts(self): "Make changes to psycopg default typecast list" if self.zdatetime: #use zope internal datetime routines ZDATETIME=new_type((1184,1114), "ZDATETIME", cast_DateTime) ZDATE=new_type((1082,), "ZDATE", cast_Date) ZTIME=new_type((1083,), "ZTIME", cast_Time) ZINTERVAL=new_type((1186,), "ZINTERVAL", cast_Interval) register_type(ZDATETIME) register_type(ZDATE) register_type(ZTIME) register_type(ZINTERVAL) else: #use the standard. WARN: order is important! register_type(DATETIME) register_type(DATE) register_type(TIME) register_type(INTERVAL) if getattr(self, "ustrings", 0) and self.encoding: USTRING = psycopg.new_type(psycopg.STRING.values, "USTRING", cast_String_factory(self.encoding)) register_type(USTRING) else: register_type(STRING) def factory(self): return DB def table_info(self): return self._v_database_connection.table_info() def connect(self,s): try: self._v_database_connection.close() except: pass # check psycopg version and raise exception if does not match if psycopg.__version__ not in __psycopg_versions__: raise ImportError("psycopg version mismatch: " + psycopg.__version__) self.set_type_casts() self._v_connected='' DB=self.factory() try: try: # this is necessary when upgrading from old installs without # having to recreate the connection object if not hasattr(self, 'tilevel'): self.tilevel = 2 if not hasattr(self, 'encoding'): self.encoding = 'UTF-8' if not hasattr(self, 'ustrings'): self.ustrings = 0 self._v_database_connection=DB(s, self.tilevel, self.encoding) except: t, v, tb = sys.exc_info() raise 'BadRequest', ( 'Could not open connection.
' 'Connection string:
%s
\n' '
\n%s\n%s\n
\n' % (s,t,v)), tb finally: tb=None self._v_connected=DateTime() return self def sql_quote__(self, v): # quote dictionary quote_dict = {"\'": "''", "\\": "\\\\"} for dkey in quote_dict.keys(): if find(v, dkey) >= 0: v=join(split(v,dkey),quote_dict[dkey]) return "'%s'" % v classes = ('DA.Connection',) meta_types=( {'name':'Z %s Database Connection' % database_type, 'action':'manage_addZ%sConnectionForm' % database_type},) folder_methods={ 'manage_addZPsycopgConnection': manage_addZPsycopgConnection, 'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm} __ac_permissions__=( ('Add Z Psycopg Database Connections', ('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),) misc_={ 'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')} for icon in ('table', 'view', 'stable', 'what', 'field', 'text','bin','int','float', 'date','time','datetime'): misc_[icon] = ImageFile('icons/%s.gif' % icon, globals())