SVN repo up to date (1.1.16pre1).
							
								
								
									
										5
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						|  | @ -1,8 +1,9 @@ | |||
| Main authors: | ||||
|   Michele Comitini <mcm@initd.org> | ||||
|   Federico Di Gregorio <fog@debian.org> | ||||
| 
 | ||||
| For the win32 port: | ||||
|   Jason Erickson <jerickso@indian.com> (most of his changes are still in 2.0) | ||||
|   Jason Erickson <jerickso@indian.com> | ||||
| 
 | ||||
| Additional Help: | ||||
|    | ||||
|   Tom Jenkins <tjenkins@devis.com> (COPY FROM/COPY TO backport) | ||||
|  |  | |||
							
								
								
									
										190
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						|  | @ -1,18 +1,184 @@ | |||
| Compiling and installing psycopg | ||||
| ******************************** | ||||
| Basic Installation | ||||
| ================== | ||||
| 
 | ||||
| While psycopg 1.x used autoconf for its build process psycopg 2 switched to | ||||
| the more pythoning setup.py. Currently both psycopg's author and distutils | ||||
| have some limitations so the file setup.cfg is almost unused and most build | ||||
| options are hidden in setup.py. Before building psycopg look at the very | ||||
| first lines of setup.py and change any settings to follow your system (or | ||||
| taste); then: | ||||
|    These are generic installation instructions. Before building and | ||||
| installing make sure you read carefully the "Install" section in the | ||||
| README file.  | ||||
| 
 | ||||
