Undo of wrong commit of 1.1.x source code over 2.x.
5
AUTHORS
|
@ -1,9 +1,8 @@
|
|||
Main authors:
|
||||
Michele Comitini <mcm@initd.org>
|
||||
Federico Di Gregorio <fog@debian.org>
|
||||
|
||||
For the win32 port:
|
||||
Jason Erickson <jerickso@indian.com>
|
||||
Jason Erickson <jerickso@indian.com> (most of his changes are still in 2.0)
|
||||
|
||||
Additional Help:
|
||||
Tom Jenkins <tjenkins@devis.com> (COPY FROM/COPY TO backport)
|
||||
|
||||
|
|
190
INSTALL
|
@ -1,184 +1,18 @@
|
|||
Basic Installation
|
||||
==================
|
||||
Compiling and installing psycopg
|
||||
********************************
|
||||
|
||||
These are generic installation instructions. Before building and
|
||||
installing make sure you read carefully the "Install" section in the
|
||||
README file.
|
||||
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:
|
||||
|
||||
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').
|
||||
python setup.py build
|
||||
|
||||
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.
|
||||
to build in the local directory; and:
|
||||
|
||||
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'.
|
||||
python setup.py install
|
||||
|
||||
The simplest way to compile this package is:
|
||||
to install system-wide.
|
||||
|
||||
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,355 +1,155 @@
|
|||
psycopg news for 1.1.15
|
||||
-----------------------
|
||||
What's new in psycopg 1.99.10
|
||||
-----------------------------
|
||||
|
||||
* Interval typecasting eventually-eventually works the Right Way (TM).
|
||||
* 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.
|
||||
|
||||
* Fixed two bad memory leaks in QuotedString and Binary objects.
|
||||
* More configuration options moved from setup.py to setup.cfg.
|
||||
|
||||
* Reverted change on rowcount attribute, now it is always set to the real
|
||||
number of affected columns.
|
||||
* Fixed two memory leaks: one in cursor deallocation and one in row
|
||||
fetching (.fetchXXX() methods.)
|
||||
|
||||
psycopg news for 1.1.14
|
||||
-----------------------
|
||||
What's new in psycopg 1.99.9
|
||||
----------------------------
|
||||
|
||||
* Interval typecasting eventually works the Right Way (TM).
|
||||
* Added simple pooling code (psycopg.pool module); see the reworked
|
||||
examples/threads.py for example code.
|
||||
|
||||
* ZPsycopgDA now support unicode strings and different backend encodings.
|
||||
* 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 accept query data as an extra parameter to execute() (but
|
||||
still no way to give it extra data from inside a ZSQL Method.)
|
||||
* ZPsycopgDA back in and working using the new pooling code.
|
||||
|
||||
* Better DBAPI-2.0 compliance (rowcount attribute and argument passing.)
|
||||
* Isn't that enough? :)
|
||||
|
||||
* Now builds on Fedora Core 2 (but remember that the real psycopg
|
||||
aficionado runs on Debian ;-P )
|
||||
What's new in psycopg 1.99.8
|
||||
----------------------------
|
||||
|
||||
* COPY FROM raise an exception and return usefull information on error.
|
||||
* added support for UNICODE queries.
|
||||
|
||||
psycopg news for 1.1.13
|
||||
-----------------------
|
||||
* added UNICODE typecaster; to activate it just do:
|
||||
|
||||
* ZPsycopgDA works again.
|
||||
psycopg.extensions.register_type(psycopg.extensions.UNICODE)
|
||||
|
||||
psycopg news for 1.1.12
|
||||
-----------------------
|
||||
Note that the UNICODE typecaster override the STRING one, so it is
|
||||
not activated by default.
|
||||
|
||||
* Fixed nasty segfault/deadlock in switch_isolation_level.
|
||||
* cursors now really support the iterator protocol.
|
||||
|
||||
* 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.
|
||||
* solved the rounding errors in time conversions.
|
||||
|
||||
* Added an "sslmode" parameter (look at PostgreSQL documentation for
|
||||
possible values.)
|
||||
* now cursors support .fileno() and .isready() methods, to be used in
|
||||
select() calls.
|
||||
|
||||
* .execute() now rise the right exception if called with a wrong
|
||||
tuple/dict. Also, %% in queries does not raise an exception anymore.
|
||||
* .copy_from() and .copy_in() methods are back in (still using the old
|
||||
protocol, will be updated to use new one in next releasae.)
|
||||
|
||||
* Updated RPM specs (thanks to Mark McClain we now have updated RPMs on
|
||||
initd.org too.)
|
||||
* fixed memory corruption bug reported on win32 platform.
|
||||
|
||||
psycopg news for 1.1.11
|
||||
-----------------------
|
||||
What's new in psycopg 1.99.7
|
||||
----------------------------
|
||||
|
||||
* a modern autoconf is now needed to build psycopg.
|
||||
* 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.
|
||||
|
||||
* now an error during commit or rollback is correctly reported by raising
|
||||
an exception.
|
||||
* 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.
|
||||
|
||||
* 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.)
|
||||
What's new in psycopg 1.99.6
|
||||
----------------------------
|
||||
|
||||
* plugged a memory leak in copy_from().
|
||||
* sslmode parameter from 1.1.x
|
||||
|
||||
* where did the news for 1.1.10 go?
|
||||
* various datetime conversion improvements.
|
||||
|
||||
psycopg news for 1.1.9
|
||||
----------------------
|
||||
* now psycopg should compile without mx or without native datetime
|
||||
(not both, obviously.)
|
||||
|
||||
* psycopg distribution now includes the GeoTypes package by Richard Taylor
|
||||
(QinetiQ Plc)!
|
||||
* included various win32/MSVC fixes (pthread.h changes, winsock2
|
||||
library, include path in setup.py, etc.)
|
||||
|
||||
* 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.
|
||||
* ported interval fixes from 1.1.14/1.1.15.
|
||||
|
||||
* no more libpq 7.1.x linking problems related to PQfreeNotify.
|
||||
* the last query executed by a cursor is now available in the
|
||||
.query attribute.
|
||||
|
||||
psycopg news for 1.1.7
|
||||
----------------------
|
||||
* conversion of unicode strings to backend encoding now uses a table
|
||||
(that still need to be filled.)
|
||||
|
||||
* added notifies and fileno methods to cursor objects.
|
||||
* cursors now have a .mogrify() method that return the query string
|
||||
instead of executing it.
|
||||
|
||||
* now execute accept any object that defined __getitem__ and not only
|
||||
dictionaries.
|
||||
* connection objects now have a .dsn read-only attribute that holds the
|
||||
connection string.
|
||||
|
||||
* little fix in ZPsycopgDA, should work with Zope 2.7.
|
||||
* 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.)
|
||||
|
||||
psycopg news for 1.1.6
|
||||
----------------------
|
||||
What's new in psycopg 1.99.3
|
||||
----------------------------
|
||||
|
||||
* cursor objects now have the .scroll() method.
|
||||
* added support for python 2.3 datetime types (both ways) and made datetime
|
||||
the default set of typecasters when available.
|
||||
|
||||
* NUL characters in strings are discarded in quoting; use a Binary object if
|
||||
you need strings with embedded NULs.
|
||||
* added example: dt.py.
|
||||
|
||||
* Fixed another MT problem in .execute().
|
||||
What's new in psycopg 1.99.3
|
||||
----------------------------
|
||||
|
||||
psycopg news for 1.1.5
|
||||
----------------------
|
||||
* initial working support for unicode bound variables: UTF-8 and latin-1
|
||||
backend encodings are natively supported (and the encoding.py example even
|
||||
works!)
|
||||
|
||||
* 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 .set_client_encoding() method on the connection object.
|
||||
|
||||
* fixed problem with dictionary mogrification (i.e., specifying the same key
|
||||
multiple times and having the None value in the dict should work now.)
|
||||
* added examples: encoding.py, binary.py, lastrowid.py.
|
||||
|
||||
* fixed keeper status trashing problem: no more psycopg stuck in transaction
|
||||
(maybe this will also solve ZPsycopgDA problems: will see...)
|
||||
What's new in psycopg 1.99.2
|
||||
----------------------------
|
||||
|
||||
* now copy_from and copy_to can be passed instances of classes with "readline"
|
||||
and "write" methods and not only file instances.
|
||||
* better typecasting:
|
||||
- DateTimeDelta used for postgresql TIME (merge from 1.1)
|
||||
- BYTEA now is converted to a real buffer object, not to a string
|
||||
|
||||
psycopg news for 1.1.4
|
||||
----------------------
|
||||
* buffer objects are now adapted into Binary objects automatically.
|
||||
|
||||
* Fixed various memory leak problems.
|
||||
* ported scroll method from 1.1 (DBAPI-2.0 extension for cursors)
|
||||
|
||||
* Implemented "statusmessage" attribute on cursors.
|
||||
* 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
|
||||
|
||||
psycopg news for 1.1.3
|
||||
----------------------
|
||||
What's new in psycopg 1.99.1
|
||||
----------------------------
|
||||
|
||||
* Fixed problem with psycopg always reporting IntegrityError.
|
||||
* implemented microprotocols to adapt arbitrary types to the interface used by
|
||||
psycopg to bind variables in execute;
|
||||
|
||||
* Fixed segfault in debug statements.
|
||||
* moved qstring, pboolean and mxdatetime to the new adapter layout (binary is
|
||||
still missing; python 2.3 datetime needs to be written).
|
||||
|
||||
* Now Python GIL is unlocked during PQconnectdb() calls (better
|
||||
multithreading.)
|
||||
|
||||
psycopg news for 1.1.2
|
||||
----------------------
|
||||
What's new in psycopg 1.99.0
|
||||
----------------------------
|
||||
|
||||
* Skipped version 1.1.1 (never released 'cause of a cvs tag error)
|
||||
* reorganized the whole source tree;
|
||||
|
||||
* Much better cursor.description fields (many thanks to William K. Volkman)
|
||||
* async core is in place;
|
||||
|
||||
* psycopg.connect() now takes keyword parameters for host, dbname, port,
|
||||
user and password (they are all strings, even "port".)
|
||||
* splitted QuotedString objects from mx stuff;
|
||||
|
||||
* 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!
|
||||
* dropped autotools and moved to pythonic setup.py (needs work.)
|
||||
|
|
173
README
|
@ -1,145 +1,26 @@
|
|||
psycopg - Python-PostgreSQL Database Adapter
|
||||
********************************************
|
||||
|
||||
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 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 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.
|
||||
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 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.
|
||||
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.
|
||||
|
||||
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
|
||||
-------
|
||||
|
@ -149,16 +30,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) 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.
|
||||
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
|
||||
|
||||
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.
|
||||
|
|
391
ZPsycopgDA/DA.py
|
@ -1,287 +1,202 @@
|
|||
##############################################################################
|
||||
# ZPsycopgDA/DA.py - ZPsycopgDA Zope product: Database Connection
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
# 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.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
# 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.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
# 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.
|
||||
#
|
||||
# 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
|
||||
# See the LICENSE file for details.
|
||||
|
||||
$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
|
||||
import Shared.DC.ZRDB.Connection, sys, DABase, time
|
||||
from Globals import HTMLFile, ImageFile
|
||||
from Globals import DTMLFile
|
||||
from Globals import HTMLFile
|
||||
from ImageFile import ImageFile
|
||||
from ExtensionClass import Base
|
||||
from string import find, join, split, rindex
|
||||
try:
|
||||
import psycopg
|
||||
from psycopg import new_type, register_type, DATETIME, TIME, DATE, INTERVAL
|
||||
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
|
||||
from DateTime import DateTime
|
||||
|
||||
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)
|
||||
# import psycopg and functions/singletons needed for date/time conversions
|
||||
|
||||
import psycopg
|
||||
from psycopg import DATETIME
|
||||
from psycopg.extensions import TIME, DATE, INTERVAL
|
||||
from psycopg.extensions import new_type, register_type
|
||||
|
||||
# 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')))
|
||||
# add a new connection to a folder
|
||||
|
||||
# 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:]))
|
||||
manage_addZPsycopgConnectionForm = DTMLFile('dtml/add',globals())
|
||||
|
||||
# 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
|
||||
def manage_addZPsycopgConnection(self, id, title, connection_string,
|
||||
zdatetime=None, tilevel=2,
|
||||
check=None, REQUEST=None):
|
||||
"""Add a DB connection to a folder."""
|
||||
self._setObject(id, Connection(id, title, connection_string,
|
||||
zdatetime, check, tilevel))
|
||||
if REQUEST is not None: return self.manage_main(self, REQUEST)
|
||||
|
||||
|
||||
|
||||
# the connection object
|
||||
|
||||
class Connection(DABase.Connection):
|
||||
"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
|
||||
"""ZPsycopg Connection."""
|
||||
id = 'Psycopg_database_connection'
|
||||
database_type = 'Psycopg'
|
||||
meta_type = title = 'Z Psycopg Database Connection'
|
||||
icon = 'misc_/ZPsycopg/conn'
|
||||
|
||||
def __init__(self, id, title, connection_string, zdatetime,
|
||||
check=None, tilevel=2, encoding='UTF-8'):
|
||||
self.zdatetime=zdatetime
|
||||
self.id=str(id)
|
||||
def __init__(self, id, title, connection_string,
|
||||
zdatetime, check=None, tilevel=2, encoding=''):
|
||||
self.zdatetime = zdatetime
|
||||
self.id = str(id)
|
||||
self.edit(title, connection_string, zdatetime,
|
||||
check=check, tilevel=tilevel, encoding=encoding)
|
||||
|
||||
def 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 connect(self,s):
|
||||
try: self._v_database_connection.close()
|
||||
except: pass
|
||||
def edit(self, title, connection_string,
|
||||
zdatetime, check=None, tilevel=2, encoding=''):
|
||||
self.title = title
|
||||
self.connection_string = connection_string
|
||||
self.zdatetime = zdatetime
|
||||
self.tilevel = tilevel
|
||||
self.encoding = encoding
|
||||
|
||||
self.set_type_casts()
|
||||
|
||||
if check: self.connect(self.connection_string)
|
||||
|
||||
manage_properties = DTMLFile('dtml/edit', globals())
|
||||
|
||||
def manage_edit(self, title, connection_string,
|
||||
zdatetime=None, check=None, tilevel=2, encoding='UTF-8',
|
||||
REQUEST=None):
|
||||
"""Edit the DB connection."""
|
||||
self.edit(title, connection_string, zdatetime,
|
||||
check=check, tilevel=tilevel, encoding=encoding)
|
||||
if REQUEST is not None:
|
||||
msg = "Connection edited."
|
||||
return self.manage_main(self,REQUEST,manage_tabs_message=msg)
|
||||
|
||||
def connect(self, s):
|
||||
try:
|
||||
self._v_database_connection.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
# check psycopg version and raise exception if does not match
|
||||
if psycopg.__version__ not in __psycopg_versions__:
|
||||
raise ImportError("psycopg version mismatch: " +
|
||||
if psycopg.__version__ not in ALLOWED_PSYCOPG_VERSIONS:
|
||||
raise ImportError("psycopg version mismatch (imported %s)" +
|
||||
psycopg.__version__)
|
||||
|
||||
self.set_type_casts()
|
||||
self._v_connected=''
|
||||
DB=self.factory()
|
||||
try:
|
||||
try:
|
||||
# this is necessary when upgrading from old installs without
|
||||
# having to recreate the connection object
|
||||
if not hasattr(self, 'tilevel'):
|
||||
self.tilevel = 2
|
||||
if not hasattr(self, 'encoding'):
|
||||
self.encoding = 'UTF-8'
|
||||
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()
|
||||
self._v_connected = ''
|
||||
dbf = self.factory()
|
||||
|
||||
# TODO: let the psycopg exception propagate, or not?
|
||||
self._v_database_connection = dbf(
|
||||
self.connection_string, self.tilevel, self.encoding)
|
||||
self._v_database_connection.open()
|
||||
self._v_connected = DateTime()
|
||||
|
||||
return self
|
||||
|
||||
def 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
|
||||
def set_type_casts(self):
|
||||
# note that in both cases order *is* important
|
||||
if self.zdatetime:
|
||||
# use zope internal datetime routines
|
||||
register_type(ZDATETIME)
|
||||
register_type(ZDATE)
|
||||
register_type(ZTIME)
|
||||
register_type(ZINTERVAL)
|
||||
else:
|
||||
# use the standard
|
||||
register_type(DATETIME)
|
||||
register_type(DATE)
|
||||
register_type(TIME)
|
||||
register_type(INTERVAL)
|
||||
|
||||
# database connection registration data
|
||||
|
||||
classes = ('DA.Connection',)
|
||||
classes = (Connection,)
|
||||
|
||||
meta_types=(
|
||||
{'name':'Z %s Database Connection' % database_type,
|
||||
'action':'manage_addZ%sConnectionForm' % database_type},)
|
||||
meta_types = ({'name':'Z Psycopg Database Connection',
|
||||
'action':'manage_addZPsycopgConnectionForm'},)
|
||||
|
||||
folder_methods={
|
||||
folder_methods = {
|
||||
'manage_addZPsycopgConnection': manage_addZPsycopgConnection,
|
||||
'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm}
|
||||
|
||||
__ac_permissions__=(
|
||||
__ac_permissions__ = (
|
||||
('Add Z Psycopg Database Connections',
|
||||
('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),)
|
||||
|
||||
misc_={
|
||||
'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')}
|
||||
# add icons
|
||||
|
||||
for icon in ('table', 'view', 'stable', 'what',
|
||||
'field', 'text','bin','int','float',
|
||||
'date','time','datetime'):
|
||||
misc_={'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')}
|
||||
|
||||
for icon in ('table', 'view', 'stable', 'what', 'field', 'text', 'bin',
|
||||
'int', 'float', 'date', 'time', 'datetime'):
|
||||
misc_[icon] = ImageFile('icons/%s.gif' % icon, globals())
|
||||
|
||||
# zope-specific psycopg typecasters
|
||||
|
||||
# convert an ISO timestamp string from postgres to a Zope DateTime object
|
||||
def _cast_DateTime(str):
|
||||
if str:
|
||||
# this will split us into [date, time, GMT/AM/PM(if there)]
|
||||
dt = split(str, ' ')
|
||||
if len(dt) > 1:
|
||||
# we now should split out any timezone info
|
||||
dt[1] = split(dt[1], '-')[0]
|
||||
dt[1] = split(dt[1], '+')[0]
|
||||
return DateTime(join(dt[:2], ' '))
|
||||
else:
|
||||
return DateTime(dt[0])
|
||||
|
||||
# convert an ISO date string from postgres to a Zope DateTime object
|
||||
def _cast_Date(str):
|
||||
if str:
|
||||
return DateTime(str)
|
||||
|
||||
# Convert a time string from postgres to a Zope DateTime object.
|
||||
# NOTE: we set the day as today before feeding to DateTime so
|
||||
# that it has the same DST settings.
|
||||
def _cast_Time(str):
|
||||
if str:
|
||||
return DateTime(time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(time.time())[:3]+
|
||||
time.strptime(str[:8], "%H:%M:%S")[3:]))
|
||||
|
||||
# TODO: DateTime does not support intervals: what's the best we can do?
|
||||
def _cast_Interval(str):
|
||||
return str
|
||||
|
||||
ZDATETIME = new_type((1184, 1114), "ZDATETIME", _cast_DateTime)
|
||||
ZINTERVAL = new_type((1186,), "ZINTERVAL", _cast_Interval)
|
||||
ZDATE = new_type((1082,), "ZDATE", _cast_Date)
|
||||
ZTIME = new_type((1083,), "ZTIME", _cast_Time)
|
||||
|
||||
|
|
|
@ -1,150 +1,61 @@
|
|||
##############################################################################
|
||||
# ZPsycopgDA/DABase.py - ZPsycopgDA Zope product: Database inspection
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
# 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.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
# 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.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
# 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.
|
||||
#
|
||||
# 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
|
||||
# See the LICENSE file for details.
|
||||
|
||||
$Id: DABase.py 400 2003-01-20 14:39:34Z fog $'''
|
||||
__version__='$Revision: 1.10 $'[11:-2]
|
||||
import sys
|
||||
import Shared.DC.ZRDB.Connection
|
||||
|
||||
|
||||
import Shared.DC.ZRDB.Connection, sys
|
||||
from App.Dialogs import MessageDialog
|
||||
from Globals import HTMLFile, ImageFile
|
||||
from db import DB
|
||||
from Globals import HTMLFile
|
||||
from ImageFile import ImageFile
|
||||
from ExtensionClass import Base
|
||||
import Acquisition
|
||||
from psycopg import NUMBER, ROWID, STRING, INTEGER, FLOAT
|
||||
from psycopg import BOOLEAN, DATETIME, LONGINTEGER
|
||||
from DateTime import DateTime
|
||||
|
||||
# import psycopg and functions/singletons needed for date/time conversions
|
||||
|
||||
import psycopg
|
||||
from psycopg.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN
|
||||
from psycopg import NUMBER, STRING, ROWID, DATETIME
|
||||
|
||||
|
||||
|
||||
class Connection(Shared.DC.ZRDB.Connection.Connection):
|
||||
_isAnSQLConnection = 1
|
||||
|
||||
info = None
|
||||
|
||||
manage_options=Shared.DC.ZRDB.Connection.Connection.manage_options+(
|
||||
{'label': 'Browse', 'action':'manage_browse'},
|
||||
# {'label': 'Design', 'action':'manage_tables'}
|
||||
)
|
||||
#manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + (
|
||||
# {'label': 'Browse', 'action':'manage_browse'},)
|
||||
|
||||
manage_tables = HTMLFile('tables',globals())
|
||||
manage_browse = HTMLFile('browse',globals())
|
||||
|
||||
info=None
|
||||
|
||||
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
|
||||
|
||||
finally: pass #print sys.exc_type, sys.exc_value
|
||||
#self._v_tpValues=r
|
||||
return r
|
||||
#manage_tables = HTMLFile('tables', globals())
|
||||
#manage_browse = HTMLFile('browse',globals())
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name=='tableNamed':
|
||||
if name == 'tableNamed':
|
||||
if not hasattr(self, '_v_tables'): self.tpValues()
|
||||
return self._v_tables.__of__(self)
|
||||
raise KeyError, name
|
||||
|
||||
|
||||
## old stuff from ZPsycopgDA 1.1 (never implemented) ##
|
||||
|
||||
def manage_wizard(self, tables):
|
||||
" "
|
||||
"Wizard of what? Oozing?"
|
||||
|
||||
def manage_join(self, tables, select_cols, join_cols, REQUEST=None):
|
||||
"""Create an SQL join"""
|
||||
|
@ -154,116 +65,3 @@ 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,105 +1,32 @@
|
|||
##############################################################################
|
||||
# ZPsycopgDA/__init__.py - ZPsycopgDA Zope product
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
# 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.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
# 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.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
# 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.
|
||||
#
|
||||
# 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
|
||||
# See the LICENSE file for details.
|
||||
|
||||
$Id: __init__.py 400 2003-01-20 14:39:34Z fog $'''
|
||||
__version__='$Revision: 1.11 $'[11:-2]
|
||||
__doc__ = "ZPsycopg Database Adalper Registration."
|
||||
__version__ = '2.0'
|
||||
|
||||
import sys, string
|
||||
import sys
|
||||
import string
|
||||
import DA
|
||||
|
||||
methods=DA.folder_methods
|
||||
methods = DA.folder_methods
|
||||
classes = DA.classes
|
||||
meta_types = DA.meta_types
|
||||
misc_ = DA.misc_
|
||||
|
||||
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')
|
||||
__ac_permissions__=DA.__ac_permissions__
|
||||
|
|
266
ZPsycopgDA/db.py
|
@ -1,171 +1,126 @@
|
|||
##############################################################################
|
||||
# ZPsycopgDA/db.py - query execution
|
||||
#
|
||||
# Zope Public License (ZPL) Version 1.0
|
||||
# -------------------------------------
|
||||
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
|
||||
#
|
||||
# Copyright (c) Digital Creations. All rights reserved.
|
||||
# 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.
|
||||
#
|
||||
# This license has been certified as Open Source(tm).
|
||||
# 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.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
# 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.
|
||||
#
|
||||
# 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]
|
||||
|
||||
# See the LICENSE file for details.
|
||||
|
||||
from Shared.DC.ZRDB.TM import TM
|
||||
from Shared.DC.ZRDB import dbi_db
|
||||
|
||||
import string, sys
|
||||
from string import strip, split, find
|
||||
from time import time
|
||||
from types import ListType
|
||||
import site
|
||||
|
||||
import psycopg
|
||||
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):
|
||||
import time
|
||||
import site
|
||||
import pool
|
||||
|
||||
import psycopg
|
||||
from psycopg.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN
|
||||
from psycopg import NUMBER, STRING, ROWID, DATETIME
|
||||
|
||||
|
||||
|
||||
# the DB object, managing all the real query work
|
||||
|
||||
class DB(TM, dbi_db.DB):
|
||||
|
||||
_p_oid = _p_changed = _registered = None
|
||||
|
||||
def __init__(self, connection, tilevel, enc='utf-8'):
|
||||
self.connection = connection
|
||||
def __init__(self, dsn, tilevel, enc='utf-8'):
|
||||
self.dsn = dsn
|
||||
self.tilevel = tilevel
|
||||
self.encoding = enc
|
||||
self.db = self.connect(self.connection)
|
||||
self.failures = 0
|
||||
self.calls = 0
|
||||
|
||||
def connect(self, connection):
|
||||
o = psycopg.connect(connection)
|
||||
o.set_isolation_level(int(self.tilevel))
|
||||
return o
|
||||
def getconn(self, create=True):
|
||||
conn = pool.getconn(self.dsn)
|
||||
conn.set_isolation_level(int(self.tilevel))
|
||||
return conn
|
||||
|
||||
def putconn(self, close=False):
|
||||
try:
|
||||
conn = pool.getconn(self.dsn, False)
|
||||
except AttributeError:
|
||||
pass
|
||||
pool.putconn(self.dsn, conn, close)
|
||||
|
||||
def getcursor(self):
|
||||
conn = self.getconn()
|
||||
return conn.cursor()
|
||||
|
||||
def _finish(self, *ignored):
|
||||
if hasattr(self, 'db') and self.db:
|
||||
self.db.commit()
|
||||
try:
|
||||
conn = self.getconn(False)
|
||||
conn.commit()
|
||||
self.putconn()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _abort(self, *ignored):
|
||||
if hasattr(self, 'db') and self.db:
|
||||
self.db.rollback()
|
||||
try:
|
||||
conn = self.getconn(False)
|
||||
conn.rollback()
|
||||
self.putconn()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
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 open(self):
|
||||
# this will create a new pool for our DSN if not already existing,
|
||||
# then get and immediately release a connection
|
||||
self.getconn()
|
||||
self.putconn()
|
||||
|
||||
def close(self):
|
||||
# FIXME: if this connection is closed we flush all the pool associated
|
||||
# with the current DSN; does this makes sense?
|
||||
pool.flushpool(self.dsn)
|
||||
|
||||
def sortKey(self):
|
||||
return 1
|
||||
|
||||
## tables and rows ##
|
||||
|
||||
def tables(self, rdb=0, _care=('TABLE', 'VIEW')):
|
||||
self._register()
|
||||
c = self._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
|
||||
c = self.getcursor()
|
||||
c.execute(
|
||||
"SELECT t.tablename AS NAME, 'TABLE' AS TYPE "
|
||||
" FROM pg_tables t WHERE tableowner <> 'postgres' "
|
||||
"UNION SELECT v.viewname AS NAME, 'VIEW' AS TYPE "
|
||||
" FROM pg_views v WHERE viewowner <> 'postgres' "
|
||||
"UNION SELECT t.tablename AS NAME, 'SYSTEM_TABLE\' AS TYPE "
|
||||
" FROM pg_tables t WHERE tableowner = 'postgres' "
|
||||
"UNION SELECT v.viewname AS NAME, 'SYSTEM_TABLE' AS TYPE "
|
||||
"FROM pg_views v WHERE viewowner = 'postgres'")
|
||||
res = []
|
||||
for name, typ in c.fetchall():
|
||||
if typ in _care:
|
||||
a({'TABLE_NAME': name, 'TABLE_TYPE': typ})
|
||||
c.close()
|
||||
return r
|
||||
res.append({'TABLE_NAME': name, 'TABLE_TYPE': typ})
|
||||
self.putconn()
|
||||
return res
|
||||
|
||||
def columns(self, table_name):
|
||||
self._register()
|
||||
c = self._cursor()
|
||||
c = self.getcursor()
|
||||
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 ()
|
||||
desc = c.description
|
||||
r = []
|
||||
a = r.append
|
||||
for name, type, width, ds, p, scale, null_ok in desc:
|
||||
res = []
|
||||
for name, type, width, ds, p, scale, null_ok in c.description:
|
||||
if type == NUMBER:
|
||||
if type == INTEGER:
|
||||
type = INTEGER
|
||||
|
@ -180,46 +135,50 @@ class DB(TM,dbi_db.DB):
|
|||
type = DATETIME
|
||||
else:
|
||||
type = STRING
|
||||
a({ 'Name': name,
|
||||
|
||||
res.append({'Name': name,
|
||||
'Type': type.name,
|
||||
'Precision': 0,
|
||||
'Scale': 0,
|
||||
'Nullable': 0})
|
||||
return r
|
||||
self.putconn()
|
||||
return res
|
||||
|
||||
## query execution ##
|
||||
|
||||
def query(self, query_string, max_rows=None, query_data=None):
|
||||
self._register()
|
||||
self.calls = self.calls+1
|
||||
|
||||
desc = ()
|
||||
result = []
|
||||
res = []
|
||||
nselects = 0
|
||||
|
||||
c = self._cursor()
|
||||
c = self.getcursor()
|
||||
|
||||
try:
|
||||
for qs in filter(None, map(strip, split(query_string, '\0'))):
|
||||
for qs in [x for x in query_string.split('\0') if x]:
|
||||
if type(qs) == unicode:
|
||||
if self.encoding:
|
||||
qs = qs.encode(self.encoding)
|
||||
try:
|
||||
if (query_data):
|
||||
r = c.execute(qs, query_data)
|
||||
c.execute(qs, query_data)
|
||||
else:
|
||||
r = c.execute(qs)
|
||||
except (psycopg.ProgrammingError,psycopg.IntegrityError), perr:
|
||||
if perr.args[0].find("concurrent update") > -1:
|
||||
c.execute(qs)
|
||||
except (psycopg.ProgrammingError, psycopg.IntegrityError), e:
|
||||
if e.args[0].find("concurrent update") > -1:
|
||||
raise ConflictError
|
||||
raise perr
|
||||
raise e
|
||||
if c.description is not None:
|
||||
nselects = nselects + 1
|
||||
nselects += 1
|
||||
if c.description != desc and nselects > 1:
|
||||
raise 'Query Error', \
|
||||
'Multiple select schema are not allowed'
|
||||
raise psycopg.ProgrammingError(
|
||||
'multiple selects in single query not allowed')
|
||||
if max_rows:
|
||||
result = c.fetchmany(max_rows)
|
||||
res = c.fetchmany(max_rows)
|
||||
else:
|
||||
result = c.fetchall()
|
||||
res = c.fetchall()
|
||||
desc = c.description
|
||||
self.failures = 0
|
||||
|
||||
|
@ -247,13 +206,4 @@ class DB(TM,dbi_db.DB):
|
|||
'null': null_ok,
|
||||
})
|
||||
|
||||
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
|
||||
return items, res
|
||||
|
|
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 |