diff options
author | Federico Di Gregorio <fog@initd.org> | 2004-10-19 03:17:12 +0000 |
---|---|---|
committer | Federico Di Gregorio <fog@initd.org> | 2004-10-19 03:17:12 +0000 |
commit | c904d97f696a665958c2cc43333d09c0e6357577 (patch) | |
tree | de88cb1cb6a48230f79bc0b532835d26a33660e9 /ZPsycopgDA | |
download | psycopg2-c904d97f696a665958c2cc43333d09c0e6357577.tar.gz |
Initial psycopg 2 import after SVN crash.
Diffstat (limited to 'ZPsycopgDA')
-rw-r--r-- | ZPsycopgDA/DA.py | 202 | ||||
-rw-r--r-- | ZPsycopgDA/DABase.py | 67 | ||||
-rw-r--r-- | ZPsycopgDA/__init__.py | 32 | ||||
-rw-r--r-- | ZPsycopgDA/db.py | 209 | ||||
-rw-r--r-- | ZPsycopgDA/dtml/add.dtml | 96 | ||||
-rw-r--r-- | ZPsycopgDA/dtml/edit.dtml | 67 | ||||
-rw-r--r-- | ZPsycopgDA/icons/bin.gif | bin | 0 -> 924 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/date.gif | bin | 0 -> 930 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/datetime.gif | bin | 0 -> 925 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/field.gif | bin | 0 -> 915 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/float.gif | bin | 0 -> 929 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/int.gif | bin | 0 -> 918 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/stable.gif | bin | 0 -> 884 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/table.gif | bin | 0 -> 878 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/text.gif | bin | 0 -> 918 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/time.gif | bin | 0 -> 926 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/view.gif | bin | 0 -> 893 bytes | |||
-rw-r--r-- | ZPsycopgDA/icons/what.gif | bin | 0 -> 894 bytes | |||
-rw-r--r-- | ZPsycopgDA/pool.py | 51 |
19 files changed, 724 insertions, 0 deletions
diff --git a/ZPsycopgDA/DA.py b/ZPsycopgDA/DA.py new file mode 100644 index 0000000..b9979b7 --- /dev/null +++ b/ZPsycopgDA/DA.py @@ -0,0 +1,202 @@ +# ZPsycopgDA/DA.py - ZPsycopgDA Zope product: Database Connection +# +# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# Or, at your option this program (ZPsycopgDA) can be distributed under the +# Zope Public License (ZPL) Version 1.0, as published on the Zope web site, +# http://www.zope.org/Resources/ZPL. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. +# +# See the LICENSE file for details. + + +ALLOWED_PSYCOPG_VERSIONS = ('1.99.9',) + +import sys +import db +import DABase +import Shared.DC.ZRDB.Connection + +from db import DB +from Globals import DTMLFile +from Globals import HTMLFile +from ImageFile import ImageFile +from ExtensionClass import Base +from DateTime import DateTime + +# import psycopg and functions/singletons needed for date/time conversions + +import psycopg +from psycopg import DATETIME +from psycopg.extensions import TIME, DATE, INTERVAL +from psycopg.extensions import new_type, register_type + + + +# add a new connection to a folder + +manage_addZPsycopgConnectionForm = DTMLFile('dtml/add',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) + + + +# the connection object + +class Connection(DABase.Connection): + """ZPsycopg Connection.""" + id = 'Psycopg_database_connection' + database_type = 'Psycopg' + meta_type = title = 'Z Psycopg Database Connection' + icon = 'misc_/ZPsycopg/conn' + + def __init__(self, id, title, connection_string, + zdatetime, check=None, tilevel=2, encoding=''): + self.zdatetime = zdatetime + self.id = str(id) + self.edit(title, connection_string, zdatetime, + check=check, tilevel=tilevel, encoding=encoding) + + def factory(self): + return DB + + def table_info(self): + return self._v_database_connection.table_info() + + def edit(self, title, connection_string, + zdatetime, check=None, tilevel=2, encoding=''): + self.title = title + self.connection_string = connection_string + self.zdatetime = zdatetime + self.tilevel = tilevel + self.encoding = encoding + + self.set_type_casts() + + if check: self.connect(self.connection_string) + + manage_properties = DTMLFile('dtml/edit', globals()) + + def manage_edit(self, title, connection_string, + zdatetime=None, check=None, tilevel=2, encoding='UTF-8', + REQUEST=None): + """Edit the DB connection.""" + self.edit(title, connection_string, zdatetime, + check=check, tilevel=tilevel, encoding=encoding) + if REQUEST is not None: + msg = "Connection edited." + return self.manage_main(self,REQUEST,manage_tabs_message=msg) + + 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 ALLOWED_PSYCOPG_VERSIONS: + raise ImportError("psycopg version mismatch (imported %s)" + + psycopg.__version__) + + self.set_type_casts() + self._v_connected = '' + dbf = self.factory() + + # TODO: let the psycopg exception propagate, or not? + self._v_database_connection = dbf( + self.connection_string, self.tilevel, self.encoding) + self._v_database_connection.open() + self._v_connected = DateTime() + + return self + + def set_type_casts(self): + # note that in both cases order *is* important + if self.zdatetime: + # use zope internal datetime routines + register_type(ZDATETIME) + register_type(ZDATE) + register_type(ZTIME) + register_type(ZINTERVAL) + else: + # use the standard + register_type(DATETIME) + register_type(DATE) + register_type(TIME) + register_type(INTERVAL) + +# database connection registration data + +classes = (Connection,) + +meta_types = ({'name':'Z Psycopg Database Connection', + 'action':'manage_addZPsycopgConnectionForm'},) + +folder_methods = { + 'manage_addZPsycopgConnection': manage_addZPsycopgConnection, + 'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm} + +__ac_permissions__ = ( + ('Add Z Psycopg Database Connections', + ('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),) + +# add icons + +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()) + +# zope-specific psycopg typecasters + +# convert an ISO timestamp string from postgres to a Zope DateTime 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] + return DateTime(join(dt[:2], ' ')) + else: + return DateTime(dt[0]) + +# convert an ISO date string from postgres to a Zope DateTime object +def _cast_Date(str): + if str: + return DateTime(str) + +# Convert a time string from postgres to a Zope DateTime object. +# NOTE: 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:])) + +# TODO: DateTime does not support intervals: what's the best we can do? +def _cast_Interval(str): + return str + +ZDATETIME = new_type((1184, 1114), "ZDATETIME", _cast_DateTime) +ZINTERVAL = new_type((1186,), "ZINTERVAL", _cast_Interval) +ZDATE = new_type((1082,), "ZDATE", _cast_Date) +ZTIME = new_type((1083,), "ZTIME", _cast_Time) + diff --git a/ZPsycopgDA/DABase.py b/ZPsycopgDA/DABase.py new file mode 100644 index 0000000..03102c3 --- /dev/null +++ b/ZPsycopgDA/DABase.py @@ -0,0 +1,67 @@ +# ZPsycopgDA/DABase.py - ZPsycopgDA Zope product: Database inspection +# +# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# Or, at your option this program (ZPsycopgDA) can be distributed under the +# Zope Public License (ZPL) Version 1.0, as published on the Zope web site, +# http://www.zope.org/Resources/ZPL. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. +# +# See the LICENSE file for details. + +import sys +import Shared.DC.ZRDB.Connection + +from db import DB +from Globals import HTMLFile +from ImageFile import ImageFile +from ExtensionClass import Base +from DateTime import DateTime + +# import psycopg and functions/singletons needed for date/time conversions + +import psycopg +from psycopg.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN +from psycopg import NUMBER, STRING, ROWID, DATETIME + + + +class Connection(Shared.DC.ZRDB.Connection.Connection): + _isAnSQLConnection = 1 + + info = None + + #manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + ( + # {'label': 'Browse', 'action':'manage_browse'},) + + #manage_tables = HTMLFile('tables', globals()) + #manage_browse = HTMLFile('browse',globals()) + + def __getitem__(self, name): + if name == 'tableNamed': + if not hasattr(self, '_v_tables'): self.tpValues() + return self._v_tables.__of__(self) + raise KeyError, name + + + ## old stuff from ZPsycopgDA 1.1 (never implemented) ## + + def manage_wizard(self, tables): + "Wizard of what? Oozing?" + + def manage_join(self, tables, select_cols, join_cols, REQUEST=None): + """Create an SQL join""" + + def manage_insert(self, table, cols, REQUEST=None): + """Create an SQL insert""" + + def manage_update(self, table, keys, cols, REQUEST=None): + """Create an SQL update""" diff --git a/ZPsycopgDA/__init__.py b/ZPsycopgDA/__init__.py new file mode 100644 index 0000000..b0e2a45 --- /dev/null +++ b/ZPsycopgDA/__init__.py @@ -0,0 +1,32 @@ +# ZPsycopgDA/__init__.py - ZPsycopgDA Zope product +# +# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# Or, at your option this program (ZPsycopgDA) can be distributed under the +# Zope Public License (ZPL) Version 1.0, as published on the Zope web site, +# http://www.zope.org/Resources/ZPL. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. +# +# See the LICENSE file for details. + +__doc__ = "ZPsycopg Database Adalper Registration." +__version__ = '2.0' + +import sys +import string +import DA + +methods = DA.folder_methods +classes = DA.classes +meta_types = DA.meta_types +misc_ = DA.misc_ + +__ac_permissions__=DA.__ac_permissions__ diff --git a/ZPsycopgDA/db.py b/ZPsycopgDA/db.py new file mode 100644 index 0000000..c859535 --- /dev/null +++ b/ZPsycopgDA/db.py @@ -0,0 +1,209 @@ +# ZPsycopgDA/db.py - query execution +# +# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# Or, at your option this program (ZPsycopgDA) can be distributed under the +# Zope Public License (ZPL) Version 1.0, as published on the Zope web site, +# http://www.zope.org/Resources/ZPL. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. +# +# See the LICENSE file for details. + +from Shared.DC.ZRDB.TM import TM +from Shared.DC.ZRDB import dbi_db + +from ZODB.POSException import ConflictError + +import time +import site +import pool + +import psycopg +from psycopg.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN +from psycopg import NUMBER, STRING, ROWID, DATETIME + + + +# the DB object, managing all the real query work + +class DB(TM, dbi_db.DB): + + _p_oid = _p_changed = _registered = None + + def __init__(self, dsn, tilevel, enc='utf-8'): + self.dsn = dsn + self.tilevel = tilevel + self.encoding = enc + self.failures = 0 + self.calls = 0 + + def getconn(self, create=True): + conn = pool.getconn(self.dsn) + conn.set_isolation_level(int(self.tilevel)) + return conn + + def putconn(self, close=False): + try: + conn = pool.getconn(self.dsn, False) + except AttributeError: + pass + pool.putconn(self.dsn, conn, close) + + def getcursor(self): + conn = self.getconn() + return conn.cursor() + + def _finish(self, *ignored): + try: + conn = self.getconn(False) + conn.commit() + self.putconn() + except AttributeError: + pass + + def _abort(self, *ignored): + try: + conn = self.getconn(False) + conn.rollback() + self.putconn() + except AttributeError: + pass + + def open(self): + # this will create a new pool for our DSN if not already existing, + # then get and immediately release a connection + self.getconn() + self.putconn() + + def close(self): + # FIXME: if this connection is closed we flush all the pool associated + # with the current DSN; does this makes sense? + pool.flushpool(self.dsn) + + def sortKey(self): + return 1 + + ## tables and rows ## + + def tables(self, rdb=0, _care=('TABLE', 'VIEW')): + self._register() + c = self.getcursor() + c.execute( + "SELECT t.tablename AS NAME, 'TABLE' AS TYPE " + " FROM pg_tables t WHERE tableowner <> 'postgres' " + "UNION SELECT v.viewname AS NAME, 'VIEW' AS TYPE " + " FROM pg_views v WHERE viewowner <> 'postgres' " + "UNION SELECT t.tablename AS NAME, 'SYSTEM_TABLE\' AS TYPE " + " FROM pg_tables t WHERE tableowner = 'postgres' " + "UNION SELECT v.viewname AS NAME, 'SYSTEM_TABLE' AS TYPE " + "FROM pg_views v WHERE viewowner = 'postgres'") + res = [] + for name, typ in c.fetchall(): + if typ in _care: + res.append({'TABLE_NAME': name, 'TABLE_TYPE': typ}) + self.putconn() + return res + + def columns(self, table_name): + self._register() + c = self.getcursor() + try: + r = c.execute('SELECT * FROM "%s" WHERE 1=0' % table_name) + except: + return () + res = [] + for name, type, width, ds, p, scale, null_ok in c.description: + if type == NUMBER: + if type == INTEGER: + type = INTEGER + elif type == FLOAT: + type = FLOAT + else: type = NUMBER + elif type == BOOLEAN: + type = BOOLEAN + elif type == ROWID: + type = ROWID + elif type == DATETIME: + type = DATETIME + else: + type = STRING + + res.append({'Name': name, + 'Type': type.name, + 'Precision': 0, + 'Scale': 0, + 'Nullable': 0}) + self.putconn() + return res + + ## query execution ## + + def query(self, query_string, max_rows=None, query_data=None): + self._register() + self.calls = self.calls+1 + + desc = () + res = [] + nselects = 0 + + c = self.getcursor() + + try: + for qs in [x for x in query_string.split('\0') if x]: + if type(qs) == unicode: + if self.encoding: + qs = qs.encode(self.encoding) + try: + if (query_data): + c.execute(qs, query_data) + else: + c.execute(qs) + except (psycopg.ProgrammingError, psycopg.IntegrityError), e: + if e.args[0].find("concurrent update") > -1: + raise ConflictError + raise e + if c.description is not None: + nselects += 1 + if c.description != desc and nselects > 1: + raise psycopg.ProgrammingError( + 'multiple selects in single query not allowed') + if max_rows: + res = c.fetchmany(max_rows) + else: + res = c.fetchall() + desc = c.description + self.failures = 0 + + except StandardError, err: + self._abort() + raise err + + items = [] + for name, typ, width, ds, p, scale, null_ok in desc: + if typ == NUMBER: + if typ == INTEGER or typ == LONGINTEGER: typs = 'i' + else: typs = 'n' + elif typ == BOOLEAN: + typs = 'n' + elif typ == ROWID: + typs = 'i' + elif typ == DATETIME: + typs = 'd' + else: + typs = 's' + items.append({ + 'name': name, + 'type': typs, + 'width': width, + 'null': null_ok, + }) + + return items, res diff --git a/ZPsycopgDA/dtml/add.dtml b/ZPsycopgDA/dtml/add.dtml new file mode 100644 index 0000000..d138779 --- /dev/null +++ b/ZPsycopgDA/dtml/add.dtml @@ -0,0 +1,96 @@ +<dtml-var manage_page_header> + +<dtml-var "manage_form_title(this(), _, + form_title='Add Z Psycopg Database Connection', + help_product='ZPsycopgDA', + help_topic='ZPsycopgDA-Method-Add.stx' + )"> + +<p class="form-help"> +A Zope Psycopg Database Connection is used to connect and execute +queries on a PostgreSQL database. +</p> + +<p class="form-help"> +In the form below <em>Connection String</em> (also called the Data Source Name +or DSN for short) is a string... (TODO: finish docs) +</p> + +<form action="manage_addZPsycopgConnection" method="POST"> +<table cellspacing="0" cellpadding="2" border="0"> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Id + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="id" size="40" + value="Psycopg_database_connection" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-optional"> + Title + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="title" size="40" + value="Z Psycopg Database Connection"/> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Connection string + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="connection_string" size="40" value="" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Connect immediately + </div> + </td> + <td align="left" valign="top"> + <input type="checkbox" name="check" value="YES" checked="YES" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Use Zope's internal DateTime + </div> + </td> + <td align="left" valign="top"> + <input type="checkbox" name="zdatetime" value="YES" checked="YES" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Transaction isolation level + </div> + </td> + <td align="left" valign="top"> + <select name="tilevel:int"> + <option value="1">Read committed</option> + <option value="2" selected="YES">Serializable</option> + </select> + </td> + </tr> + <tr> + <td align="left" valign="top" colspan="2"> + <div class="form-element"> + <input class="form-element" type="submit" name="submit" value=" Add " /> + </div> + </td> + </tr> +</table> +</form> + +<dtml-var manage_page_footer> diff --git a/ZPsycopgDA/dtml/edit.dtml b/ZPsycopgDA/dtml/edit.dtml new file mode 100644 index 0000000..45275ed --- /dev/null +++ b/ZPsycopgDA/dtml/edit.dtml @@ -0,0 +1,67 @@ +<dtml-var manage_page_header> +<dtml-var manage_tabs> + +<form action="manage_edit" method="POST"> +<table cellspacing="0" cellpadding="2" border="0"> + <tr> + <td align="left" valign="top"> + <div class="form-optional"> + Title + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="title" size="40" + value="&dtml-title;"/> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Connection string + </div> + </td> + <td align="left" valign="top"> + <input type="text" name="connection_string" size="40" + value="&dtml-connection_string;" /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Use Zope's internal DateTime + </div> + </td> + <td align="left" valign="top"> + <input type="checkbox" name="zdatetime" value="YES" + <dtml-if expr="zdatetime">checked="YES"</dtml-if> /> + </td> + </tr> + <tr> + <td align="left" valign="top"> + <div class="form-label"> + Transaction isolation level + </div> + </td> + <td align="left" valign="top"> + <select name="tilevel:int"> + <option value="1" + <dtml-if expr="tilevel==1">selected="YES"</dtml-if">> + Read committed</option> + <option value="2" + <dtml-if expr="tilevel==2">selected="YES"</dtml-if">> + Serializable</option> + </select> + </td> + </tr> + <tr> + <td align="left" valign="top" colspan="2"> + <div class="form-element"> + <input class="form-element" type="submit" name="submit" + value=" Save Changes " /> + </div> + </td> + </tr> +</table> +</form> + +<dtml-var manage_page_footer> diff --git a/ZPsycopgDA/icons/bin.gif b/ZPsycopgDA/icons/bin.gif Binary files differnew file mode 100644 index 0000000..fa4fdd0 --- /dev/null +++ b/ZPsycopgDA/icons/bin.gif diff --git a/ZPsycopgDA/icons/date.gif b/ZPsycopgDA/icons/date.gif Binary files differnew file mode 100644 index 0000000..0d88a57 --- /dev/null +++ b/ZPsycopgDA/icons/date.gif diff --git a/ZPsycopgDA/icons/datetime.gif b/ZPsycopgDA/icons/datetime.gif Binary files differnew file mode 100644 index 0000000..faa540b --- /dev/null +++ b/ZPsycopgDA/icons/datetime.gif diff --git a/ZPsycopgDA/icons/field.gif b/ZPsycopgDA/icons/field.gif Binary files differnew file mode 100644 index 0000000..9bf8692 --- /dev/null +++ b/ZPsycopgDA/icons/field.gif diff --git a/ZPsycopgDA/icons/float.gif b/ZPsycopgDA/icons/float.gif Binary files differnew file mode 100644 index 0000000..efc5c78 --- /dev/null +++ b/ZPsycopgDA/icons/float.gif diff --git a/ZPsycopgDA/icons/int.gif b/ZPsycopgDA/icons/int.gif Binary files differnew file mode 100644 index 0000000..5ee3ced --- /dev/null +++ b/ZPsycopgDA/icons/int.gif diff --git a/ZPsycopgDA/icons/stable.gif b/ZPsycopgDA/icons/stable.gif Binary files differnew file mode 100644 index 0000000..acdd37d --- /dev/null +++ b/ZPsycopgDA/icons/stable.gif diff --git a/ZPsycopgDA/icons/table.gif b/ZPsycopgDA/icons/table.gif Binary files differnew file mode 100644 index 0000000..4fb32d9 --- /dev/null +++ b/ZPsycopgDA/icons/table.gif diff --git a/ZPsycopgDA/icons/text.gif b/ZPsycopgDA/icons/text.gif Binary files differnew file mode 100644 index 0000000..c9d5365 --- /dev/null +++ b/ZPsycopgDA/icons/text.gif diff --git a/ZPsycopgDA/icons/time.gif b/ZPsycopgDA/icons/time.gif Binary files differnew file mode 100644 index 0000000..6d08915 --- /dev/null +++ b/ZPsycopgDA/icons/time.gif diff --git a/ZPsycopgDA/icons/view.gif b/ZPsycopgDA/icons/view.gif Binary files differnew file mode 100644 index 0000000..71b30de --- /dev/null +++ b/ZPsycopgDA/icons/view.gif diff --git a/ZPsycopgDA/icons/what.gif b/ZPsycopgDA/icons/what.gif Binary files differnew file mode 100644 index 0000000..0214a4d --- /dev/null +++ b/ZPsycopgDA/icons/what.gif diff --git a/ZPsycopgDA/pool.py b/ZPsycopgDA/pool.py new file mode 100644 index 0000000..8cc7fa7 --- /dev/null +++ b/ZPsycopgDA/pool.py @@ -0,0 +1,51 @@ +# ZPsycopgDA/pool.py - ZPsycopgDA Zope product: connection pooling +# +# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# Or, at your option this program (ZPsycopgDA) can be distributed under the +# Zope Public License (ZPL) Version 1.0, as published on the Zope web site, +# http://www.zope.org/Resources/ZPL. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. +# +# See the LICENSE file for details. + +# all the connections are held in a pool of pools, directly accessible by the +# ZPsycopgDA code in db.py + +import threading +import psycopg.pool + +_connections_pool = {} +_connections_lock = threading.Lock() + +def getpool(dsn, create=True): + _connections_lock.acquire() + try: + if not _connections_pool.has_key(dsn) and create: + _connections_pool[dsn] = \ + psycopg.pool.ThreadedConnectionPool(4, 200, dsn) + finally: + _connections_lock.release() + return _connections_pool[dsn] + +def flushpool(dsn): + _connections_lock.acquire() + try: + _connections_pool[dsn].closeall() + del _connections_pool[dsn] + finally: + _connections_lock.release() + +def getconn(dsn, create=True): + return getpool(dsn, create=create).getconn() + +def putconn(dsn, conn, close=False): + getpool(dsn).putconn(conn, close=close) |