|     python setup.py build | ||||
|    The `configure' shell script attempts to guess correct values for | ||||
| various system-dependent variables used during compilation.  It uses | ||||
| those values to create a `Makefile' in each directory of the package. | ||||
| It may also create one or more `.h' files containing system-dependent | ||||
| definitions.  Finally, it creates a shell script `config.status' that | ||||
| you can run in the future to recreate the current configuration, a file | ||||
| `config.cache' that saves the results of its tests to speed up | ||||
| reconfiguring, and a file `config.log' containing compiler output | ||||
| (useful mainly for debugging `configure'). | ||||
| 
 | ||||
| to build in the local directory; and: | ||||
|    If you need to do unusual things to compile the package, please try | ||||
| to figure out how `configure' could check whether to do them, and mail | ||||
| diffs or instructions to the address given in the `README' so they can | ||||
| be considered for the next release.  If at some point `config.cache' | ||||
| contains results you don't want to keep, you may remove or edit it. | ||||
| 
 | ||||
|     python setup.py install | ||||
|    The file `configure.in' is used to create `configure' by a program | ||||
| called `autoconf'.  You only need `configure.in' if you want to change | ||||
| it or regenerate `configure' using a newer version of `autoconf'. | ||||
| 
 | ||||
| to install system-wide. | ||||
| The simplest way to compile this package is: | ||||
| 
 | ||||
|   1. `cd' to the directory containing the package's source code and type | ||||
|      `./configure' to configure the package for your system.  If you're | ||||
|      using `csh' on an old version of System V, you might need to type | ||||
|      `sh ./configure' instead to prevent `csh' from trying to execute | ||||
|      `configure' itself. | ||||
| 
 | ||||
|      Running `configure' takes awhile.  While running, it prints some | ||||
|      messages telling which features it is checking for. | ||||
| 
 | ||||
|   2. Type `make' to compile the package. | ||||
| 
 | ||||
|   3. Optionally, type `make check' to run any self-tests that come with | ||||
|      the package. | ||||
| 
 | ||||
|   4. Type `make install' to install the programs and any data files and | ||||
|      documentation. | ||||
| 
 | ||||
|   5. You can remove the program binaries and object files from the | ||||
|      source code directory by typing `make clean'.  To also remove the | ||||
|      files that `configure' created (so you can compile the package for | ||||
|      a different kind of computer), type `make distclean'.  There is | ||||
|      also a `make maintainer-clean' target, but that is intended mainly | ||||
|      for the package's developers.  If you use it, you may have to get | ||||
|      all sorts of other programs in order to regenerate files that came | ||||
|      with the distribution. | ||||
| 
 | ||||
| Compilers and Options | ||||
| ===================== | ||||
| 
 | ||||
|    Some systems require unusual options for compilation or linking that | ||||
| the `configure' script does not know about.  You can give `configure' | ||||
| initial values for variables by setting them in the environment.  Using | ||||
| a Bourne-compatible shell, you can do that on the command line like | ||||
| this: | ||||
|      CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure | ||||
| 
 | ||||
| Or on systems that have the `env' program, you can do it like this: | ||||
|      env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure | ||||
| 
 | ||||
| Compiling For Multiple Architectures | ||||
| ==================================== | ||||
| 
 | ||||
|    You can compile the package for more than one kind of computer at the | ||||
| same time, by placing the object files for each architecture in their | ||||
| own directory.  To do this, you must use a version of `make' that | ||||
| supports the `VPATH' variable, such as GNU `make'.  `cd' to the | ||||
| directory where you want the object files and executables to go and run | ||||
| the `configure' script.  `configure' automatically checks for the | ||||
| source code in the directory that `configure' is in and in `..'. | ||||
| 
 | ||||
|    If you have to use a `make' that does not supports the `VPATH' | ||||
| variable, you have to compile the package for one architecture at a time | ||||
| in the source code directory.  After you have installed the package for | ||||
| one architecture, use `make distclean' before reconfiguring for another | ||||
| architecture. | ||||
| 
 | ||||
| Installation Names | ||||
| ================== | ||||
| 
 | ||||
|    By default, `make install' will install the package's files in | ||||
| `/usr/local/bin', `/usr/local/man', etc.  You can specify an | ||||
| installation prefix other than `/usr/local' by giving `configure' the | ||||
| option `--prefix=PATH'. | ||||
| 
 | ||||
|    You can specify separate installation prefixes for | ||||
| architecture-specific files and architecture-independent files.  If you | ||||
| give `configure' the option `--exec-prefix=PATH', the package will use | ||||
| PATH as the prefix for installing programs and libraries. | ||||
| Documentation and other data files will still use the regular prefix. | ||||
| 
 | ||||
|    In addition, if you use an unusual directory layout you can give | ||||
| options like `--bindir=PATH' to specify different values for particular | ||||
| kinds of files.  Run `configure --help' for a list of the directories | ||||
| you can set and what kinds of files go in them. | ||||
| 
 | ||||
|    If the package supports it, you can cause programs to be installed | ||||
| with an extra prefix or suffix on their names by giving `configure' the | ||||
| option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. | ||||
| 
 | ||||
| Optional Features | ||||
| ================= | ||||
| 
 | ||||
|    Some packages pay attention to `--enable-FEATURE' options to | ||||
| `configure', where FEATURE indicates an optional part of the package. | ||||
| They may also pay attention to `--with-PACKAGE' options, where PACKAGE | ||||
| is something like `gnu-as' or `x' (for the X Window System).  The | ||||
| `README' should mention any `--enable-' and `--with-' options that the | ||||
| package recognizes. | ||||
| 
 | ||||
|    For packages that use the X Window System, `configure' can usually | ||||
| find the X include and library files automatically, but if it doesn't, | ||||
| you can use the `configure' options `--x-includes=DIR' and | ||||
| `--x-libraries=DIR' to specify their locations. | ||||
| 
 | ||||
| Specifying the System Type | ||||
| ========================== | ||||
| 
 | ||||
|    There may be some features `configure' can not figure out | ||||
| automatically, but needs to determine by the type of host the package | ||||
| will run on.  Usually `configure' can figure that out, but if it prints | ||||
| a message saying it can not guess the host type, give it the | ||||
| `--host=TYPE' option.  TYPE can either be a short name for the system | ||||
| type, such as `sun4', or a canonical name with three fields: | ||||
|      CPU-COMPANY-SYSTEM | ||||
| 
 | ||||
| See the file `config.sub' for the possible values of each field.  If | ||||
| `config.sub' isn't included in this package, then this package doesn't | ||||
| need to know the host type. | ||||
| 
 | ||||
|    If you are building compiler tools for cross-compiling, you can also | ||||
| use the `--target=TYPE' option to select the type of system they will | ||||
| produce code for and the `--build=TYPE' option to select the type of | ||||
| system on which you are compiling the package. | ||||
| 
 | ||||
| Sharing Defaults | ||||
| ================ | ||||
| 
 | ||||
|    If you want to set default values for `configure' scripts to share, | ||||
| you can create a site shell script called `config.site' that gives | ||||
| default values for variables like `CC', `cache_file', and `prefix'. | ||||
| `configure' looks for `PREFIX/share/config.site' if it exists, then | ||||
| `PREFIX/etc/config.site' if it exists.  Or, you can set the | ||||
| `CONFIG_SITE' environment variable to the location of the site script. | ||||
| A warning: not all `configure' scripts look for a site script. | ||||
| 
 | ||||
| Operation Controls | ||||
| ================== | ||||
| 
 | ||||
|    `configure' recognizes the following options to control how it | ||||
| operates. | ||||
| 
 | ||||
| `--cache-file=FILE' | ||||
|      Use and save the results of the tests in FILE instead of | ||||
|      `./config.cache'.  Set FILE to `/dev/null' to disable caching, for | ||||
|      debugging `configure'. | ||||
| 
 | ||||
| `--help' | ||||
|      Print a summary of the options to `configure', and exit. | ||||
| 
 | ||||
| `--quiet' | ||||
| `--silent' | ||||
| `-q' | ||||
|      Do not print messages saying which checks are being made.  To | ||||
|      suppress all normal output, redirect it to `/dev/null' (any error | ||||
|      messages will still be shown). | ||||
| 
 | ||||
| `--srcdir=DIR' | ||||
|      Look for the package's source code in directory DIR.  Usually | ||||
|      `configure' can determine that directory automatically. | ||||
| 
 | ||||
| `--version' | ||||
|      Print the version of Autoconf used to generate the `configure' | ||||
|      script, and exit. | ||||
| 
 | ||||
| `configure' also accepts some other, not widely useful, options. | ||||
|  |  | |||
							
								
								
									
										404
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						|  | @ -1,155 +1,355 @@ | |||
| What's new in psycopg 1.99.10 | ||||
| ----------------------------- | ||||
| psycopg news for 1.1.15 | ||||
| ----------------------- | ||||
| 
 | ||||
| * The adapt() function now fully supports the adaptation protocol | ||||
|   described in PEP 246. Note that the adapters registry now is indexed | ||||
|   by (type, protocol) and not by type alone. Change your adapters | ||||
|   accordingly. | ||||
| * Interval typecasting eventually-eventually works the Right Way (TM). | ||||
| 
 | ||||
| * More configuration options moved from setup.py to setup.cfg. | ||||
| * Fixed two bad memory leaks in QuotedString and Binary objects. | ||||
| 
 | ||||
| * Fixed two memory leaks: one in cursor deallocation and one in row | ||||
|   fetching (.fetchXXX() methods.) | ||||
| * Reverted change on rowcount attribute, now it is always set to the real | ||||
|   number of affected columns. | ||||
| 
 | ||||
| What's new in psycopg 1.99.9 | ||||
| ---------------------------- | ||||
| psycopg news for 1.1.14 | ||||
| ----------------------- | ||||
| 
 | ||||
| * Added simple pooling code (psycopg.pool module); see the reworked | ||||
|   examples/threads.py for example code. | ||||
| * Interval typecasting eventually works the Right Way (TM). | ||||
| 
 | ||||
| * Added DECIMAL typecaster to convert postgresql DECIMAL and NUMERIC | ||||
|   types (i.e, all types with an OID of NUMERICOID.) Note that the | ||||
|   DECIMAL typecaster does not set scale and precision on the created | ||||
|   objects but uses Python defaults. | ||||
| * ZPsycopgDA now support unicode strings and different backend encodings. | ||||
| 
 | ||||
| * ZPsycopgDA back in and working using the new pooling code. | ||||
| * ZPsycopgDA accept query data as an extra parameter to execute() (but | ||||
|   still no way to give it extra data from inside a ZSQL Method.) | ||||
| 
 | ||||
| * Isn't that enough? :) | ||||
| * Better DBAPI-2.0 compliance (rowcount attribute and argument passing.) | ||||
| 
 | ||||
| What's new in psycopg 1.99.8 | ||||
| ---------------------------- | ||||
| * Now builds on Fedora Core 2 (but remember that the real psycopg | ||||
|   aficionado runs on Debian ;-P ) | ||||
| 
 | ||||
| * added support for UNICODE queries. | ||||
| * COPY FROM raise an exception and return usefull information on error. | ||||
| 
 | ||||
| * added UNICODE typecaster; to activate it just do: | ||||
| psycopg news for 1.1.13 | ||||
| ----------------------- | ||||
| 
 | ||||
|     psycopg.extensions.register_type(psycopg.extensions.UNICODE) | ||||
| * ZPsycopgDA works again. | ||||
| 
 | ||||
|   Note that the UNICODE typecaster override the STRING one, so it is | ||||
|   not activated by default. | ||||
| psycopg news for 1.1.12 | ||||
| ----------------------- | ||||
| 
 | ||||
| * cursors now really support the iterator protocol. | ||||
| * Fixed nasty segfault/deadlock in switch_isolation_level. | ||||
| 
 | ||||
| * solved the rounding errors in time conversions. | ||||
| * Now the PostgreSQL TIME type is correctly converted to a DateTimeDelta | ||||
|   instead of a DateTime. This is much better because you can now add two | ||||
|   times and a time and a date. | ||||
| 
 | ||||
| * now cursors support .fileno() and .isready() methods, to be used in | ||||
|   select() calls. | ||||
| * Added an "sslmode" parameter (look at PostgreSQL documentation for | ||||
|   possible values.) | ||||
| 
 | ||||
| * .copy_from() and .copy_in() methods are back in (still using the old | ||||
|   protocol, will be updated to use new one in next releasae.) | ||||
| * .execute() now rise the right exception if called with a wrong | ||||
|    tuple/dict. Also, %% in queries does not raise an exception anymore. | ||||
| 
 | ||||
| * fixed memory corruption bug reported on win32 platform. | ||||
| * Updated RPM specs (thanks to Mark McClain we now have updated RPMs on | ||||
|   initd.org too.) | ||||
| 
 | ||||
| What's new in psycopg 1.99.7 | ||||
| ---------------------------- | ||||
| psycopg news for 1.1.11 | ||||
| ----------------------- | ||||
| 
 | ||||
| * added support for tuple factories in cursor objects (removed factory | ||||
|   argument in favor of a .tuple_factory attribute on the cursor object); | ||||
|   see the new module psycopg.extras for a cursor (DictCursor) that | ||||
|   return rows as objects that support indexing both by position and | ||||
|   column name. | ||||
| * a modern autoconf is now needed to build psycopg. | ||||
| 
 | ||||
| * added support for tzinfo objects in datetime.timestamp objects: the | ||||
|   PostgreSQL type "timestamp with time zone" is converted to  | ||||
|   datetime.timestamp with a FixedOffsetTimezone initialized as necessary. | ||||
| * now an error during commit or rollback is correctly reported by raising  | ||||
|   an exception. | ||||
| 
 | ||||
| What's new in psycopg 1.99.6 | ||||
| ---------------------------- | ||||
| * when the libpq protocol 3.0 is available, psycopg uses a smater method | ||||
|   to determine exception type (unfortunately the old string compare method | ||||
|   is still neede for postgresql <= 7.3.x.) | ||||
| 
 | ||||
| * sslmode parameter from 1.1.x | ||||
| * plugged a memory leak in copy_from(). | ||||
| 
 | ||||
| * various datetime conversion improvements. | ||||
| * where did the news for 1.1.10 go? | ||||
| 
 | ||||
| * now psycopg should compile without mx or without native datetime | ||||
|   (not both, obviously.) | ||||
| psycopg news for 1.1.9 | ||||
| ---------------------- | ||||
| 
 | ||||
| * included various win32/MSVC fixes (pthread.h changes, winsock2 | ||||
|   library, include path in setup.py, etc.) | ||||
| * psycopg distribution now includes the GeoTypes package by Richard Taylor | ||||
|   (QinetiQ Plc)! | ||||
| 
 | ||||
| * ported interval fixes from 1.1.14/1.1.15. | ||||
| * Problems with sequences and mappings non correctly used in .execute() | ||||
|   should be gone (mogrification code completely rewritten.) Many thanks | ||||
|   to Richard Taylor and Vsevolod Lobko that helped by testing the "pre" | ||||
|   releases. | ||||
| 
 | ||||
| * the last query executed by a cursor is now available in the | ||||
|   .query attribute. | ||||
| * no more libpq 7.1.x linking problems related to PQfreeNotify. | ||||
| 
 | ||||
| * conversion of unicode strings to backend encoding now uses a table | ||||
|   (that still need to be filled.) | ||||
| psycopg news for 1.1.7 | ||||
| ---------------------- | ||||
| 
 | ||||
| * cursors now have a .mogrify() method that return the query string | ||||
|   instead of executing it. | ||||
| * added notifies and fileno methods to cursor objects. | ||||
| 
 | ||||
| * connection objects now have a .dsn read-only attribute that holds the | ||||
|   connection string. | ||||
| * now execute accept any object that defined __getitem__ and not only | ||||
|   dictionaries. | ||||
| 
 | ||||
| * moved psycopg C module to _psycopg and made psycopg a python module: | ||||
|   this allows for a neat separation of DBAPI-2.0 functionality and psycopg | ||||
|   extensions; the psycopg namespace will be also used to provide | ||||
|   python-only extensions (like the pooling code, some ZPsycopgDA support | ||||
|   functions and the like.) | ||||
| * little fix in ZPsycopgDA, should work with Zope 2.7. | ||||
| 
 | ||||
| What's new in psycopg 1.99.3 | ||||
| ---------------------------- | ||||
| psycopg news for 1.1.6 | ||||
| ---------------------- | ||||
| 
 | ||||
| * added support for python 2.3 datetime types (both ways) and made datetime | ||||
|   the default set of typecasters when available. | ||||
| * cursor objects now have the .scroll() method. | ||||
| 
 | ||||
| * added example: dt.py. | ||||
| * NUL characters in strings are discarded in quoting; use a Binary object if | ||||
|   you need strings with embedded NULs. | ||||
| 
 | ||||
| What's new in psycopg 1.99.3 | ||||
| ---------------------------- | ||||
| * Fixed another MT problem in .execute(). | ||||
| 
 | ||||
| * initial working support for unicode bound variables: UTF-8 and latin-1 | ||||
|   backend encodings are natively supported (and the encoding.py example even | ||||
|   works!) | ||||
| psycopg news for 1.1.5 | ||||
| ---------------------- | ||||
| 
 | ||||
| * added .set_client_encoding() method on the connection object. | ||||
| * ZPsycopgDA now rollback before raising an exception; should be a backward | ||||
|   compatible change for people that really want to continue executing queries | ||||
|   after an exception. | ||||
| 
 | ||||
| * added examples: encoding.py, binary.py, lastrowid.py. | ||||
| * fixed problem with dictionary mogrification (i.e., specifying the same key | ||||
|   multiple times and having the None value in the dict should work now.) | ||||
| 
 | ||||
| What's new in psycopg 1.99.2 | ||||
| ---------------------------- | ||||
| * fixed keeper status trashing problem: no more psycopg stuck in transaction | ||||
|   (maybe this will also solve ZPsycopgDA problems: will see...) | ||||
| 
 | ||||
| * better typecasting: | ||||
|   - DateTimeDelta used for postgresql TIME (merge from 1.1) | ||||
|   - BYTEA now is converted to a real buffer object, not to a string | ||||
| * now copy_from and copy_to can be passed instances of classes with "readline" | ||||
|   and "write" methods and not only file instances. | ||||
|   | ||||
| * buffer objects are now adapted into Binary objects automatically. | ||||
| psycopg news for 1.1.4 | ||||
| ---------------------- | ||||
| 
 | ||||
| * ported scroll method from 1.1 (DBAPI-2.0 extension for cursors) | ||||
| * Fixed various memory leak problems. | ||||
| 
 | ||||
| * initial support for some DBAPI-2.0 extensions: | ||||
|   - .rownumber attribute for cursors | ||||
|   - .connection attribute for cursors | ||||
|   - .next() and .__iter__() methods to have cursors support the iterator | ||||
|     protocol | ||||
|   - all exception objects are exported to the connection object | ||||
| * Implemented "statusmessage" attribute on cursors. | ||||
| 
 | ||||
| What's new in psycopg 1.99.1 | ||||
| ---------------------------- | ||||
| psycopg news for 1.1.3 | ||||
| ---------------------- | ||||
| 
 | ||||
| * implemented microprotocols to adapt arbitrary types to the interface used by | ||||
|   psycopg to bind variables in execute; | ||||
| * Fixed problem with psycopg always reporting IntegrityError. | ||||
| 
 | ||||
| * moved qstring, pboolean and mxdatetime to the new adapter layout (binary is | ||||
|   still missing; python 2.3 datetime needs to be written). | ||||
| * Fixed segfault in debug statements. | ||||
| 
 | ||||
| * Now Python GIL is unlocked during PQconnectdb() calls (better | ||||
|   multithreading.) | ||||
| 
 | ||||
| What's new in psycopg 1.99.0 | ||||
| ---------------------------- | ||||
| psycopg news for 1.1.2 | ||||
| ---------------------- | ||||
| 
 | ||||
| * reorganized the whole source tree; | ||||
| * Skipped version 1.1.1 (never released 'cause of a cvs tag error) | ||||
| 
 | ||||
| * async core is in place; | ||||
| * Much better cursor.description fields (many thanks to William K. Volkman) | ||||
| 
 | ||||
| * splitted QuotedString objects from mx stuff; | ||||
| * psycopg.connect() now takes keyword parameters for host, dbname, port, | ||||
|   user and password (they are all strings, even "port".) | ||||
| 
 | ||||
| * dropped autotools and moved to pythonic setup.py (needs work.) | ||||
| * connection.set_isolation_level() implemented to help switching from default | ||||
|   isolation to other levels supported by PostgreSQL. [autocommit now simply  | ||||
|   does a set_isolation_level(0)] | ||||
| 
 | ||||
| * Implemented .lastrowid attribute for cursors. | ||||
| 
 | ||||
| * Now psycopg should build on win32/cygwin, thank to Hajime Nakagami patches. | ||||
| 
 | ||||
| * Includes every fix from 1.0.x up to 1.0.15.1: | ||||
| 
 | ||||
|   - Fixed connection-stay-open-when-i-do-conn.close() bug. | ||||
|   - Better DBAPI-2.0 compliance for setinputsizes and setoutputsize methods. | ||||
|   - Better support for build on MacOS X. | ||||
|   - Fixed problem with formats in string mogrification. | ||||
|   - Fixed other miscellaneous buglets in Zope Adapter. | ||||
|   - Fixed small memory leak in .fetchXXX() methods. | ||||
|   - Fixed serialization problem in ZPsycopgDA reported by Dieter Maurer. | ||||
| 
 | ||||
| psycopg news for 1.1 | ||||
| -------------------- | ||||
| 
 | ||||
| * COPY TO/COPY FROM implemented by Tom Jenkins | ||||
| 
 | ||||
| * Merged changes from 1.0.13. | ||||
| 
 | ||||
| psycopg news for 1.0.12 | ||||
| ----------------------- | ||||
| 
 | ||||
| * Maintenance release fixing some little buglets: | ||||
|   - Fixed memory leak in .execute(). | ||||
|   - Better configure under MacOS X. | ||||
|   - DA-browser now works even with tables with mixed-case names. | ||||
|   - timestamps time is now set to correct value instead of 0.  | ||||
| 
 | ||||
| psycopg news for 1.0.11.1 | ||||
| ------------------------- | ||||
| 
 | ||||
| * Fixed orrible bug in ZPsycopgDA not acception psycopg 1.0.11 as a valid | ||||
|   version. | ||||
| 
 | ||||
| psycopg news for 1.0.11 | ||||
| ----------------------- | ||||
| 
 | ||||
| * last problems from "None passed to typecasters" (introduced in 1.0.9) in | ||||
|   ZPsycopgDA solved (hopefully.) | ||||
| 
 | ||||
| * psycopg now reports meaningfull exception types for some errors (like | ||||
|   IntegrityError for duplicate insertions in unique indices, etc.) | ||||
| 
 | ||||
| psycopg news for 1.0.10 | ||||
| ----------------------- | ||||
| 
 | ||||
| * fixed an exception problem introduced in 1.0.9 (patch by Matt  | ||||
|   Hoskins.) | ||||
| 
 | ||||
| * ZPsycopgDA now checks psycopg version and raise an exception if it | ||||
|   does not match. | ||||
| 
 | ||||
| psycopg news for 1.0.9 | ||||
| ---------------------- | ||||
| 
 | ||||
| * fixed problem with connection left in invalid state by applying | ||||
|   Tom Jenkins patch. | ||||
| 
 | ||||
| * None values passed to the typecasters, it is now possible to | ||||
|   translate None into "" to achieve pygrsql compatibilty.  | ||||
| 
 | ||||
| * applied 'seconds as a float' patch from Jelle. | ||||
| 
 | ||||
| psycopg news for 1.0.8 | ||||
| ---------------------- | ||||
| 
 | ||||
| * fixed a segfault introduced in 1.0.7 and another little bug when | ||||
|   dealing with empty strings in QuotedString objects. | ||||
| 
 | ||||
| * Added win32 compatibility (many many thanks to Jason Erickson). | ||||
| 
 | ||||
| psycopg news for 1.0.7 | ||||
| ---------------------- | ||||
| 
 | ||||
| * Fixed little bugs in type management (infinity problems and the | ||||
|   TIMESTAMPTZ type) and Zope import. Better configure script. | ||||
| 
 | ||||
| * Now psycopg really close the physical connection to PostgreSQL on | ||||
|   connection .close(). | ||||
| 
 | ||||
| psycopg news for 1.0.5 | ||||
| ---------------------- | ||||
| 
 | ||||
| * Applied a little patch to make table browser in zope show system tables | ||||
|   correctly.  | ||||
| 
 | ||||
| * Infinity values are now converted the correct way. | ||||
| 
 | ||||
| psycopg news for 1.0.4 | ||||
| ---------------------- | ||||
| 
 | ||||
| * ZPsycopgDA does not duplicate itself anymore. | ||||
| 
 | ||||
| * Table browsing works again. | ||||
| 
 | ||||
| psycopg news for 1.0.3 | ||||
| ---------------------- | ||||
| 
 | ||||
| * bugfix for b0rken ZPsycopgDA in 1.0.2. | ||||
| 
 | ||||
| psycopg news for 1.0.2 | ||||
| ---------------------- | ||||
| 
 | ||||
| * Fixed problem with incorrect interpretation of hundredths of a second. | ||||
| 
 | ||||
| psycopg news for 1.0.1 | ||||
| ---------------------- | ||||
| 
 | ||||
| * fixed two little memory leaks, see ChangeLog for details. | ||||
| 
 | ||||
| * fixed problem with garbled passwords when using crypt autentication. | ||||
| 
 | ||||
| psycopg news for 1.0 | ||||
| -------------------- | ||||
| 
 | ||||
| * added regression tests, first result is much better conversion of date and | ||||
|   time types. | ||||
|    | ||||
| * fixed last know segfault (psycopg runs stable for a lot of people now.) | ||||
| 
 | ||||
| * psycopg compile and run on FreeBSD and MacOS X. | ||||
| 
 | ||||
| * much better binary objects, they use less memory and quoting is faster, | ||||
|   thank to the new, smarter memory allocator. | ||||
|    | ||||
| * fixed all reported buglets (mostly dbapi and type-system related.) | ||||
| 
 | ||||
| * hey, this is one-dot-oh! | ||||
| 
 | ||||
| * the following features are missing from psycopg 1.0 and will be added when | ||||
|   we have a little more time (i.e., there will be no _feature_ releases after | ||||
|   1.0, only bugfixes): | ||||
| 
 | ||||
|     - documentation is incomplete (we are slowly writing it, track CVS if you | ||||
|       want up-to-date docs) | ||||
| 
 | ||||
|     - dbapi-2.0 testsuite is incomplete (need to move code to the unittest | ||||
|       framework) | ||||
| 
 | ||||
|     - psycopg needs a full suite of regression tests to be sure we don't break | ||||
|       things while implementing new features (i think we'll add them _while_ | ||||
|       writing new features :) | ||||
| 
 | ||||
| psycopg news for 0.99.7 | ||||
| ----------------------- | ||||
| 
 | ||||
| * time intervals are correctly recognized and converted into DateTimeInterval  | ||||
|   objects.  | ||||
| 
 | ||||
| * almost complete (bugs apart) DBAPI-2.0 support. switched psycopg to use | ||||
|   QuotedString for every string passed as a bound argument. Binary now works  | ||||
|   (but still consumes lots of memory). | ||||
| 
 | ||||
| * added doc/ to hold documentation. | ||||
| 
 | ||||
| * added lastoid() method to cursor objects, to retrieve the OID of the last  | ||||
|   inserted row.  | ||||
| 
 | ||||
| psycopg news for 0.99.4 | ||||
| ----------------------- | ||||
| 
 | ||||
| * psycopg is approaching 1.0, so only DBAPI compliance patches and bug fixes | ||||
|   are getting in. | ||||
| 
 | ||||
| * added Binary and QuotedString objects. note that sometime before 1.0 we'll | ||||
|   switch turn every string passed to psycopg into a QuotedString, possibily | ||||
|   breaking Zope compatibility and old scripts doing their own quoting. | ||||
| 
 | ||||
| psycopg news for 0.5.x | ||||
| ---------------------- | ||||
| 
 | ||||
| * this is the development branch, if you want stability, stick with 0.4.6. | ||||
| 
 | ||||
| * added pthread locks so that different threads (cursors) can use the same | ||||
|   postgres connection (this was done *only* to respect the dbapi on cursor | ||||
|   isolation.) | ||||
| 
 | ||||
| * now the default for the .cursor() method is to associate every cursor to | ||||
|   the same physical connection, to avoid isolation (as the DBAPI-2.0 specify), | ||||
|   you can change that by calling the .serialize() method on the connection and | ||||
|   giving it 0 as the argument, e.g., "o.serialize(0)". | ||||
| 
 | ||||
| psycopg news for 0.4.1 | ||||
| ---------------------- | ||||
| 
 | ||||
| * autocommit mode is now supported on cursors and connections. | ||||
| 
 | ||||
| psycopg news for 0.4 | ||||
| -------------------- | ||||
| 
 | ||||
| * implemented all the remaining DBAPI-2.0 type singletons (DATETIME and | ||||
|   BINARY included) | ||||
| 
 | ||||
| psycopg news for 0.3 | ||||
| -------------------- | ||||
| 
 | ||||
| * threading problems resolved | ||||
| 
 | ||||
| * added type casting from postgres to python (the user can now specify | ||||
|   its own casting objects, the default singletons NUMBER and STRING are | ||||
|   included [and act as default cast objects] plus INTEGER and FLOAT as | ||||
|   an extension to the DBAPI-2.0.)  | ||||
|   investigate the code in examples/usercast_test.py to understand how to | ||||
|   add your own types... | ||||
| 
 | ||||
| * beginning of the Zope Database Adapter: give it a try even it it is  | ||||
|   broken! | ||||
|  |  | |||
							
								
								
									
										173
									
								
								README
									
									
									
									
									
								
							
							
						
						|  | @ -1,26 +1,145 @@ | |||
| psycopg - Python-PostgreSQL Database Adapter | ||||
| ******************************************** | ||||
| 
 | ||||
| psycopg is a PostgreSQL database adapter for the Python programming | ||||
| language. This is version 2, a complete rewrite of the original code to | ||||
| provide new-style classes for connection and cursor objects and other sweet | ||||
| candies. Like the original, psycopg 2 was written with the aim of being | ||||
| very small and fast, and stable as a rock. | ||||
| psycopg is a PostgreSQL database adapter for the Python programming language | ||||
| (just like pygresql and popy.) It was written from scratch with the aim of | ||||
| being very small and fast, and stable as a rock. The main advantages of | ||||
| psycopg are that it supports (well... *will* support) the full Python | ||||
| DBAPI-2.0 and being thread safe at level 2. | ||||
| 
 | ||||
| psycopg is different from the other database adapter because it was | ||||
| designed for heavily multi-threaded applications that create and destroy | ||||
| lots of cursors and make a conspicuous number of concurrent INSERTs or | ||||
| UPDATEs. psycopg 2 also provide full asycronous operations for the really | ||||
| brave programmer. | ||||
| psycopg is different from the other database adapter because it was designed | ||||
| for heavily multi-threaded applications that create and destroy lots of | ||||
| cursors and make a conspicuous number of concurrent INSERTs or UPDATEs.  | ||||
| Every open Python connection keeps a pool of real (UNIX or TCP/IP) connections | ||||
| to the database. Every time a new cursor is created, a new connection does not | ||||
| need to be opened; instead one of the unused connections from the pool is | ||||
| used. That makes psycopg very fast in typical client-server applications that | ||||
| create a servicing thread every time a client request arrives. | ||||
| 
 | ||||
| There are confirmed reports of psycopg 1.x compiling and running on Linux | ||||
| and FreeBSD on i386, Solaris, MacOS X and win32 architectures. psycopg 2 | ||||
| does not introduce build-wise incompatible changes so it should be able to | ||||
| compile on all architectures just as its predecessor did. | ||||
| psycopg now support the Python DBAPI-2.0 completely. There are confirmed | ||||
| reports of psycopg compiling and running on Linux and FreeBSD on i386, Solaris | ||||
| and MacOS X. | ||||
| 
 | ||||
| Now go read the INSTALL file. More information about psycopg extensions to | ||||
| the DBAPI-2.0 is available in the files located in the doc/ direcory. | ||||
| 
 | ||||
| Extensions to the Python DBAPI-2.0 | ||||
| ---------------------------------- | ||||
| 
 | ||||
| psycopg offers some little extensions on the Python DBAPI-2.0. Note that the | ||||
| extension do not make psycopg incompatible and you can still use it without | ||||
| ever knowing the extensions are here.  | ||||
| 
 | ||||
| The DBAPI-2.0 mandates that cursors derived from the same connection are not | ||||
| isolated, i.e., changes done to the database by one of them should be | ||||
| immediately visible by all the others. This is done by serializing the queries | ||||
| on the same physical connection to the database (PGconn struct in C.)  | ||||
| Serializing queries when the network latencies are hight (and network speed is | ||||
| low) dramatically lowers performance, so it is possible to put a connection | ||||
| into not-serialized mode, by calling the .serialize() method giving it a | ||||
| 0-value argument or by creating a connection using the following code: | ||||
| 
 | ||||
| 	conn = psycopg.connect("dbname=...", serialize=0) | ||||
| 
 | ||||
| After that every cursor will get its own physical connection to the database | ||||
| and multiple threads will go at full speed. Note that this feature makes the | ||||
| new cursors non-compliant respect to the DBAPI-2.0. | ||||
| 
 | ||||
| The main extension is that we support (on not-serialized cursors) per-cursor | ||||
| commits. If you do a commit() on the connection all the changes on all the | ||||
| cursors derived from that connection are committed to the database (in random | ||||
| order, so take your care.)  But you can also call commit() on a single cursor | ||||
| to commit just the operations done on that cursor. Pretty nice. | ||||
| 
 | ||||
| Note that you *do have* to call .commit() on the cursors or on the connection | ||||
| if you want to change your database. Note also that you *do have* to call | ||||
| commit() on a cursor even before a SELECT if you want to see the changes | ||||
| apported by other threads to the database. | ||||
| 
 | ||||
| Also note that you *can't* (I repeat: *you* *can't*) call .commit() on cursor | ||||
| derived from a serialized connection: trying that will give you an exception | ||||
| with the message: "serialized connection: cannot commit on this cursor". If | ||||
| you want to use the per-cursor commit feature you need to create a | ||||
| non-serialized connection, as explained above. | ||||
| 
 | ||||
| From version 0.4.1 psycopg supports autocommit mode. You can set the default | ||||
| mode for new cursor by setting the 'autocommit' variable to 0 or 1 on the | ||||
| connection before creating a new cursor with the cursor() method. On an | ||||
| already created cursor you can change the commit mode by calling the | ||||
| autocommit() method. Giving no arguments or 1 switches autocommit on, 0 | ||||
| switches it off. | ||||
| 
 | ||||
| Obviously everything said about commit is valid for rollbacks too. | ||||
| 
 | ||||
| 
 | ||||
| The type system | ||||
| --------------- | ||||
| 
 | ||||
| The DBAPI-2.0 specify that should be possible to check for the column type | ||||
| reported in the second field of the description tuple of the cursor used for a | ||||
| SELECT using 'singletons' like NUMBER, STRING, etc. While this is fully | ||||
| supported by psycopg from release 0.3 on, we went forward and implemented | ||||
| support for custom typecasting from PostgreSQL to Python types using | ||||
| user-defined functions. See the examples test/check_types.py and | ||||
| doc/examples/usercast.py for more information. In particular usercast_test.py | ||||
| shows how to implement a callback that translates the PostgreSQL box type to | ||||
| an ad-hoc Python class with instances created automagically on SELECT. | ||||
| 
 | ||||
| 
 | ||||
| Compile-time configuration options | ||||
| ---------------------------------- | ||||
| 
 | ||||
| To build psycopg you will need a C compiler (gcc), the Python development | ||||
| files (headers and libraries), the PostgreSQL header and libraries and the | ||||
| mxDateTime header files (and the mxDateTime Python package installed, version | ||||
| >= 2.0.0, of curse.) | ||||
| 
 | ||||
| The following options are specific to psycopg and can be set when running | ||||
| configure before issuing 'make' to compile the package. | ||||
| 
 | ||||
|   --with-postgres-libraries=DIR | ||||
|       PostgreSQL 7.x libraries (libpq.so) are in directory DIR  | ||||
| 
 | ||||
|   --with-postgres-includes=DIR | ||||
|       PostgreSQL 7.x header files are located in directory DIR | ||||
|    | ||||
|   --with-mxdatetime-includes=DIR | ||||
|       MXDateTime Python extension header files are located in directory DIR | ||||
| 
 | ||||
|   --with-zope=DIR | ||||
|       install the ZPsycopgDA Zope Product into DIR (use 'make install-zope') | ||||
| 
 | ||||
|   --enable-devel[=yes/no] | ||||
|       Enable developer features like debugging output and extra assertions. | ||||
| 
 | ||||
| Some random notes about python versions and paths: | ||||
| 
 | ||||
|   1/ If possible, don't use the configure arguments --with-python-prefix  | ||||
|      and --with-python-exec-prefix; the configure script is able to guess | ||||
|      the correct values from you python installation. | ||||
| 
 | ||||
|   2/ If you have more than one Python version installed, use the arguments | ||||
|      --with-python (giving it the *full*, *absolute* path to the Python  | ||||
|      interpreter) and --with-python-version (giving it the corresponding | ||||
|      version, like 1.5 or 2.1.) | ||||
|    | ||||
| Common problems while building psycopg: | ||||
| 
 | ||||
|   1/ if your compiler does not find some postgres headers try copying all the | ||||
|      headers from the postgres _source_ distribution to a single place. Also, | ||||
|      if building postgresql from source, make sure to install all headers by | ||||
|      the "make install-all-headers" target. | ||||
| 
 | ||||
|   2/ if you have the same problem with mx.DateTime, try using the source | ||||
|      directory again; the install script does not copy all the headers, same | ||||
|      way as postgres install procedure does. | ||||
| 
 | ||||
|   3/ under MacOS X you may need to run the runlib program on the posgres  | ||||
|      installed libraries before trying to compile psycopg. Also, if you | ||||
|      get compilation errors there is a change your python was not compiled | ||||
|      correctly and psycopg is grabbing the wrong compile-time options from | ||||
|      python's Makefile. try setting the OPT and LDFLAG environment variables  | ||||
|      to something usefull, as in the next example: | ||||
| 
 | ||||
|        OPT="-no-cpp-precomp" LDFLAGS="-flat-namespace" ./configure ... | ||||
| 
 | ||||
| Licence | ||||
| ------- | ||||
|  | @ -30,16 +149,16 @@ it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. See file COPYING for details. | ||||
| 
 | ||||
| As a special exception, specific permission is granted for the GPLed code in | ||||
| this distribition to be linked to OpenSSL and PostgreSQL libpq without | ||||
| invoking GPL clause 2(b). | ||||
| As a special exception, specific permission is granted for the GPLed | ||||
| code in this distribition to be linked to OpenSSL and PostgreSQL libpq | ||||
| without invoking GPL clause 2(b). | ||||
| 
 | ||||
| If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e., every | ||||
| file inside the ZPsycopgDA directory) under the ZPL license as published on | ||||
| the Zope web site, http://www.zope.org/Resources/ZPL. The ZPL is perfectly | ||||
| compatible with the GPL | ||||
| If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e., | ||||
| every file inside the ZPsycopgDA directory) user the ZPL license as  | ||||
| published on the Zope web site, http://www.zope.org/Resources/ZPL. | ||||
| 
 | ||||
