Undo of wrong commit of 1.1.x source code over 2.x.
5
AUTHORS
|
@ -1,9 +1,8 @@
|
||||||
Main authors:
|
Main authors:
|
||||||
Michele Comitini <mcm@initd.org>
|
|
||||||
Federico Di Gregorio <fog@debian.org>
|
Federico Di Gregorio <fog@debian.org>
|
||||||
|
|
||||||
For the win32 port:
|
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:
|
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
|
While psycopg 1.x used autoconf for its build process psycopg 2 switched to
|
||||||
installing make sure you read carefully the "Install" section in the
|
the more pythoning setup.py. Currently both psycopg's author and distutils
|
||||||
README file.
|
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
|
python setup.py build
|
||||||
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').
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
to build in the local directory; and:
|
||||||
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.
|
|
||||||
|
|
||||||
The file `configure.in' is used to create `configure' by a program
|
python setup.py install
|
||||||
called `autoconf'. You only need `configure.in' if you want to change
|
|
||||||
it or regenerate `configure' using a newer version of `autoconf'.
|
|
||||||
|
|
||||||
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
|
* Fixed two memory leaks: one in cursor deallocation and one in row
|
||||||
number of affected columns.
|
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
|
* ZPsycopgDA back in and working using the new pooling code.
|
||||||
still no way to give it extra data from inside a ZSQL Method.)
|
|
||||||
|
|
||||||
* 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
|
What's new in psycopg 1.99.8
|
||||||
aficionado runs on Debian ;-P )
|
----------------------------
|
||||||
|
|
||||||
* 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
|
* solved the rounding errors in time conversions.
|
||||||
instead of a DateTime. This is much better because you can now add two
|
|
||||||
times and a time and a date.
|
|
||||||
|
|
||||||
* Added an "sslmode" parameter (look at PostgreSQL documentation for
|
* now cursors support .fileno() and .isready() methods, to be used in
|
||||||
possible values.)
|
select() calls.
|
||||||
|
|
||||||
* .execute() now rise the right exception if called with a wrong
|
* .copy_from() and .copy_in() methods are back in (still using the old
|
||||||
tuple/dict. Also, %% in queries does not raise an exception anymore.
|
protocol, will be updated to use new one in next releasae.)
|
||||||
|
|
||||||
* Updated RPM specs (thanks to Mark McClain we now have updated RPMs on
|
* fixed memory corruption bug reported on win32 platform.
|
||||||
initd.org too.)
|
|
||||||
|
|
||||||
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
|
* added support for tzinfo objects in datetime.timestamp objects: the
|
||||||
an exception.
|
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
|
What's new in psycopg 1.99.6
|
||||||
to determine exception type (unfortunately the old string compare method
|
----------------------------
|
||||||
is still neede for postgresql <= 7.3.x.)
|
|
||||||
|
|
||||||
* 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
|
* included various win32/MSVC fixes (pthread.h changes, winsock2
|
||||||
(QinetiQ Plc)!
|
library, include path in setup.py, etc.)
|
||||||
|
|
||||||
* Problems with sequences and mappings non correctly used in .execute()
|
* ported interval fixes from 1.1.14/1.1.15.
|
||||||
should be gone (mogrification code completely rewritten.) Many thanks
|
|
||||||
to Richard Taylor and Vsevolod Lobko that helped by testing the "pre"
|
|
||||||
releases.
|
|
||||||
|
|
||||||
* 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
|
* connection objects now have a .dsn read-only attribute that holds the
|
||||||
dictionaries.
|
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
|
* added example: dt.py.
|
||||||
you need strings with embedded NULs.
|
|
||||||
|
|
||||||
* 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
|
* added .set_client_encoding() method on the connection object.
|
||||||
compatible change for people that really want to continue executing queries
|
|
||||||
after an exception.
|
|
||||||
|
|
||||||
* fixed problem with dictionary mogrification (i.e., specifying the same key
|
* added examples: encoding.py, binary.py, lastrowid.py.
|
||||||
multiple times and having the None value in the dict should work now.)
|
|
||||||
|
|
||||||
* fixed keeper status trashing problem: no more psycopg stuck in transaction
|
What's new in psycopg 1.99.2
|
||||||
(maybe this will also solve ZPsycopgDA problems: will see...)
|
----------------------------
|
||||||
|
|
||||||
* now copy_from and copy_to can be passed instances of classes with "readline"
|
* better typecasting:
|
||||||
and "write" methods and not only file instances.
|
- 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,
|
* splitted QuotedString objects from mx stuff;
|
||||||
user and password (they are all strings, even "port".)
|
|
||||||
|
|
||||||
* connection.set_isolation_level() implemented to help switching from default
|
* dropped autotools and moved to pythonic setup.py (needs work.)
|
||||||
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,145 +1,26 @@
|
||||||
psycopg - Python-PostgreSQL Database Adapter
|
psycopg - Python-PostgreSQL Database Adapter
|
||||||
********************************************
|
********************************************
|
||||||
|
|
||||||
psycopg is a PostgreSQL database adapter for the Python programming language
|
psycopg is a PostgreSQL database adapter for the Python programming
|
||||||
(just like pygresql and popy.) It was written from scratch with the aim of
|
language. This is version 2, a complete rewrite of the original code to
|
||||||
being very small and fast, and stable as a rock. The main advantages of
|
provide new-style classes for connection and cursor objects and other sweet
|
||||||
psycopg are that it supports (well... *will* support) the full Python
|
candies. Like the original, psycopg 2 was written with the aim of being
|
||||||
DBAPI-2.0 and being thread safe at level 2.
|
very small and fast, and stable as a rock.
|
||||||
|
|
||||||
psycopg is different from the other database adapter because it was designed
|
psycopg is different from the other database adapter because it was
|
||||||
for heavily multi-threaded applications that create and destroy lots of
|
designed for heavily multi-threaded applications that create and destroy
|
||||||
cursors and make a conspicuous number of concurrent INSERTs or UPDATEs.
|
lots of cursors and make a conspicuous number of concurrent INSERTs or
|
||||||
Every open Python connection keeps a pool of real (UNIX or TCP/IP) connections
|
UPDATEs. psycopg 2 also provide full asycronous operations for the really
|
||||||
to the database. Every time a new cursor is created, a new connection does not
|
brave programmer.
|
||||||
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 now support the Python DBAPI-2.0 completely. There are confirmed
|
There are confirmed reports of psycopg 1.x compiling and running on Linux
|
||||||
reports of psycopg compiling and running on Linux and FreeBSD on i386, Solaris
|
and FreeBSD on i386, Solaris, MacOS X and win32 architectures. psycopg 2
|
||||||
and MacOS X.
|
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
|
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
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version. See file COPYING for details.
|
(at your option) any later version. See file COPYING for details.
|
||||||
|
|
||||||
As a special exception, specific permission is granted for the GPLed
|
As a special exception, specific permission is granted for the GPLed code in
|
||||||
code in this distribition to be linked to OpenSSL and PostgreSQL libpq
|
this distribition to be linked to OpenSSL and PostgreSQL libpq without
|
||||||
without invoking GPL clause 2(b).
|
invoking GPL clause 2(b).
|
||||||
|
|
||||||
If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e.,
|
If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e., every
|
||||||
every file inside the ZPsycopgDA directory) user the ZPL license as
|
file inside the ZPsycopgDA directory) under the ZPL license as published on
|
||||||
published on the Zope web site, http://www.zope.org/Resources/ZPL.
|
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.
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
427
ZPsycopgDA/DA.py
|
@ -1,128 +1,171 @@
|
||||||
##############################################################################
|
# 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
|
# This program is distributed in the hope that it will be useful, but
|
||||||
# modification, are permitted provided that the following conditions are
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
|
||||||
# met:
|
# or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
#
|
#
|
||||||
# 1. Redistributions in source code must retain the above copyright
|
# See the LICENSE file for details.
|
||||||
# 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 db import DB
|
||||||
import Shared.DC.ZRDB.Connection, sys, DABase, time
|
from Globals import DTMLFile
|
||||||
from Globals import HTMLFile, ImageFile
|
from Globals import HTMLFile
|
||||||
|
from ImageFile import ImageFile
|
||||||
from ExtensionClass import Base
|
from ExtensionClass import Base
|
||||||
from string import find, join, split, rindex
|
from DateTime import DateTime
|
||||||
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
|
|
||||||
|
|
||||||
manage_addZPsycopgConnectionForm = HTMLFile('connectionAdd', globals())
|
# import psycopg and functions/singletons needed for date/time conversions
|
||||||
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
|
||||||
|
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):
|
# add a new connection to a folder
|
||||||
|
|
||||||
|
manage_addZPsycopgConnectionForm = DTMLFile('dtml/add',globals())
|
||||||
|
|
||||||
|
def manage_addZPsycopgConnection(self, id, title, connection_string,
|
||||||
|
zdatetime=None, tilevel=2,
|
||||||
|
check=None, REQUEST=None):
|
||||||
|
"""Add a DB connection to a folder."""
|
||||||
|
self._setObject(id, Connection(id, title, connection_string,
|
||||||
|
zdatetime, check, tilevel))
|
||||||
|
if REQUEST is not None: return self.manage_main(self, REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# the connection object
|
||||||
|
|
||||||
|
class Connection(DABase.Connection):
|
||||||
|
"""ZPsycopg Connection."""
|
||||||
|
id = 'Psycopg_database_connection'
|
||||||
|
database_type = 'Psycopg'
|
||||||
|
meta_type = title = 'Z Psycopg Database Connection'
|
||||||
|
icon = 'misc_/ZPsycopg/conn'
|
||||||
|
|
||||||
|
def __init__(self, id, title, connection_string,
|
||||||
|
zdatetime, check=None, tilevel=2, encoding=''):
|
||||||
|
self.zdatetime = zdatetime
|
||||||
|
self.id = str(id)
|
||||||
|
self.edit(title, connection_string, zdatetime,
|
||||||
|
check=check, tilevel=tilevel, encoding=encoding)
|
||||||
|
|
||||||
|
def factory(self):
|
||||||
|
return DB
|
||||||
|
|
||||||
|
def table_info(self):
|
||||||
|
return self._v_database_connection.table_info()
|
||||||
|
|
||||||
|
def edit(self, title, connection_string,
|
||||||
|
zdatetime, check=None, tilevel=2, encoding=''):
|
||||||
|
self.title = title
|
||||||
|
self.connection_string = connection_string
|
||||||
|
self.zdatetime = zdatetime
|
||||||
|
self.tilevel = tilevel
|
||||||
|
self.encoding = encoding
|
||||||
|
|
||||||
|
self.set_type_casts()
|
||||||
|
|
||||||
|
if check: self.connect(self.connection_string)
|
||||||
|
|
||||||
|
manage_properties = DTMLFile('dtml/edit', globals())
|
||||||
|
|
||||||
|
def manage_edit(self, title, connection_string,
|
||||||
|
zdatetime=None, check=None, tilevel=2, encoding='UTF-8',
|
||||||
|
REQUEST=None):
|
||||||
|
"""Edit the DB connection."""
|
||||||
|
self.edit(title, connection_string, zdatetime,
|
||||||
|
check=check, tilevel=tilevel, encoding=encoding)
|
||||||
|
if REQUEST is not None:
|
||||||
|
msg = "Connection edited."
|
||||||
|
return self.manage_main(self,REQUEST,manage_tabs_message=msg)
|
||||||
|
|
||||||
|
def connect(self, s):
|
||||||
|
try:
|
||||||
|
self._v_database_connection.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# check psycopg version and raise exception if does not match
|
||||||
|
if psycopg.__version__ not in ALLOWED_PSYCOPG_VERSIONS:
|
||||||
|
raise ImportError("psycopg version mismatch (imported %s)" +
|
||||||
|
psycopg.__version__)
|
||||||
|
|
||||||
|
self.set_type_casts()
|
||||||
|
self._v_connected = ''
|
||||||
|
dbf = self.factory()
|
||||||
|
|
||||||
|
# TODO: let the psycopg exception propagate, or not?
|
||||||
|
self._v_database_connection = dbf(
|
||||||
|
self.connection_string, self.tilevel, self.encoding)
|
||||||
|
self._v_database_connection.open()
|
||||||
|
self._v_connected = DateTime()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def set_type_casts(self):
|
||||||
|
# note that in both cases order *is* important
|
||||||
|
if self.zdatetime:
|
||||||
|
# use zope internal datetime routines
|
||||||
|
register_type(ZDATETIME)
|
||||||
|
register_type(ZDATE)
|
||||||
|
register_type(ZTIME)
|
||||||
|
register_type(ZINTERVAL)
|
||||||
|
else:
|
||||||
|
# use the standard
|
||||||
|
register_type(DATETIME)
|
||||||
|
register_type(DATE)
|
||||||
|
register_type(TIME)
|
||||||
|
register_type(INTERVAL)
|
||||||
|
|
||||||
|
# database connection registration data
|
||||||
|
|
||||||
|
classes = (Connection,)
|
||||||
|
|
||||||
|
meta_types = ({'name':'Z Psycopg Database Connection',
|
||||||
|
'action':'manage_addZPsycopgConnectionForm'},)
|
||||||
|
|
||||||
|
folder_methods = {
|
||||||
|
'manage_addZPsycopgConnection': manage_addZPsycopgConnection,
|
||||||
|
'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm}
|
||||||
|
|
||||||
|
__ac_permissions__ = (
|
||||||
|
('Add Z Psycopg Database Connections',
|
||||||
|
('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),)
|
||||||
|
|
||||||
|
# add icons
|
||||||
|
|
||||||
|
misc_={'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')}
|
||||||
|
|
||||||
|
for icon in ('table', 'view', 'stable', 'what', 'field', 'text', 'bin',
|
||||||
|
'int', 'float', 'date', 'time', 'datetime'):
|
||||||
|
misc_[icon] = ImageFile('icons/%s.gif' % icon, globals())
|
||||||
|
|
||||||
|
# zope-specific psycopg typecasters
|
||||||
|
|
||||||
|
# convert an ISO timestamp string from postgres to a Zope DateTime object
|
||||||
|
def _cast_DateTime(str):
|
||||||
if str:
|
if str:
|
||||||
# this will split us into [date, time, GMT/AM/PM(if there)]
|
# this will split us into [date, time, GMT/AM/PM(if there)]
|
||||||
dt = split(str, ' ')
|
dt = split(str, ' ')
|
||||||
|
@ -130,158 +173,30 @@ def cast_DateTime(str):
|
||||||
# we now should split out any timezone info
|
# we now should split out any timezone info
|
||||||
dt[1] = split(dt[1], '-')[0]
|
dt[1] = split(dt[1], '-')[0]
|
||||||
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'))
|
return DateTime(join(dt[:2], ' '))
|
||||||
else:
|
else:
|
||||||
t = time.mktime(time.strptime(dt[0], '%Y-%m-%d %H:%M:%S'))
|
return DateTime(dt[0])
|
||||||
return DateTime(t)
|
|
||||||
|
|
||||||
# Convert an ISO date string from postgres to a DateTime(zope version)
|
# convert an ISO date string from postgres to a Zope DateTime object
|
||||||
# object.
|
def _cast_Date(str):
|
||||||
def cast_Date(str):
|
|
||||||
if str:
|
if str:
|
||||||
return DateTime(time.mktime(time.strptime(str, '%Y-%m-%d')))
|
return DateTime(str)
|
||||||
|
|
||||||
# Convert a time string from postgres to a DateTime(zope version) object.
|
# Convert a time string from postgres to a Zope DateTime object.
|
||||||
# WARNING: We set the day as today before feeding to DateTime so
|
# NOTE: we set the day as today before feeding to DateTime so
|
||||||
# that it has the same DST settings.
|
# that it has the same DST settings.
|
||||||
def cast_Time(str):
|
def _cast_Time(str):
|
||||||
if str:
|
if str:
|
||||||
return DateTime(time.strftime('%Y-%m-%d %H:%M:%S',
|
return DateTime(time.strftime('%Y-%m-%d %H:%M:%S',
|
||||||
time.localtime(time.time())[:3]+
|
time.localtime(time.time())[:3]+
|
||||||
time.strptime(str[:8], "%H:%M:%S")[3:]))
|
time.strptime(str[:8], "%H:%M:%S")[3:]))
|
||||||
|
|
||||||
# Convert a time string from postgres to a DateTime(zope version) object.
|
# TODO: DateTime does not support intervals: what's the best we can do?
|
||||||
# WARNING: We set the day as the epoch day (1970-01-01) since this
|
def _cast_Interval(str):
|
||||||
# DateTime does not support time deltas. (EXPERIMENTAL USE WITH CARE!)
|
|
||||||
def cast_Interval(str):
|
|
||||||
return 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)
|
||||||
|
|
||||||
class Connection(DABase.Connection):
|
|
||||||
"The connection class."
|
|
||||||
database_type = database_type
|
|
||||||
id = '%s_database_connection' % database_type
|
|
||||||
meta_type = title = 'Z %s Database Connection' % database_type
|
|
||||||
icon = 'misc_/Z%sDA/conn' % database_type
|
|
||||||
|
|
||||||
def __init__(self, id, title, connection_string, zdatetime,
|
|
||||||
check=None, tilevel=2, encoding='UTF-8'):
|
|
||||||
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
|
|
||||||
|
|
||||||
# check psycopg version and raise exception if does not match
|
|
||||||
if psycopg.__version__ not in __psycopg_versions__:
|
|
||||||
raise ImportError("psycopg version mismatch: " +
|
|
||||||
psycopg.__version__)
|
|
||||||
|
|
||||||
self.set_type_casts()
|
|
||||||
self._v_connected=''
|
|
||||||
DB=self.factory()
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
# this is necessary when upgrading from old installs without
|
|
||||||
# having to recreate the connection object
|
|
||||||
if not hasattr(self, 'tilevel'):
|
|
||||||
self.tilevel = 2
|
|
||||||
if not hasattr(self, 'encoding'):
|
|
||||||
self.encoding = 'UTF-8'
|
|
||||||
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 sql_quote__(self, v):
|
|
||||||
# quote dictionary
|
|
||||||
quote_dict = {"\'": "''", "\\": "\\\\"}
|
|
||||||
for dkey in quote_dict.keys():
|
|
||||||
if find(v, dkey) >= 0:
|
|
||||||
v=join(split(v,dkey),quote_dict[dkey])
|
|
||||||
return "'%s'" % v
|
|
||||||
|
|
||||||
|
|
||||||
classes = ('DA.Connection',)
|
|
||||||
|
|
||||||
meta_types=(
|
|
||||||
{'name':'Z %s Database Connection' % database_type,
|
|
||||||
'action':'manage_addZ%sConnectionForm' % database_type},)
|
|
||||||
|
|
||||||
folder_methods={
|
|
||||||
'manage_addZPsycopgConnection': manage_addZPsycopgConnection,
|
|
||||||
'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm}
|
|
||||||
|
|
||||||
__ac_permissions__=(
|
|
||||||
('Add Z Psycopg Database Connections',
|
|
||||||
('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),)
|
|
||||||
|
|
||||||
misc_={
|
|
||||||
'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')}
|
|
||||||
|
|
||||||
for icon in ('table', 'view', 'stable', 'what',
|
|
||||||
'field', 'text','bin','int','float',
|
|
||||||
'date','time','datetime'):
|
|
||||||
misc_[icon] = ImageFile('icons/%s.gif' % icon, globals())
|
|
||||||
|
|
|
@ -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
|
# This program is distributed in the hope that it will be useful, but
|
||||||
# modification, are permitted provided that the following conditions are
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
|
||||||
# met:
|
# or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
#
|
#
|
||||||
# 1. Redistributions in source code must retain the above copyright
|
# See the LICENSE file for details.
|
||||||
# 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
|
|
||||||
|
|
||||||
$Id: DABase.py 400 2003-01-20 14:39:34Z fog $'''
|
import sys
|
||||||
__version__='$Revision: 1.10 $'[11:-2]
|
import Shared.DC.ZRDB.Connection
|
||||||
|
|
||||||
|
from db import DB
|
||||||
import Shared.DC.ZRDB.Connection, sys
|
from Globals import HTMLFile
|
||||||
from App.Dialogs import MessageDialog
|
from ImageFile import ImageFile
|
||||||
from Globals import HTMLFile, ImageFile
|
|
||||||
from ExtensionClass import Base
|
from ExtensionClass import Base
|
||||||
import Acquisition
|
from DateTime import DateTime
|
||||||
from psycopg import NUMBER, ROWID, STRING, INTEGER, FLOAT
|
|
||||||
from psycopg import BOOLEAN, DATETIME, LONGINTEGER
|
# 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):
|
class Connection(Shared.DC.ZRDB.Connection.Connection):
|
||||||
_isAnSQLConnection = 1
|
_isAnSQLConnection = 1
|
||||||
|
|
||||||
|
info = None
|
||||||
|
|
||||||
manage_options=Shared.DC.ZRDB.Connection.Connection.manage_options+(
|
#manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + (
|
||||||
{'label': 'Browse', 'action':'manage_browse'},
|
# {'label': 'Browse', 'action':'manage_browse'},)
|
||||||
# {'label': 'Design', 'action':'manage_tables'}
|
|
||||||
)
|
|
||||||
|
|
||||||
manage_tables = HTMLFile('tables',globals())
|
#manage_tables = HTMLFile('tables', globals())
|
||||||
manage_browse = HTMLFile('browse',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
|
|
||||||
|
|
||||||
def __getitem__(self, name):
|
def __getitem__(self, name):
|
||||||
if name=='tableNamed':
|
if name == 'tableNamed':
|
||||||
if not hasattr(self, '_v_tables'): self.tpValues()
|
if not hasattr(self, '_v_tables'): self.tpValues()
|
||||||
return self._v_tables.__of__(self)
|
return self._v_tables.__of__(self)
|
||||||
raise KeyError, name
|
raise KeyError, name
|
||||||
|
|
||||||
|
|
||||||
|
## old stuff from ZPsycopgDA 1.1 (never implemented) ##
|
||||||
|
|
||||||
def manage_wizard(self, tables):
|
def manage_wizard(self, tables):
|
||||||
" "
|
"Wizard of what? Oozing?"
|
||||||
|
|
||||||
def manage_join(self, tables, select_cols, join_cols, REQUEST=None):
|
def manage_join(self, tables, select_cols, join_cols, REQUEST=None):
|
||||||
"""Create an SQL join"""
|
"""Create an SQL join"""
|
||||||
|
@ -154,116 +65,3 @@ class Connection(Shared.DC.ZRDB.Connection.Connection):
|
||||||
|
|
||||||
def manage_update(self, table, keys, cols, REQUEST=None):
|
def manage_update(self, table, keys, cols, REQUEST=None):
|
||||||
"""Create an SQL update"""
|
"""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
|
# This program is distributed in the hope that it will be useful, but
|
||||||
# modification, are permitted provided that the following conditions are
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
|
||||||
# met:
|
# or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
#
|
#
|
||||||
# 1. Redistributions in source code must retain the above copyright
|
# See the LICENSE file for details.
|
||||||
# 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
|
|
||||||
|
|
||||||
$Id: __init__.py 400 2003-01-20 14:39:34Z fog $'''
|
__doc__ = "ZPsycopg Database Adalper Registration."
|
||||||
__version__='$Revision: 1.11 $'[11:-2]
|
__version__ = '2.0'
|
||||||
|
|
||||||
import sys, string
|
import sys
|
||||||
|
import string
|
||||||
import DA
|
import DA
|
||||||
|
|
||||||
methods=DA.folder_methods
|
methods = DA.folder_methods
|
||||||
misc_ = DA.misc_
|
classes = DA.classes
|
||||||
|
meta_types = DA.meta_types
|
||||||
|
misc_ = DA.misc_
|
||||||
|
|
||||||
def initialize(context):
|
__ac_permissions__=DA.__ac_permissions__
|
||||||
"""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')
|
|
||||||
|
|
274
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
|
# This program is distributed in the hope that it will be useful, but
|
||||||
# modification, are permitted provided that the following conditions are
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
|
||||||
# met:
|
# or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
#
|
#
|
||||||
# 1. Redistributions in source code must retain the above copyright
|
# See the LICENSE file for details.
|
||||||
# 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.TM import TM
|
||||||
from Shared.DC.ZRDB import dbi_db
|
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
|
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
|
_p_oid = _p_changed = _registered = None
|
||||||
|
|
||||||
def __init__(self, connection, tilevel, enc='utf-8'):
|
def __init__(self, dsn, tilevel, enc='utf-8'):
|
||||||
self.connection = connection
|
self.dsn = dsn
|
||||||
self.tilevel = tilevel
|
self.tilevel = tilevel
|
||||||
self.encoding = enc
|
self.encoding = enc
|
||||||
self.db = self.connect(self.connection)
|
|
||||||
self.failures = 0
|
self.failures = 0
|
||||||
self.calls = 0
|
self.calls = 0
|
||||||
|
|
||||||
def connect(self, connection):
|
def getconn(self, create=True):
|
||||||
o = psycopg.connect(connection)
|
conn = pool.getconn(self.dsn)
|
||||||
o.set_isolation_level(int(self.tilevel))
|
conn.set_isolation_level(int(self.tilevel))
|
||||||
return o
|
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):
|
def _finish(self, *ignored):
|
||||||
if hasattr(self, 'db') and self.db:
|
try:
|
||||||
self.db.commit()
|
conn = self.getconn(False)
|
||||||
|
conn.commit()
|
||||||
|
self.putconn()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def _abort(self, *ignored):
|
def _abort(self, *ignored):
|
||||||
if hasattr(self, 'db') and self.db:
|
try:
|
||||||
self.db.rollback()
|
conn = self.getconn(False)
|
||||||
|
conn.rollback()
|
||||||
|
self.putconn()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def _cursor(self):
|
def open(self):
|
||||||
"""Obtains a cursor in a safe way."""
|
# this will create a new pool for our DSN if not already existing,
|
||||||
if not hasattr(self, 'db') or not self.db:
|
# then get and immediately release a connection
|
||||||
self.db = self.connect(self.connection)
|
self.getconn()
|
||||||
return self.db.cursor()
|
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')):
|
def tables(self, rdb=0, _care=('TABLE', 'VIEW')):
|
||||||
self._register()
|
self._register()
|
||||||
c = self._cursor()
|
c = self.getcursor()
|
||||||
c.execute('SELECT t.tablename AS NAME, '
|
c.execute(
|
||||||
'\'TABLE\' AS TYPE FROM pg_tables t '
|
"SELECT t.tablename AS NAME, 'TABLE' AS TYPE "
|
||||||
'WHERE tableowner <> \'postgres\' '
|
" FROM pg_tables t WHERE tableowner <> 'postgres' "
|
||||||
'UNION SELECT v.viewname AS NAME, '
|
"UNION SELECT v.viewname AS NAME, 'VIEW' AS TYPE "
|
||||||
'\'VIEW\' AS TYPE FROM pg_views v '
|
" FROM pg_views v WHERE viewowner <> 'postgres' "
|
||||||
'WHERE viewowner <> \'postgres\' '
|
"UNION SELECT t.tablename AS NAME, 'SYSTEM_TABLE\' AS TYPE "
|
||||||
'UNION SELECT t.tablename AS NAME, '
|
" FROM pg_tables t WHERE tableowner = 'postgres' "
|
||||||
'\'SYSTEM_TABLE\' AS TYPE FROM pg_tables t '
|
"UNION SELECT v.viewname AS NAME, 'SYSTEM_TABLE' AS TYPE "
|
||||||
'WHERE tableowner = \'postgres\' '
|
"FROM pg_views v WHERE viewowner = 'postgres'")
|
||||||
'UNION SELECT v.viewname AS NAME, '
|
res = []
|
||||||
'\'SYSTEM_TABLE\' AS TYPE FROM pg_views v '
|
|
||||||
'WHERE viewowner = \'postgres\' ' )
|
|
||||||
r = []
|
|
||||||
a = r.append
|
|
||||||
for name, typ in c.fetchall():
|
for name, typ in c.fetchall():
|
||||||
if typ in _care:
|
if typ in _care:
|
||||||
a({'TABLE_NAME': name, 'TABLE_TYPE': typ})
|
res.append({'TABLE_NAME': name, 'TABLE_TYPE': typ})
|
||||||
c.close()
|
self.putconn()
|
||||||
return r
|
return res
|
||||||
|
|
||||||
def columns(self, table_name):
|
def columns(self, table_name):
|
||||||
self._register()
|
self._register()
|
||||||
c = self._cursor()
|
c = self.getcursor()
|
||||||
try:
|
try:
|
||||||
r = c.execute('select * from "%s" where 1=0' % table_name)
|
r = c.execute('SELECT * FROM "%s" WHERE 1=0' % table_name)
|
||||||
except:
|
except:
|
||||||
return ()
|
return ()
|
||||||
desc = c.description
|
res = []
|
||||||
r = []
|
for name, type, width, ds, p, scale, null_ok in c.description:
|
||||||
a = r.append
|
|
||||||
for name, type, width, ds, p, scale, null_ok in desc:
|
|
||||||
if type == NUMBER:
|
if type == NUMBER:
|
||||||
if type == INTEGER:
|
if type == INTEGER:
|
||||||
type = INTEGER
|
type = INTEGER
|
||||||
|
@ -180,46 +135,50 @@ class DB(TM,dbi_db.DB):
|
||||||
type = DATETIME
|
type = DATETIME
|
||||||
else:
|
else:
|
||||||
type = STRING
|
type = STRING
|
||||||
a({ 'Name': name,
|
|
||||||
'Type': type.name,
|
res.append({'Name': name,
|
||||||
'Precision': 0,
|
'Type': type.name,
|
||||||
'Scale': 0,
|
'Precision': 0,
|
||||||
'Nullable': 0})
|
'Scale': 0,
|
||||||
return r
|
'Nullable': 0})
|
||||||
|
self.putconn()
|
||||||
|
return res
|
||||||
|
|
||||||
|
## query execution ##
|
||||||
|
|
||||||
def query(self, query_string, max_rows=None, query_data=None):
|
def query(self, query_string, max_rows=None, query_data=None):
|
||||||
self._register()
|
self._register()
|
||||||
self.calls = self.calls+1
|
self.calls = self.calls+1
|
||||||
|
|
||||||
desc = ()
|
desc = ()
|
||||||
result = []
|
res = []
|
||||||
nselects = 0
|
nselects = 0
|
||||||
|
|
||||||
c = self._cursor()
|
c = self.getcursor()
|
||||||
|
|
||||||
try:
|
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 type(qs) == unicode:
|
||||||
if self.encoding:
|
if self.encoding:
|
||||||
qs = qs.encode(self.encoding)
|
qs = qs.encode(self.encoding)
|
||||||
try:
|
try:
|
||||||
if (query_data):
|
if (query_data):
|
||||||
r = c.execute(qs, query_data)
|
c.execute(qs, query_data)
|
||||||
else:
|
else:
|
||||||
r = c.execute(qs)
|
c.execute(qs)
|
||||||
except (psycopg.ProgrammingError,psycopg.IntegrityError), perr:
|
except (psycopg.ProgrammingError, psycopg.IntegrityError), e:
|
||||||
if perr.args[0].find("concurrent update") > -1:
|
if e.args[0].find("concurrent update") > -1:
|
||||||
raise ConflictError
|
raise ConflictError
|
||||||
raise perr
|
raise e
|
||||||
if c.description is not None:
|
if c.description is not None:
|
||||||
nselects = nselects + 1
|
nselects += 1
|
||||||
if c.description != desc and nselects > 1:
|
if c.description != desc and nselects > 1:
|
||||||
raise 'Query Error', \
|
raise psycopg.ProgrammingError(
|
||||||
'Multiple select schema are not allowed'
|
'multiple selects in single query not allowed')
|
||||||
if max_rows:
|
if max_rows:
|
||||||
result = c.fetchmany(max_rows)
|
res = c.fetchmany(max_rows)
|
||||||
else:
|
else:
|
||||||
result = c.fetchall()
|
res = c.fetchall()
|
||||||
desc = c.description
|
desc = c.description
|
||||||
self.failures = 0
|
self.failures = 0
|
||||||
|
|
||||||
|
@ -247,13 +206,4 @@ class DB(TM,dbi_db.DB):
|
||||||
'null': null_ok,
|
'null': null_ok,
|
||||||
})
|
})
|
||||||
|
|
||||||
return items, result
|
return items, res
|
||||||
|
|
||||||
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 |