| psycopg is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| psycopg is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more | ||||
| details. | ||||
|  |  | |||
							
								
								
									
										381
									
								
								ZPsycopgDA/DA.py
									
									
									
									
									
								
							
							
						
						|  | @ -1,150 +1,274 @@ | |||
| # ZPsycopgDA/DA.py - ZPsycopgDA Zope product: Database Connection | ||||
| ############################################################################## | ||||
| #  | ||||
| # Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> | ||||
| # Zope Public License (ZPL) Version 1.0 | ||||
| # ------------------------------------- | ||||
| #  | ||||
| # 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. | ||||
| # Copyright (c) Digital Creations.  All rights reserved. | ||||
| #  | ||||
| # 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 license has been certified as Open Source(tm). | ||||
| #  | ||||
| # 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. | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions are | ||||
| # met: | ||||
| #  | ||||
| # See the LICENSE file for details. | ||||
| # 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 531 2004-09-18 09:54:40Z fog $''' % database_type | ||||
| __version__='$Revision: 1.20.2.14 $'[11:-2] | ||||
| __psycopg_versions__ = ('1.1.12', '1.1.13', '1.1.14', '1.1.15', '1.1.16') | ||||
| 
 | ||||
| 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 | ||||
| import Shared.DC.ZRDB.Connection, sys, DABase, time | ||||
| from Globals import HTMLFile, ImageFile | ||||
| from ExtensionClass import Base | ||||
| from DateTime import DateTime | ||||
| 
 | ||||
| # import psycopg and functions/singletons needed for date/time conversions | ||||
| 
 | ||||
| from string import find, join, split, rindex | ||||
| try: | ||||
|     import psycopg | ||||
| from psycopg import DATETIME | ||||
| from psycopg.extensions import TIME, DATE, INTERVAL | ||||
| from psycopg.extensions import new_type, register_type | ||||
|     from psycopg import new_type, register_type, DATETIME, TIME, DATE, INTERVAL | ||||
| 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 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| # 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)) | ||||
| 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) | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| # the connection object | ||||
| # 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] | ||||
|             t = time.mktime(time.strptime(join(dt[:2], ' '), '%Y-%m-%d %H:%M:%S')) | ||||
|         else: | ||||
|             t = time.mktime(time.strptime(dt[0], '%Y-%m-%d %H:%M:%S')) | ||||
|         return DateTime(t) | ||||
| 
 | ||||
| # Convert an ISO date string from postgres to a DateTime(zope version) | ||||
| # object. | ||||
| def cast_Date(str): | ||||
|     if str: | ||||
|         return DateTime(time.mktime(time.strptime(str, '%Y-%m-%d'))) | ||||
| 
 | ||||
| # 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 | ||||
| 
 | ||||
| 
 | ||||
| class Connection(DABase.Connection): | ||||
|     """ZPsycopg Connection.""" | ||||
|     id = 'Psycopg_database_connection'  | ||||
|     database_type     = 'Psycopg' | ||||
|     meta_type = title = 'Z Psycopg Database Connection' | ||||
|     icon              = 'misc_/ZPsycopg/conn' | ||||
|     "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=''): | ||||
|     def __init__(self, id, title, connection_string, zdatetime, | ||||
|                  check=None, tilevel=2, encoding='UTF-8'): | ||||
|         self.zdatetime=zdatetime | ||||
|         self.id=str(id) | ||||
|         self.edit(title, connection_string, zdatetime, | ||||
|                   check=check, tilevel=tilevel, encoding=encoding) | ||||
| 
 | ||||
|     def edit(self, title, connection_string, zdatetime, | ||||
|              check=1, tilevel=2, encoding='UTF-8'): | ||||
|         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(connection_string) | ||||
| 
 | ||||
|     manage_properties=HTMLFile('connectionEdit', globals()) | ||||
| 
 | ||||
|     def manage_edit(self, title, connection_string, | ||||
|                     zdatetime=None, check=None, tilevel=2, encoding='UTF-8', | ||||
|                     REQUEST=None): | ||||
|         """Change connection | ||||
|         """ | ||||
|         self.edit(title, connection_string, zdatetime, | ||||
|                   check=check, tilevel=tilevel, encoding=encoding) | ||||
|         if REQUEST is not None: | ||||
|             return MessageDialog( | ||||
|                 title='Edited', | ||||
|                 message='<strong>%s</strong> 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) | ||||
|              | ||||
|     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 | ||||
|         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)" + | ||||
|         if psycopg.__version__ not in __psycopg_versions__: | ||||
|             raise ImportError("psycopg version mismatch: " + | ||||
|                               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() | ||||
|         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' | ||||
|                 self._v_database_connection=DB(s, self.tilevel, self.encoding) | ||||
|             except: | ||||
|                 t, v, tb = sys.exc_info() | ||||
|                 raise 'BadRequest', ( | ||||
|                     '<strong>Could not open connection.<br>' | ||||
|                     'Connection string: </strong><CODE>%s</CODE><br>\n' | ||||
|                     '<pre>\n%s\n%s\n</pre>\n' | ||||
|                     % (s,t,v)), tb | ||||
|         finally: tb=None | ||||
|         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) | ||||
|     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 | ||||
| 
 | ||||
| # database connection registration data | ||||
| 
 | ||||
| classes = (Connection,) | ||||
| classes = ('DA.Connection',) | ||||
| 
 | ||||
| meta_types = ({'name':'Z Psycopg Database Connection', | ||||
|                'action':'manage_addZPsycopgConnectionForm'},) | ||||
| meta_types=( | ||||
|     {'name':'Z %s Database Connection' % database_type, | ||||
|      'action':'manage_addZ%sConnectionForm' % database_type},) | ||||
| 
 | ||||
| folder_methods={ | ||||
|     'manage_addZPsycopgConnection': manage_addZPsycopgConnection, | ||||
|  | @ -154,49 +278,10 @@ __ac_permissions__ = ( | |||
|     ('Add Z Psycopg Database Connections', | ||||
|      ('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),) | ||||
| 
 | ||||
| # add icons | ||||
| misc_={ | ||||
|     'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')} | ||||
| 
 | ||||
| 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'): | ||||
| 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) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,49 +1,141 @@ | |||
| # ZPsycopgDA/DABase.py - ZPsycopgDA Zope product: Database inspection | ||||
| ############################################################################## | ||||
| #  | ||||
| # Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> | ||||
| # Zope Public License (ZPL) Version 1.0 | ||||
| # ------------------------------------- | ||||
| #  | ||||
| # 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. | ||||
| # Copyright (c) Digital Creations.  All rights reserved. | ||||
| #  | ||||
| # 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 license has been certified as Open Source(tm). | ||||
| #  | ||||
| # 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. | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions are | ||||
| # met: | ||||
| #  | ||||
| # See the LICENSE file for details. | ||||
| # 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. | ||||
| #  | ||||
| ############################################################################## | ||||
| __doc__='''Database Connection | ||||
| 
 | ||||
| import sys | ||||
| import Shared.DC.ZRDB.Connection | ||||
| $Id: DABase.py 400 2003-01-20 14:39:34Z fog $''' | ||||
| __version__='$Revision: 1.10 $'[11:-2] | ||||
| 
 | ||||
| from db import DB | ||||
| from Globals import HTMLFile | ||||
| from ImageFile import ImageFile | ||||
| 
 | ||||
| import Shared.DC.ZRDB.Connection, sys | ||||
| from App.Dialogs import MessageDialog | ||||
| from Globals import HTMLFile, 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  | ||||
| 
 | ||||
|  | ||||
| import Acquisition | ||||
| from psycopg import NUMBER, ROWID, STRING, INTEGER, FLOAT | ||||
| from psycopg import BOOLEAN, DATETIME, LONGINTEGER | ||||
| 
 | ||||
| class Connection(Shared.DC.ZRDB.Connection.Connection): | ||||
|     _isAnSQLConnection = 1 | ||||
| 
 | ||||
|      | ||||
|     manage_options=Shared.DC.ZRDB.Connection.Connection.manage_options+( | ||||
|         {'label': 'Browse', 'action':'manage_browse'}, | ||||
|         # {'label': 'Design', 'action':'manage_tables'} | ||||
|         ) | ||||
| 
 | ||||
|     manage_tables = HTMLFile('tables',globals()) | ||||
|     manage_browse = HTMLFile('browse',globals()) | ||||
| 
 | ||||
|     info=None | ||||
| 
 | ||||
|     #manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + ( | ||||
|     #    {'label': 'Browse', 'action':'manage_browse'},) | ||||
|     def tpValues(self): | ||||
|         #if hasattr(self, '_v_tpValues'): return self._v_tpValues | ||||
|         r=[] | ||||
|         # self._v_tables=tables=TableBrowserCollection() | ||||
|         #tables=tables.__dict__ | ||||
|         c = self._v_database_connection | ||||
|         try: | ||||
|             for d in c.tables(rdb=0): | ||||
|                 try: | ||||
|                     name=d['TABLE_NAME'] | ||||
|                     b=TableBrowser() | ||||
|                     b.__name__=name | ||||
|                     b._d=d | ||||
|                     b._c=c | ||||
|                     # b._columns=c.columns(name) | ||||
|                     try: b.icon=table_icons[d['TABLE_TYPE']] | ||||
|                     except: pass | ||||
|                     r.append(b) | ||||
|                     # tables[name]=b | ||||
|                 except: | ||||
|                     # print d['TABLE_NAME'], sys.exc_type, sys.exc_value | ||||
|                     pass | ||||
| 
 | ||||
|     #manage_tables = HTMLFile('tables', globals()) | ||||
|     #manage_browse = HTMLFile('browse',globals()) | ||||
|         finally: pass #print sys.exc_type, sys.exc_value | ||||
|         #self._v_tpValues=r | ||||
|         return r | ||||
| 
 | ||||
|     def __getitem__(self, name): | ||||
|         if name=='tableNamed': | ||||
|  | @ -51,11 +143,8 @@ class Connection(Shared.DC.ZRDB.Connection.Connection): | |||
|             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""" | ||||
|  | @ -65,3 +154,116 @@ class Connection(Shared.DC.ZRDB.Connection.Connection): | |||
| 
 | ||||
|     def manage_update(self, table, keys, cols, REQUEST=None): | ||||
|         """Create an SQL update""" | ||||
| 
 | ||||
| class TableBrowserCollection(Acquisition.Implicit): | ||||
|     "Helper class for accessing tables via URLs" | ||||
|     pass | ||||
| 
 | ||||
| class Browser(Base): | ||||
|     def __getattr__(self, name): | ||||
|         try: return self._d[name] | ||||
|         except KeyError: raise AttributeError, name | ||||
| 
 | ||||
| class values: | ||||
| 
 | ||||
|     def len(self): return 1 | ||||
| 
 | ||||
|     def __getitem__(self, i): | ||||
|         try: return self._d[i] | ||||
|         except AttributeError: | ||||
|             pass | ||||
|         self._d=self._f() | ||||
|         return self._d[i] | ||||
| 
 | ||||
| class TableBrowser(Browser, Acquisition.Implicit): | ||||
|     icon='what' | ||||
|     Description=check='' | ||||
|     info=HTMLFile('table_info',globals()) | ||||
|     menu=HTMLFile('table_menu',globals()) | ||||
| 
 | ||||
|     def tpValues(self): | ||||
|         v=values() | ||||
|         v._f=self.tpValues_ | ||||
|         return v | ||||
| 
 | ||||
|     def tpValues_(self): | ||||
|         r=[] | ||||
|         tname=self.__name__ | ||||
|         for d in self._c.columns(tname): | ||||
|             b=ColumnBrowser() | ||||
|             b._d=d | ||||
|             try: b.icon=field_icons[d['Type']] | ||||
|             except: pass | ||||
|             b.TABLE_NAME=tname | ||||
|             r.append(b) | ||||
|         return r | ||||
|              | ||||
|     def tpId(self): return self._d['TABLE_NAME'] | ||||
|     def tpURL(self): return "Table/%s" % self._d['TABLE_NAME'] | ||||
|     def Name(self): return self._d['TABLE_NAME'] | ||||
|     def Type(self): return self._d['TABLE_TYPE'] | ||||
| 
 | ||||
|     manage_designInput=HTMLFile('designInput',globals()) | ||||
|     def manage_buildInput(self, id, source, default, REQUEST=None): | ||||
|         "Create a database method for an input form" | ||||
|         args=[] | ||||
|         values=[] | ||||
|         names=[] | ||||
|         columns=self._columns | ||||
|         for i in range(len(source)): | ||||
|             s=source[i] | ||||
|             if s=='Null': continue | ||||
|             c=columns[i] | ||||
|             d=default[i] | ||||
|             t=c['Type'] | ||||
|             n=c['Name'] | ||||
|             names.append(n) | ||||
|             if s=='Argument': | ||||
|                 values.append("<dtml-sqlvar %s type=%s>'" % | ||||
|                               (n, vartype(t))) | ||||
|                 a='%s%s' % (n, boboType(t)) | ||||
|                 if d: a="%s=%s" % (a,d) | ||||
|                 args.append(a) | ||||
|             elif s=='Property': | ||||
|                 values.append("<dtml-sqlvar %s type=%s>'" % | ||||
|                               (n, vartype(t))) | ||||
|             else: | ||||
|                 if isStringType(t): | ||||
|                     if find(d,"\'") >= 0: d=join(split(d,"\'"),"''") | ||||
|                     values.append("'%s'" % d) | ||||
|                 elif d: | ||||
|                     values.append(str(d)) | ||||
|                 else: | ||||
|                     raise ValueError, ( | ||||
|                         'no default was given for <em>%s</em>' % n) | ||||
| 
 | ||||
| class ColumnBrowser(Browser): | ||||
|     icon='field' | ||||
| 
 | ||||
|     def check(self): | ||||
|         return ('\t<input type=checkbox name="%s.%s">' % | ||||
|                 (self.TABLE_NAME, self._d['Name'])) | ||||
|     def tpId(self): return self._d['Name'] | ||||
|     def tpURL(self): return "Column/%s" % self._d['Name'] | ||||
|     def Description(self): | ||||
|         d=self._d | ||||
|         if d['Scale']: | ||||
|             return " %(Type)s(%(Precision)s,%(Scale)s) %(Nullable)s" % d | ||||
|         else: | ||||
|             return " %(Type)s(%(Precision)s) %(Nullable)s" % d | ||||
| 
 | ||||
| table_icons={ | ||||
|     'TABLE': 'table', | ||||
|     'VIEW':'view', | ||||
|     'SYSTEM_TABLE': 'stable', | ||||
|     } | ||||
| 
 | ||||
| field_icons={ | ||||
|     NUMBER.name: 'int', | ||||
|     STRING.name: 'text', | ||||
|     DATETIME.name: 'date', | ||||
|     INTEGER.name: 'int', | ||||
|     FLOAT.name: 'float', | ||||
|     BOOLEAN.name: 'bin', | ||||
|     ROWID.name: 'int' | ||||
|     } | ||||
|  |  | |||
|  | @ -1,32 +1,105 @@ | |||
| # ZPsycopgDA/__init__.py - ZPsycopgDA Zope product | ||||
| ############################################################################## | ||||
| #  | ||||
| # Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> | ||||
| # Zope Public License (ZPL) Version 1.0 | ||||
| # ------------------------------------- | ||||
| #  | ||||
| # 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. | ||||
| # Copyright (c) Digital Creations.  All rights reserved. | ||||
| #  | ||||
| # 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 license has been certified as Open Source(tm). | ||||
| #  | ||||
| # 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. | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions are | ||||
| # met: | ||||
| #  | ||||
| # See the LICENSE file for details. | ||||
| # 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. | ||||
| #  | ||||
| ############################################################################## | ||||
| # Modified by mcm@initd.net for the psycopg driver | ||||
| __doc__='''Generic Database Adapter Package Registration | ||||
| 
 | ||||
| __doc__ = "ZPsycopg Database Adalper Registration."  | ||||
| __version__ = '2.0' | ||||
| $Id: __init__.py 400 2003-01-20 14:39:34Z fog $''' | ||||
| __version__='$Revision: 1.11 $'[11:-2] | ||||
| 
 | ||||
| import sys | ||||
| import string | ||||
| import sys, string | ||||
| import DA | ||||
| 
 | ||||
| methods=DA.folder_methods | ||||
| classes    = DA.classes | ||||
| meta_types = DA.meta_types | ||||
| misc_ = DA.misc_ | ||||
| 
 | ||||
| __ac_permissions__=DA.__ac_permissions__ | ||||
| def initialize(context): | ||||
|     """Initialize the DBA product. | ||||
|     """ | ||||
|     context.registerClass( | ||||
|         DA.Connection, | ||||
|         permission = 'Add Z Psycopg Database Connections', | ||||
|         constructors = (DA.manage_addZPsycopgConnectionForm, | ||||
|                         DA.manage_addZPsycopgConnection), | ||||
|         icon = SOFTWARE_HOME + '/Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif') | ||||
|  |  | |||
							
								
								
									
										260
									
								
								ZPsycopgDA/db.py
									
									
									
									
									
								
							
							
						
						|  | @ -1,126 +1,171 @@ | |||
| # ZPsycopgDA/db.py - query execution | ||||
| ############################################################################## | ||||
| #  | ||||
| # Copyright (C) 2004 Federico Di Gregorio <fog@initd.org> | ||||
| # Zope Public License (ZPL) Version 1.0 | ||||
| # ------------------------------------- | ||||
| #  | ||||
| # 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. | ||||
| # Copyright (c) Digital Creations.  All rights reserved. | ||||
| #  | ||||
| # 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 license has been certified as Open Source(tm). | ||||
| #  | ||||
| # 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. | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions are | ||||
| # met: | ||||
| #  | ||||
| # See the LICENSE file for details. | ||||
| # 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 INTERUPTION) 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. | ||||
| #  | ||||
| ############################################################################## | ||||
| 
 | ||||
| '''$Id: db.py 532 2004-09-27 18:35:25Z fog $''' | ||||
| __version__='$Revision: 1.31.2.7 $'[11:-2] | ||||
| 
 | ||||
| 
 | ||||
| from Shared.DC.ZRDB.TM import TM | ||||
| from Shared.DC.ZRDB import dbi_db | ||||
| 
 | ||||
| from ZODB.POSException import ConflictError | ||||
| 
 | ||||
| import time | ||||
| import string, sys | ||||
| from string import strip, split, find | ||||
| from time import time | ||||
| from types import ListType | ||||
| 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 | ||||
| from psycopg import NUMBER, STRING, INTEGER, FLOAT, DATETIME | ||||
| from psycopg import BOOLEAN, ROWID, LONGINTEGER | ||||
| from ZODB.POSException import ConflictError | ||||
| 
 | ||||
| class DB(TM,dbi_db.DB): | ||||
| 
 | ||||
|     _p_oid = _p_changed = _registered = None | ||||
| 
 | ||||
|     def __init__(self, dsn, tilevel, enc='utf-8'): | ||||
|         self.dsn = dsn | ||||
|     def __init__(self, connection, tilevel, enc='utf-8'): | ||||
|         self.connection = connection | ||||
|         self.tilevel = tilevel | ||||
|         self.encoding = enc  | ||||
|         self.db = self.connect(self.connection) | ||||
|         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 connect(self, connection): | ||||
|         o = psycopg.connect(connection) | ||||
|         o.set_isolation_level(int(self.tilevel)) | ||||
|         return o | ||||
|      | ||||
|     def _finish(self, *ignored): | ||||
|         try: | ||||
|             conn = self.getconn(False) | ||||
|             conn.commit() | ||||
|             self.putconn() | ||||
|         except AttributeError: | ||||
|             pass | ||||
|         if hasattr(self, 'db') and self.db: | ||||
|             self.db.commit() | ||||
|              | ||||
|     def _abort(self, *ignored): | ||||
|         try: | ||||
|             conn = self.getconn(False) | ||||
|             conn.rollback() | ||||
|             self.putconn() | ||||
|         except AttributeError: | ||||
|             pass | ||||
|         if hasattr(self, 'db') and self.db: | ||||
|             self.db.rollback() | ||||
|              | ||||
|     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 _cursor(self): | ||||
|         """Obtains a cursor in a safe way.""" | ||||
|         if not hasattr(self, 'db') or not self.db: | ||||
|             self.db = self.connect(self.connection) | ||||
|         return self.db.cursor() | ||||
|      | ||||
|     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 = [] | ||||
|         c = self._cursor() | ||||
|         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\' ' ) | ||||
|         r = [] | ||||
|         a = r.append | ||||
|         for name, typ in c.fetchall(): | ||||
|             if typ in _care: | ||||
|                 res.append({'TABLE_NAME': name, 'TABLE_TYPE': typ}) | ||||
|         self.putconn() | ||||
|         return res | ||||
|                 a({'TABLE_NAME': name, 'TABLE_TYPE': typ}) | ||||
|         c.close() | ||||
|         return r | ||||
| 
 | ||||
|     def columns(self, table_name): | ||||
|         self._register() | ||||
|         c = self.getcursor() | ||||
|         c = self._cursor() | ||||
|         try: | ||||
|             r = c.execute('SELECT * FROM "%s" WHERE 1=0' % table_name) | ||||
|             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: | ||||
|         desc = c.description | ||||
|         r = [] | ||||
|         a = r.append | ||||
|         for name, type, width, ds, p, scale, null_ok in desc: | ||||
|             if type == NUMBER: | ||||
|                 if type == INTEGER: | ||||
|                     type = INTEGER | ||||
|  | @ -135,50 +180,46 @@ class DB(TM, dbi_db.DB): | |||
|                 type = DATETIME | ||||
|             else: | ||||
|                 type = STRING | ||||
| 
 | ||||
|             res.append({'Name': name, | ||||
|             a({ 'Name': name, | ||||
|                 'Type': type.name, | ||||
|                 'Precision': 0, | ||||
|                 'Scale': 0, | ||||
|                 'Nullable': 0}) | ||||
|         self.putconn() | ||||
|         return res | ||||
|      | ||||
|     ## query execution ## | ||||
|         return r | ||||
| 
 | ||||
|     def query(self, query_string, max_rows=None, query_data=None): | ||||
|         self._register() | ||||
|         self.calls = self.calls+1 | ||||
|          | ||||
|         desc = () | ||||
|         res = [] | ||||
|         result = [] | ||||
|         nselects = 0 | ||||
|          | ||||
|         c = self.getcursor() | ||||
|         c = self._cursor() | ||||
|          | ||||
|         try: | ||||
|             for qs in [x for x in query_string.split('\0') if x]: | ||||
|             for qs in filter(None, map(strip, split(query_string, '\0'))): | ||||
|                 if type(qs) == unicode: | ||||
|                     if self.encoding: | ||||
|                         qs = qs.encode(self.encoding) | ||||
|                 try: | ||||
|                     if (query_data): | ||||
|                         c.execute(qs, query_data) | ||||
|                         r = c.execute(qs, query_data) | ||||
|                     else: | ||||
|                         c.execute(qs) | ||||
|                 except (psycopg.ProgrammingError, psycopg.IntegrityError), e: | ||||
|                     if e.args[0].find("concurrent update") > -1: | ||||
|                         r = c.execute(qs) | ||||
|                 except (psycopg.ProgrammingError,psycopg.IntegrityError), perr: | ||||
|                     if perr.args[0].find("concurrent update") > -1: | ||||
|                         raise ConflictError | ||||
|                     raise e | ||||
|                     raise perr | ||||
|                 if c.description is not None: | ||||
|                     nselects += 1 | ||||
|                     nselects = nselects + 1 | ||||
|                     if c.description != desc and nselects > 1: | ||||
|                         raise psycopg.ProgrammingError( | ||||
|                             'multiple selects in single query not allowed') | ||||
|                         raise 'Query Error', \ | ||||
|                               'Multiple select schema are not allowed' | ||||
|                     if max_rows: | ||||
|                         res = c.fetchmany(max_rows) | ||||
|                         result = c.fetchmany(max_rows) | ||||
|                     else: | ||||
|                         res = c.fetchall() | ||||
|                         result = c.fetchall() | ||||
|                     desc = c.description | ||||
|             self.failures = 0 | ||||
|              | ||||
|  | @ -206,4 +247,13 @@ class DB(TM, dbi_db.DB): | |||
|                 'null': null_ok, | ||||
|                 }) | ||||
| 
 | ||||
|         return items, res | ||||
|         return items, result | ||||
| 
 | ||||
|     def close(self): | ||||
|         """Close the connection.""" | ||||
|         self.db.close() | ||||
|         self.db = None | ||||
|          | ||||
|     def sortKey(self): | ||||
|         """Zope 2.6 added this one.""" | ||||
|         return 1 | ||||
|  |  | |||
| Before Width: | Height: | Size: 924 B After Width: | Height: | Size: 924 B | 
| Before Width: | Height: | Size: 929 B After Width: | Height: | Size: 929 B | 
| Before Width: | Height: | Size: 918 B After Width: | Height: | Size: 918 B | 
| Before Width: | Height: | Size: 878 B After Width: | Height: | Size: 878 B | 
| Before Width: | Height: | Size: 918 B After Width: | Height: | Size: 918 B | 
| Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 894 B |