Undo of wrong commit of 1.1.x source code over 2.x.

This commit is contained in:
Federico Di Gregorio 2004-10-29 16:15:45 +00:00
parent c89f821126
commit 091270db2a
15 changed files with 807 additions and 3361 deletions

View File

@ -1,9 +1,8 @@
Main authors:
Michele Comitini <mcm@initd.org>
Federico Di Gregorio <fog@debian.org>
For the win32 port:
Jason Erickson <jerickso@indian.com>
Jason Erickson <jerickso@indian.com> (most of his changes are still in 2.0)
Additional Help:
Tom Jenkins <tjenkins@devis.com> (COPY FROM/COPY TO backport)

2248
ChangeLog

File diff suppressed because it is too large Load Diff

190
INSTALL
View File

@ -1,184 +1,18 @@
Basic Installation
==================
Compiling and installing psycopg
********************************
These are generic installation instructions. Before building and
installing make sure you read carefully the "Install" section in the
README file.
While psycopg 1.x used autoconf for its build process psycopg 2 switched to
the more pythoning setup.py. Currently both psycopg's author and distutils
have some limitations so the file setup.cfg is almost unused and most build
options are hidden in setup.py. Before building psycopg look at the very
first lines of setup.py and change any settings to follow your system (or
taste); then:
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
python setup.py build
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
to build in the local directory; and:
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
python setup.py install
The simplest way to compile this package is:
to install system-wide.
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

404
NEWS
View File

@ -1,355 +1,155 @@
psycopg news for 1.1.15
-----------------------
What's new in psycopg 1.99.10
-----------------------------
* Interval typecasting eventually-eventually works the Right Way (TM).
* The adapt() function now fully supports the adaptation protocol
described in PEP 246. Note that the adapters registry now is indexed
by (type, protocol) and not by type alone. Change your adapters
accordingly.
* Fixed two bad memory leaks in QuotedString and Binary objects.
* More configuration options moved from setup.py to setup.cfg.
* Reverted change on rowcount attribute, now it is always set to the real
number of affected columns.
* Fixed two memory leaks: one in cursor deallocation and one in row
fetching (.fetchXXX() methods.)
psycopg news for 1.1.14
-----------------------
What's new in psycopg 1.99.9
----------------------------
* Interval typecasting eventually works the Right Way (TM).
* Added simple pooling code (psycopg.pool module); see the reworked
examples/threads.py for example code.
* ZPsycopgDA now support unicode strings and different backend encodings.
* Added DECIMAL typecaster to convert postgresql DECIMAL and NUMERIC
types (i.e, all types with an OID of NUMERICOID.) Note that the
DECIMAL typecaster does not set scale and precision on the created
objects but uses Python defaults.
* ZPsycopgDA accept query data as an extra parameter to execute() (but
still no way to give it extra data from inside a ZSQL Method.)
* ZPsycopgDA back in and working using the new pooling code.
* Better DBAPI-2.0 compliance (rowcount attribute and argument passing.)
* Isn't that enough? :)
* Now builds on Fedora Core 2 (but remember that the real psycopg
aficionado runs on Debian ;-P )
What's new in psycopg 1.99.8
----------------------------
* COPY FROM raise an exception and return usefull information on error.
* added support for UNICODE queries.
psycopg news for 1.1.13
-----------------------
* added UNICODE typecaster; to activate it just do:
* ZPsycopgDA works again.
psycopg.extensions.register_type(psycopg.extensions.UNICODE)
psycopg news for 1.1.12
-----------------------
Note that the UNICODE typecaster override the STRING one, so it is
not activated by default.
* Fixed nasty segfault/deadlock in switch_isolation_level.
* cursors now really support the iterator protocol.
* Now the PostgreSQL TIME type is correctly converted to a DateTimeDelta
instead of a DateTime. This is much better because you can now add two
times and a time and a date.
* solved the rounding errors in time conversions.
* Added an "sslmode" parameter (look at PostgreSQL documentation for
possible values.)
* now cursors support .fileno() and .isready() methods, to be used in
select() calls.
* .execute() now rise the right exception if called with a wrong
tuple/dict. Also, %% in queries does not raise an exception anymore.
* .copy_from() and .copy_in() methods are back in (still using the old
protocol, will be updated to use new one in next releasae.)
* Updated RPM specs (thanks to Mark McClain we now have updated RPMs on
initd.org too.)
* fixed memory corruption bug reported on win32 platform.
psycopg news for 1.1.11
-----------------------
What's new in psycopg 1.99.7
----------------------------
* a modern autoconf is now needed to build psycopg.
* added support for tuple factories in cursor objects (removed factory
argument in favor of a .tuple_factory attribute on the cursor object);
see the new module psycopg.extras for a cursor (DictCursor) that
return rows as objects that support indexing both by position and
column name.
* now an error during commit or rollback is correctly reported by raising
an exception.
* added support for tzinfo objects in datetime.timestamp objects: the
PostgreSQL type "timestamp with time zone" is converted to
datetime.timestamp with a FixedOffsetTimezone initialized as necessary.
* when the libpq protocol 3.0 is available, psycopg uses a smater method
to determine exception type (unfortunately the old string compare method
is still neede for postgresql <= 7.3.x.)
What's new in psycopg 1.99.6
----------------------------
* plugged a memory leak in copy_from().
* sslmode parameter from 1.1.x
* where did the news for 1.1.10 go?
* various datetime conversion improvements.
psycopg news for 1.1.9
----------------------
* now psycopg should compile without mx or without native datetime
(not both, obviously.)
* psycopg distribution now includes the GeoTypes package by Richard Taylor
(QinetiQ Plc)!
* included various win32/MSVC fixes (pthread.h changes, winsock2
library, include path in setup.py, etc.)
* Problems with sequences and mappings non correctly used in .execute()
should be gone (mogrification code completely rewritten.) Many thanks
to Richard Taylor and Vsevolod Lobko that helped by testing the "pre"
releases.
* ported interval fixes from 1.1.14/1.1.15.
* no more libpq 7.1.x linking problems related to PQfreeNotify.
* the last query executed by a cursor is now available in the
.query attribute.
psycopg news for 1.1.7
----------------------
* conversion of unicode strings to backend encoding now uses a table
(that still need to be filled.)
* added notifies and fileno methods to cursor objects.
* cursors now have a .mogrify() method that return the query string
instead of executing it.
* now execute accept any object that defined __getitem__ and not only
dictionaries.
* connection objects now have a .dsn read-only attribute that holds the
connection string.
* little fix in ZPsycopgDA, should work with Zope 2.7.
* moved psycopg C module to _psycopg and made psycopg a python module:
this allows for a neat separation of DBAPI-2.0 functionality and psycopg
extensions; the psycopg namespace will be also used to provide
python-only extensions (like the pooling code, some ZPsycopgDA support
functions and the like.)
psycopg news for 1.1.6
----------------------
What's new in psycopg 1.99.3
----------------------------
* cursor objects now have the .scroll() method.
* added support for python 2.3 datetime types (both ways) and made datetime
the default set of typecasters when available.
* NUL characters in strings are discarded in quoting; use a Binary object if
you need strings with embedded NULs.
* added example: dt.py.
* Fixed another MT problem in .execute().
What's new in psycopg 1.99.3
----------------------------
psycopg news for 1.1.5
----------------------
* initial working support for unicode bound variables: UTF-8 and latin-1
backend encodings are natively supported (and the encoding.py example even
works!)
* ZPsycopgDA now rollback before raising an exception; should be a backward
compatible change for people that really want to continue executing queries
after an exception.
* added .set_client_encoding() method on the connection object.
* fixed problem with dictionary mogrification (i.e., specifying the same key
multiple times and having the None value in the dict should work now.)
* added examples: encoding.py, binary.py, lastrowid.py.
* fixed keeper status trashing problem: no more psycopg stuck in transaction
(maybe this will also solve ZPsycopgDA problems: will see...)
What's new in psycopg 1.99.2
----------------------------
* now copy_from and copy_to can be passed instances of classes with "readline"
and "write" methods and not only file instances.
* better typecasting:
- DateTimeDelta used for postgresql TIME (merge from 1.1)
- BYTEA now is converted to a real buffer object, not to a string
psycopg news for 1.1.4
----------------------
* buffer objects are now adapted into Binary objects automatically.
* Fixed various memory leak problems.
* ported scroll method from 1.1 (DBAPI-2.0 extension for cursors)
* Implemented "statusmessage" attribute on cursors.
* initial support for some DBAPI-2.0 extensions:
- .rownumber attribute for cursors
- .connection attribute for cursors
- .next() and .__iter__() methods to have cursors support the iterator
protocol
- all exception objects are exported to the connection object
psycopg news for 1.1.3
----------------------
What's new in psycopg 1.99.1
----------------------------
* Fixed problem with psycopg always reporting IntegrityError.
* implemented microprotocols to adapt arbitrary types to the interface used by
psycopg to bind variables in execute;
* Fixed segfault in debug statements.
* moved qstring, pboolean and mxdatetime to the new adapter layout (binary is
still missing; python 2.3 datetime needs to be written).
* Now Python GIL is unlocked during PQconnectdb() calls (better
multithreading.)
psycopg news for 1.1.2
----------------------
What's new in psycopg 1.99.0
----------------------------
* Skipped version 1.1.1 (never released 'cause of a cvs tag error)
* reorganized the whole source tree;
* Much better cursor.description fields (many thanks to William K. Volkman)
* async core is in place;
* psycopg.connect() now takes keyword parameters for host, dbname, port,
user and password (they are all strings, even "port".)
* splitted QuotedString objects from mx stuff;
* connection.set_isolation_level() implemented to help switching from default
isolation to other levels supported by PostgreSQL. [autocommit now simply
does a set_isolation_level(0)]
* Implemented .lastrowid attribute for cursors.
* Now psycopg should build on win32/cygwin, thank to Hajime Nakagami patches.
* Includes every fix from 1.0.x up to 1.0.15.1:
- Fixed connection-stay-open-when-i-do-conn.close() bug.
- Better DBAPI-2.0 compliance for setinputsizes and setoutputsize methods.
- Better support for build on MacOS X.
- Fixed problem with formats in string mogrification.
- Fixed other miscellaneous buglets in Zope Adapter.
- Fixed small memory leak in .fetchXXX() methods.
- Fixed serialization problem in ZPsycopgDA reported by Dieter Maurer.
psycopg news for 1.1
--------------------
* COPY TO/COPY FROM implemented by Tom Jenkins
* Merged changes from 1.0.13.
psycopg news for 1.0.12
-----------------------
* Maintenance release fixing some little buglets:
- Fixed memory leak in .execute().
- Better configure under MacOS X.
- DA-browser now works even with tables with mixed-case names.
- timestamps time is now set to correct value instead of 0.
psycopg news for 1.0.11.1
-------------------------
* Fixed orrible bug in ZPsycopgDA not acception psycopg 1.0.11 as a valid
version.
psycopg news for 1.0.11
-----------------------
* last problems from "None passed to typecasters" (introduced in 1.0.9) in
ZPsycopgDA solved (hopefully.)
* psycopg now reports meaningfull exception types for some errors (like
IntegrityError for duplicate insertions in unique indices, etc.)
psycopg news for 1.0.10
-----------------------
* fixed an exception problem introduced in 1.0.9 (patch by Matt
Hoskins.)
* ZPsycopgDA now checks psycopg version and raise an exception if it
does not match.
psycopg news for 1.0.9
----------------------
* fixed problem with connection left in invalid state by applying
Tom Jenkins patch.
* None values passed to the typecasters, it is now possible to
translate None into "" to achieve pygrsql compatibilty.
* applied 'seconds as a float' patch from Jelle.
psycopg news for 1.0.8
----------------------
* fixed a segfault introduced in 1.0.7 and another little bug when
dealing with empty strings in QuotedString objects.
* Added win32 compatibility (many many thanks to Jason Erickson).
psycopg news for 1.0.7
----------------------
* Fixed little bugs in type management (infinity problems and the
TIMESTAMPTZ type) and Zope import. Better configure script.
* Now psycopg really close the physical connection to PostgreSQL on
connection .close().
psycopg news for 1.0.5
----------------------
* Applied a little patch to make table browser in zope show system tables
correctly.
* Infinity values are now converted the correct way.
psycopg news for 1.0.4
----------------------
* ZPsycopgDA does not duplicate itself anymore.
* Table browsing works again.
psycopg news for 1.0.3
----------------------
* bugfix for b0rken ZPsycopgDA in 1.0.2.
psycopg news for 1.0.2
----------------------
* Fixed problem with incorrect interpretation of hundredths of a second.
psycopg news for 1.0.1
----------------------
* fixed two little memory leaks, see ChangeLog for details.
* fixed problem with garbled passwords when using crypt autentication.
psycopg news for 1.0
--------------------
* added regression tests, first result is much better conversion of date and
time types.
* fixed last know segfault (psycopg runs stable for a lot of people now.)
* psycopg compile and run on FreeBSD and MacOS X.
* much better binary objects, they use less memory and quoting is faster,
thank to the new, smarter memory allocator.
* fixed all reported buglets (mostly dbapi and type-system related.)
* hey, this is one-dot-oh!
* the following features are missing from psycopg 1.0 and will be added when
we have a little more time (i.e., there will be no _feature_ releases after
1.0, only bugfixes):
- documentation is incomplete (we are slowly writing it, track CVS if you
want up-to-date docs)
- dbapi-2.0 testsuite is incomplete (need to move code to the unittest
framework)
- psycopg needs a full suite of regression tests to be sure we don't break
things while implementing new features (i think we'll add them _while_
writing new features :)
psycopg news for 0.99.7
-----------------------
* time intervals are correctly recognized and converted into DateTimeInterval
objects.
* almost complete (bugs apart) DBAPI-2.0 support. switched psycopg to use
QuotedString for every string passed as a bound argument. Binary now works
(but still consumes lots of memory).
* added doc/ to hold documentation.
* added lastoid() method to cursor objects, to retrieve the OID of the last
inserted row.
psycopg news for 0.99.4
-----------------------
* psycopg is approaching 1.0, so only DBAPI compliance patches and bug fixes
are getting in.
* added Binary and QuotedString objects. note that sometime before 1.0 we'll
switch turn every string passed to psycopg into a QuotedString, possibily
breaking Zope compatibility and old scripts doing their own quoting.
psycopg news for 0.5.x
----------------------
* this is the development branch, if you want stability, stick with 0.4.6.
* added pthread locks so that different threads (cursors) can use the same
postgres connection (this was done *only* to respect the dbapi on cursor
isolation.)
* now the default for the .cursor() method is to associate every cursor to
the same physical connection, to avoid isolation (as the DBAPI-2.0 specify),
you can change that by calling the .serialize() method on the connection and
giving it 0 as the argument, e.g., "o.serialize(0)".
psycopg news for 0.4.1
----------------------
* autocommit mode is now supported on cursors and connections.
psycopg news for 0.4
--------------------
* implemented all the remaining DBAPI-2.0 type singletons (DATETIME and
BINARY included)
psycopg news for 0.3
--------------------
* threading problems resolved
* added type casting from postgres to python (the user can now specify
its own casting objects, the default singletons NUMBER and STRING are
included [and act as default cast objects] plus INTEGER and FLOAT as
an extension to the DBAPI-2.0.)
investigate the code in examples/usercast_test.py to understand how to
add your own types...
* beginning of the Zope Database Adapter: give it a try even it it is
broken!
* dropped autotools and moved to pythonic setup.py (needs work.)

173
README
View File

@ -1,145 +1,26 @@
psycopg - Python-PostgreSQL Database Adapter
********************************************
psycopg is a PostgreSQL database adapter for the Python programming language
(just like pygresql and popy.) It was written from scratch with the aim of
being very small and fast, and stable as a rock. The main advantages of
psycopg are that it supports (well... *will* support) the full Python
DBAPI-2.0 and being thread safe at level 2.
psycopg is a PostgreSQL database adapter for the Python programming
language. This is version 2, a complete rewrite of the original code to
provide new-style classes for connection and cursor objects and other sweet
candies. Like the original, psycopg 2 was written with the aim of being
very small and fast, and stable as a rock.
psycopg is different from the other database adapter because it was designed
for heavily multi-threaded applications that create and destroy lots of
cursors and make a conspicuous number of concurrent INSERTs or UPDATEs.
Every open Python connection keeps a pool of real (UNIX or TCP/IP) connections
to the database. Every time a new cursor is created, a new connection does not
need to be opened; instead one of the unused connections from the pool is
used. That makes psycopg very fast in typical client-server applications that
create a servicing thread every time a client request arrives.
psycopg is different from the other database adapter because it was
designed for heavily multi-threaded applications that create and destroy
lots of cursors and make a conspicuous number of concurrent INSERTs or
UPDATEs. psycopg 2 also provide full asycronous operations for the really
brave programmer.
psycopg now support the Python DBAPI-2.0 completely. There are confirmed
reports of psycopg compiling and running on Linux and FreeBSD on i386, Solaris
and MacOS X.
There are confirmed reports of psycopg 1.x compiling and running on Linux
and FreeBSD on i386, Solaris, MacOS X and win32 architectures. psycopg 2
does not introduce build-wise incompatible changes so it should be able to
compile on all architectures just as its predecessor did.
Now go read the INSTALL file. More information about psycopg extensions to
the DBAPI-2.0 is available in the files located in the doc/ direcory.
Extensions to the Python DBAPI-2.0
----------------------------------
psycopg offers some little extensions on the Python DBAPI-2.0. Note that the
extension do not make psycopg incompatible and you can still use it without
ever knowing the extensions are here.
The DBAPI-2.0 mandates that cursors derived from the same connection are not
isolated, i.e., changes done to the database by one of them should be
immediately visible by all the others. This is done by serializing the queries
on the same physical connection to the database (PGconn struct in C.)
Serializing queries when the network latencies are hight (and network speed is
low) dramatically lowers performance, so it is possible to put a connection
into not-serialized mode, by calling the .serialize() method giving it a
0-value argument or by creating a connection using the following code:
conn = psycopg.connect("dbname=...", serialize=0)
After that every cursor will get its own physical connection to the database
and multiple threads will go at full speed. Note that this feature makes the
new cursors non-compliant respect to the DBAPI-2.0.
The main extension is that we support (on not-serialized cursors) per-cursor
commits. If you do a commit() on the connection all the changes on all the
cursors derived from that connection are committed to the database (in random
order, so take your care.) But you can also call commit() on a single cursor
to commit just the operations done on that cursor. Pretty nice.
Note that you *do have* to call .commit() on the cursors or on the connection
if you want to change your database. Note also that you *do have* to call
commit() on a cursor even before a SELECT if you want to see the changes
apported by other threads to the database.
Also note that you *can't* (I repeat: *you* *can't*) call .commit() on cursor
derived from a serialized connection: trying that will give you an exception
with the message: "serialized connection: cannot commit on this cursor". If
you want to use the per-cursor commit feature you need to create a
non-serialized connection, as explained above.
From version 0.4.1 psycopg supports autocommit mode. You can set the default
mode for new cursor by setting the 'autocommit' variable to 0 or 1 on the
connection before creating a new cursor with the cursor() method. On an
already created cursor you can change the commit mode by calling the
autocommit() method. Giving no arguments or 1 switches autocommit on, 0
switches it off.
Obviously everything said about commit is valid for rollbacks too.
The type system
---------------
The DBAPI-2.0 specify that should be possible to check for the column type
reported in the second field of the description tuple of the cursor used for a
SELECT using 'singletons' like NUMBER, STRING, etc. While this is fully
supported by psycopg from release 0.3 on, we went forward and implemented
support for custom typecasting from PostgreSQL to Python types using
user-defined functions. See the examples test/check_types.py and
doc/examples/usercast.py for more information. In particular usercast_test.py
shows how to implement a callback that translates the PostgreSQL box type to
an ad-hoc Python class with instances created automagically on SELECT.
Compile-time configuration options
----------------------------------
To build psycopg you will need a C compiler (gcc), the Python development
files (headers and libraries), the PostgreSQL header and libraries and the
mxDateTime header files (and the mxDateTime Python package installed, version
>= 2.0.0, of curse.)
The following options are specific to psycopg and can be set when running
configure before issuing 'make' to compile the package.
--with-postgres-libraries=DIR
PostgreSQL 7.x libraries (libpq.so) are in directory DIR
--with-postgres-includes=DIR
PostgreSQL 7.x header files are located in directory DIR
--with-mxdatetime-includes=DIR
MXDateTime Python extension header files are located in directory DIR
--with-zope=DIR
install the ZPsycopgDA Zope Product into DIR (use 'make install-zope')
--enable-devel[=yes/no]
Enable developer features like debugging output and extra assertions.
Some random notes about python versions and paths:
1/ If possible, don't use the configure arguments --with-python-prefix
and --with-python-exec-prefix; the configure script is able to guess
the correct values from you python installation.
2/ If you have more than one Python version installed, use the arguments
--with-python (giving it the *full*, *absolute* path to the Python
interpreter) and --with-python-version (giving it the corresponding
version, like 1.5 or 2.1.)
Common problems while building psycopg:
1/ if your compiler does not find some postgres headers try copying all the
headers from the postgres _source_ distribution to a single place. Also,
if building postgresql from source, make sure to install all headers by
the "make install-all-headers" target.
2/ if you have the same problem with mx.DateTime, try using the source
directory again; the install script does not copy all the headers, same
way as postgres install procedure does.
3/ under MacOS X you may need to run the runlib program on the posgres
installed libraries before trying to compile psycopg. Also, if you
get compilation errors there is a change your python was not compiled
correctly and psycopg is grabbing the wrong compile-time options from
python's Makefile. try setting the OPT and LDFLAG environment variables
to something usefull, as in the next example:
OPT="-no-cpp-precomp" LDFLAGS="-flat-namespace" ./configure ...
Licence
-------
@ -149,16 +30,16 @@ it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. See file COPYING for details.
As a special exception, specific permission is granted for the GPLed
code in this distribition to be linked to OpenSSL and PostgreSQL libpq
without invoking GPL clause 2(b).
As a special exception, specific permission is granted for the GPLed code in
this distribition to be linked to OpenSSL and PostgreSQL libpq without
invoking GPL clause 2(b).
If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e.,
every file inside the ZPsycopgDA directory) user the ZPL license as
published on the Zope web site, http://www.zope.org/Resources/ZPL.
psycopg is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e., every
file inside the ZPsycopgDA directory) under the ZPL license as published on
the Zope web site, http://www.zope.org/Resources/ZPL. The ZPL is perfectly
compatible with the GPL
psycopg is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.

View File

@ -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
# modification, are permitted provided that the following conditions are
# met:
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
database_type='Psycopg'
__doc__='''%s Database Connection
# See the LICENSE file for details.
$Id: DA.py 531 2004-09-18 09:54:40Z fog $''' % database_type
__version__='$Revision: 1.20.2.14 $'[11:-2]
__psycopg_versions__ = ('1.1.12', '1.1.13', '1.1.14', '1.1.15', '1.1.16')
ALLOWED_PSYCOPG_VERSIONS = ('1.99.9',)
import sys
import db
import DABase
import Shared.DC.ZRDB.Connection
from db import DB
import Shared.DC.ZRDB.Connection, sys, DABase, time
from Globals import HTMLFile, ImageFile
from Globals import DTMLFile
from Globals import HTMLFile
from ImageFile import ImageFile
from ExtensionClass import Base
from string import find, join, split, rindex
try:
import psycopg
from psycopg import new_type, register_type, DATETIME, TIME, DATE, INTERVAL
except StandardError, err:
print err
try:
from DateTime import DateTime
except StandardError, err:
print err
try:
from App.Dialogs import MessageDialog
except:
pass
import time
from DateTime import DateTime
manage_addZPsycopgConnectionForm = HTMLFile('connectionAdd', globals())
def manage_addZPsycopgConnection(self, id, title,
connection_string, zdatetime=None,
tilevel=2, check=None, REQUEST=None):
"""Add a DB connection to a folder"""
self._setObject(id, Connection(id, title, connection_string, zdatetime,
check, tilevel))
if REQUEST is not None: return self.manage_main(self,REQUEST)
# import psycopg and functions/singletons needed for date/time conversions
import psycopg
from psycopg import DATETIME
from psycopg.extensions import TIME, DATE, INTERVAL
from psycopg.extensions import new_type, register_type
# Convert an ISO timestamp string from postgres to a DateTime (zope version)
# object.
def cast_DateTime(str):
# add a new connection to a folder
manage_addZPsycopgConnectionForm = DTMLFile('dtml/add',globals())
def manage_addZPsycopgConnection(self, id, title, connection_string,
zdatetime=None, tilevel=2,
check=None, REQUEST=None):
"""Add a DB connection to a folder."""
self._setObject(id, Connection(id, title, connection_string,
zdatetime, check, tilevel))
if REQUEST is not None: return self.manage_main(self, REQUEST)
# the connection object
class Connection(DABase.Connection):
"""ZPsycopg Connection."""
id = 'Psycopg_database_connection'
database_type = 'Psycopg'
meta_type = title = 'Z Psycopg Database Connection'
icon = 'misc_/ZPsycopg/conn'
def __init__(self, id, title, connection_string,
zdatetime, check=None, tilevel=2, encoding=''):
self.zdatetime = zdatetime
self.id = str(id)
self.edit(title, connection_string, zdatetime,
check=check, tilevel=tilevel, encoding=encoding)
def factory(self):
return DB
def table_info(self):
return self._v_database_connection.table_info()
def edit(self, title, connection_string,
zdatetime, check=None, tilevel=2, encoding=''):
self.title = title
self.connection_string = connection_string
self.zdatetime = zdatetime
self.tilevel = tilevel
self.encoding = encoding
self.set_type_casts()
if check: self.connect(self.connection_string)
manage_properties = DTMLFile('dtml/edit', globals())
def manage_edit(self, title, connection_string,
zdatetime=None, check=None, tilevel=2, encoding='UTF-8',
REQUEST=None):
"""Edit the DB connection."""
self.edit(title, connection_string, zdatetime,
check=check, tilevel=tilevel, encoding=encoding)
if REQUEST is not None:
msg = "Connection edited."
return self.manage_main(self,REQUEST,manage_tabs_message=msg)
def connect(self, s):
try:
self._v_database_connection.close()
except:
pass
# check psycopg version and raise exception if does not match
if psycopg.__version__ not in ALLOWED_PSYCOPG_VERSIONS:
raise ImportError("psycopg version mismatch (imported %s)" +
psycopg.__version__)
self.set_type_casts()
self._v_connected = ''
dbf = self.factory()
# TODO: let the psycopg exception propagate, or not?
self._v_database_connection = dbf(
self.connection_string, self.tilevel, self.encoding)
self._v_database_connection.open()
self._v_connected = DateTime()
return self
def set_type_casts(self):
# note that in both cases order *is* important
if self.zdatetime:
# use zope internal datetime routines
register_type(ZDATETIME)
register_type(ZDATE)
register_type(ZTIME)
register_type(ZINTERVAL)
else:
# use the standard
register_type(DATETIME)
register_type(DATE)
register_type(TIME)
register_type(INTERVAL)
# database connection registration data
classes = (Connection,)
meta_types = ({'name':'Z Psycopg Database Connection',
'action':'manage_addZPsycopgConnectionForm'},)
folder_methods = {
'manage_addZPsycopgConnection': manage_addZPsycopgConnection,
'manage_addZPsycopgConnectionForm': manage_addZPsycopgConnectionForm}
__ac_permissions__ = (
('Add Z Psycopg Database Connections',
('manage_addZPsycopgConnectionForm', 'manage_addZPsycopgConnection')),)
# add icons
misc_={'conn': ImageFile('Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')}
for icon in ('table', 'view', 'stable', 'what', 'field', 'text', 'bin',
'int', 'float', 'date', 'time', 'datetime'):
misc_[icon] = ImageFile('icons/%s.gif' % icon, globals())
# zope-specific psycopg typecasters
# convert an ISO timestamp string from postgres to a Zope DateTime object
def _cast_DateTime(str):
if str:
# this will split us into [date, time, GMT/AM/PM(if there)]
dt = split(str, ' ')
@ -130,158 +173,30 @@ def cast_DateTime(str):
# we now should split out any timezone info
dt[1] = split(dt[1], '-')[0]
dt[1] = split(dt[1], '+')[0]
t = time.mktime(time.strptime(join(dt[:2], ' '), '%Y-%m-%d %H:%M:%S'))
return DateTime(join(dt[:2], ' '))
else:
t = time.mktime(time.strptime(dt[0], '%Y-%m-%d %H:%M:%S'))
return DateTime(t)
return DateTime(dt[0])
# Convert an ISO date string from postgres to a DateTime(zope version)
# object.
def cast_Date(str):
# convert an ISO date string from postgres to a Zope DateTime object
def _cast_Date(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.
# WARNING: We set the day as today before feeding to DateTime so
# Convert a time string from postgres to a Zope DateTime object.
# NOTE: we set the day as today before feeding to DateTime so
# that it has the same DST settings.
def cast_Time(str):
def _cast_Time(str):
if str:
return DateTime(time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(time.time())[:3]+
time.strptime(str[:8], "%H:%M:%S")[3:]))
time.localtime(time.time())[:3]+
time.strptime(str[:8], "%H:%M:%S")[3:]))
# Convert a time string from postgres to a DateTime(zope version) object.
# WARNING: We set the day as the epoch day (1970-01-01) since this
# DateTime does not support time deltas. (EXPERIMENTAL USE WITH CARE!)
def cast_Interval(str):
# TODO: DateTime does not support intervals: what's the best we can do?
def _cast_Interval(str):
return str
ZDATETIME = new_type((1184, 1114), "ZDATETIME", _cast_DateTime)
ZINTERVAL = new_type((1186,), "ZINTERVAL", _cast_Interval)
ZDATE = new_type((1082,), "ZDATE", _cast_Date)
ZTIME = new_type((1083,), "ZTIME", _cast_Time)
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())

View File

@ -1,150 +1,61 @@
##############################################################################
# ZPsycopgDA/DABase.py - ZPsycopgDA Zope product: Database inspection
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
#
# Copyright (c) Digital Creations. All rights reserved.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This license has been certified as Open Source(tm).
# Or, at your option this program (ZPsycopgDA) can be distributed under the
# Zope Public License (ZPL) Version 1.0, as published on the Zope web site,
# http://www.zope.org/Resources/ZPL.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__='''Database Connection
# See the LICENSE file for details.
$Id: DABase.py 400 2003-01-20 14:39:34Z fog $'''
__version__='$Revision: 1.10 $'[11:-2]
import sys
import Shared.DC.ZRDB.Connection
import Shared.DC.ZRDB.Connection, sys
from App.Dialogs import MessageDialog
from Globals import HTMLFile, ImageFile
from db import DB
from Globals import HTMLFile
from ImageFile import ImageFile
from ExtensionClass import Base
import Acquisition
from psycopg import NUMBER, ROWID, STRING, INTEGER, FLOAT
from psycopg import BOOLEAN, DATETIME, LONGINTEGER
from DateTime import DateTime
# import psycopg and functions/singletons needed for date/time conversions
import psycopg
from psycopg.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN
from psycopg import NUMBER, STRING, ROWID, DATETIME
class Connection(Shared.DC.ZRDB.Connection.Connection):
_isAnSQLConnection = 1
info = None
manage_options=Shared.DC.ZRDB.Connection.Connection.manage_options+(
{'label': 'Browse', 'action':'manage_browse'},
# {'label': 'Design', 'action':'manage_tables'}
)
#manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + (
# {'label': 'Browse', 'action':'manage_browse'},)
manage_tables = HTMLFile('tables',globals())
manage_browse = HTMLFile('browse',globals())
info=None
def tpValues(self):
#if hasattr(self, '_v_tpValues'): return self._v_tpValues
r=[]
# self._v_tables=tables=TableBrowserCollection()
#tables=tables.__dict__
c = self._v_database_connection
try:
for d in c.tables(rdb=0):
try:
name=d['TABLE_NAME']
b=TableBrowser()
b.__name__=name
b._d=d
b._c=c
# b._columns=c.columns(name)
try: b.icon=table_icons[d['TABLE_TYPE']]
except: pass
r.append(b)
# tables[name]=b
except:
# print d['TABLE_NAME'], sys.exc_type, sys.exc_value
pass
finally: pass #print sys.exc_type, sys.exc_value
#self._v_tpValues=r
return r
#manage_tables = HTMLFile('tables', globals())
#manage_browse = HTMLFile('browse',globals())
def __getitem__(self, name):
if name=='tableNamed':
if name == 'tableNamed':
if not hasattr(self, '_v_tables'): self.tpValues()
return self._v_tables.__of__(self)
raise KeyError, name
## old stuff from ZPsycopgDA 1.1 (never implemented) ##
def manage_wizard(self, tables):
" "
"Wizard of what? Oozing?"
def manage_join(self, tables, select_cols, join_cols, REQUEST=None):
"""Create an SQL join"""
@ -154,116 +65,3 @@ class Connection(Shared.DC.ZRDB.Connection.Connection):
def manage_update(self, table, keys, cols, REQUEST=None):
"""Create an SQL update"""
class TableBrowserCollection(Acquisition.Implicit):
"Helper class for accessing tables via URLs"
pass
class Browser(Base):
def __getattr__(self, name):
try: return self._d[name]
except KeyError: raise AttributeError, name
class values:
def len(self): return 1
def __getitem__(self, i):
try: return self._d[i]
except AttributeError:
pass
self._d=self._f()
return self._d[i]
class TableBrowser(Browser, Acquisition.Implicit):
icon='what'
Description=check=''
info=HTMLFile('table_info',globals())
menu=HTMLFile('table_menu',globals())
def tpValues(self):
v=values()
v._f=self.tpValues_
return v
def tpValues_(self):
r=[]
tname=self.__name__
for d in self._c.columns(tname):
b=ColumnBrowser()
b._d=d
try: b.icon=field_icons[d['Type']]
except: pass
b.TABLE_NAME=tname
r.append(b)
return r
def tpId(self): return self._d['TABLE_NAME']
def tpURL(self): return "Table/%s" % self._d['TABLE_NAME']
def Name(self): return self._d['TABLE_NAME']
def Type(self): return self._d['TABLE_TYPE']
manage_designInput=HTMLFile('designInput',globals())
def manage_buildInput(self, id, source, default, REQUEST=None):
"Create a database method for an input form"
args=[]
values=[]
names=[]
columns=self._columns
for i in range(len(source)):
s=source[i]
if s=='Null': continue
c=columns[i]
d=default[i]
t=c['Type']
n=c['Name']
names.append(n)
if s=='Argument':
values.append("<dtml-sqlvar %s type=%s>'" %
(n, vartype(t)))
a='%s%s' % (n, boboType(t))
if d: a="%s=%s" % (a,d)
args.append(a)
elif s=='Property':
values.append("<dtml-sqlvar %s type=%s>'" %
(n, vartype(t)))
else:
if isStringType(t):
if find(d,"\'") >= 0: d=join(split(d,"\'"),"''")
values.append("'%s'" % d)
elif d:
values.append(str(d))
else:
raise ValueError, (
'no default was given for <em>%s</em>' % n)
class ColumnBrowser(Browser):
icon='field'
def check(self):
return ('\t<input type=checkbox name="%s.%s">' %
(self.TABLE_NAME, self._d['Name']))
def tpId(self): return self._d['Name']
def tpURL(self): return "Column/%s" % self._d['Name']
def Description(self):
d=self._d
if d['Scale']:
return " %(Type)s(%(Precision)s,%(Scale)s) %(Nullable)s" % d
else:
return " %(Type)s(%(Precision)s) %(Nullable)s" % d
table_icons={
'TABLE': 'table',
'VIEW':'view',
'SYSTEM_TABLE': 'stable',
}
field_icons={
NUMBER.name: 'int',
STRING.name: 'text',
DATETIME.name: 'date',
INTEGER.name: 'int',
FLOAT.name: 'float',
BOOLEAN.name: 'bin',
ROWID.name: 'int'
}

View File

@ -1,105 +1,32 @@
##############################################################################
# ZPsycopgDA/__init__.py - ZPsycopgDA Zope product
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
#
# Copyright (c) Digital Creations. All rights reserved.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This license has been certified as Open Source(tm).
# Or, at your option this program (ZPsycopgDA) can be distributed under the
# Zope Public License (ZPL) Version 1.0, as published on the Zope web site,
# http://www.zope.org/Resources/ZPL.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
# Modified by mcm@initd.net for the psycopg driver
__doc__='''Generic Database Adapter Package Registration
# See the LICENSE file for details.
$Id: __init__.py 400 2003-01-20 14:39:34Z fog $'''
__version__='$Revision: 1.11 $'[11:-2]
__doc__ = "ZPsycopg Database Adalper Registration."
__version__ = '2.0'
import sys, string
import sys
import string
import DA
methods=DA.folder_methods
misc_ = DA.misc_
methods = DA.folder_methods
classes = DA.classes
meta_types = DA.meta_types
misc_ = DA.misc_
def initialize(context):
"""Initialize the DBA product.
"""
context.registerClass(
DA.Connection,
permission = 'Add Z Psycopg Database Connections',
constructors = (DA.manage_addZPsycopgConnectionForm,
DA.manage_addZPsycopgConnection),
icon = SOFTWARE_HOME + '/Shared/DC/ZRDB/www/DBAdapterFolder_icon.gif')
__ac_permissions__=DA.__ac_permissions__

View File

@ -1,171 +1,126 @@
##############################################################################
# ZPsycopgDA/db.py - query execution
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
# Copyright (C) 2004 Federico Di Gregorio <fog@initd.org>
#
# Copyright (c) Digital Creations. All rights reserved.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This license has been certified as Open Source(tm).
# Or, at your option this program (ZPsycopgDA) can be distributed under the
# Zope Public License (ZPL) Version 1.0, as published on the Zope web site,
# http://www.zope.org/Resources/ZPL.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
'''$Id: db.py 532 2004-09-27 18:35:25Z fog $'''
__version__='$Revision: 1.31.2.7 $'[11:-2]
# See the LICENSE file for details.
from Shared.DC.ZRDB.TM import TM
from Shared.DC.ZRDB import dbi_db
import string, sys
from string import strip, split, find
from time import time
from types import ListType
import site
import psycopg
from psycopg import NUMBER, STRING, INTEGER, FLOAT, DATETIME
from psycopg import BOOLEAN, ROWID, LONGINTEGER
from ZODB.POSException import ConflictError
class DB(TM,dbi_db.DB):
import time
import site
import pool
import psycopg
from psycopg.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN
from psycopg import NUMBER, STRING, ROWID, DATETIME
# the DB object, managing all the real query work
class DB(TM, dbi_db.DB):
_p_oid = _p_changed = _registered = None
def __init__(self, connection, tilevel, enc='utf-8'):
self.connection = connection
def __init__(self, dsn, tilevel, enc='utf-8'):
self.dsn = dsn
self.tilevel = tilevel
self.encoding = enc
self.db = self.connect(self.connection)
self.failures = 0
self.calls = 0
def connect(self, connection):
o = psycopg.connect(connection)
o.set_isolation_level(int(self.tilevel))
return o
def getconn(self, create=True):
conn = pool.getconn(self.dsn)
conn.set_isolation_level(int(self.tilevel))
return conn
def putconn(self, close=False):
try:
conn = pool.getconn(self.dsn, False)
except AttributeError:
pass
pool.putconn(self.dsn, conn, close)
def getcursor(self):
conn = self.getconn()
return conn.cursor()
def _finish(self, *ignored):
if hasattr(self, 'db') and self.db:
self.db.commit()
try:
conn = self.getconn(False)
conn.commit()
self.putconn()
except AttributeError:
pass
def _abort(self, *ignored):
if hasattr(self, 'db') and self.db:
self.db.rollback()
try:
conn = self.getconn(False)
conn.rollback()
self.putconn()
except AttributeError:
pass
def _cursor(self):
"""Obtains a cursor in a safe way."""
if not hasattr(self, 'db') or not self.db:
self.db = self.connect(self.connection)
return self.db.cursor()
def open(self):
# this will create a new pool for our DSN if not already existing,
# then get and immediately release a connection
self.getconn()
self.putconn()
def close(self):
# FIXME: if this connection is closed we flush all the pool associated
# with the current DSN; does this makes sense?
pool.flushpool(self.dsn)
def sortKey(self):
return 1
## tables and rows ##
def tables(self, rdb=0, _care=('TABLE', 'VIEW')):
self._register()
c = self._cursor()
c.execute('SELECT t.tablename AS NAME, '
'\'TABLE\' AS TYPE FROM pg_tables t '
'WHERE tableowner <> \'postgres\' '
'UNION SELECT v.viewname AS NAME, '
'\'VIEW\' AS TYPE FROM pg_views v '
'WHERE viewowner <> \'postgres\' '
'UNION SELECT t.tablename AS NAME, '
'\'SYSTEM_TABLE\' AS TYPE FROM pg_tables t '
'WHERE tableowner = \'postgres\' '
'UNION SELECT v.viewname AS NAME, '
'\'SYSTEM_TABLE\' AS TYPE FROM pg_views v '
'WHERE viewowner = \'postgres\' ' )
r = []
a = r.append
c = self.getcursor()
c.execute(
"SELECT t.tablename AS NAME, 'TABLE' AS TYPE "
" FROM pg_tables t WHERE tableowner <> 'postgres' "
"UNION SELECT v.viewname AS NAME, 'VIEW' AS TYPE "
" FROM pg_views v WHERE viewowner <> 'postgres' "
"UNION SELECT t.tablename AS NAME, 'SYSTEM_TABLE\' AS TYPE "
" FROM pg_tables t WHERE tableowner = 'postgres' "
"UNION SELECT v.viewname AS NAME, 'SYSTEM_TABLE' AS TYPE "
"FROM pg_views v WHERE viewowner = 'postgres'")
res = []
for name, typ in c.fetchall():
if typ in _care:
a({'TABLE_NAME': name, 'TABLE_TYPE': typ})
c.close()
return r
res.append({'TABLE_NAME': name, 'TABLE_TYPE': typ})
self.putconn()
return res
def columns(self, table_name):
self._register()
c = self._cursor()
c = self.getcursor()
try:
r = c.execute('select * from "%s" where 1=0' % table_name)
r = c.execute('SELECT * FROM "%s" WHERE 1=0' % table_name)
except:
return ()
desc = c.description
r = []
a = r.append
for name, type, width, ds, p, scale, null_ok in desc:
res = []
for name, type, width, ds, p, scale, null_ok in c.description:
if type == NUMBER:
if type == INTEGER:
type = INTEGER
@ -180,46 +135,50 @@ class DB(TM,dbi_db.DB):
type = DATETIME
else:
type = STRING
a({ 'Name': name,
'Type': type.name,
'Precision': 0,
'Scale': 0,
'Nullable': 0})
return r
res.append({'Name': name,
'Type': type.name,
'Precision': 0,
'Scale': 0,
'Nullable': 0})
self.putconn()
return res
## query execution ##
def query(self, query_string, max_rows=None, query_data=None):
self._register()
self.calls = self.calls+1
desc = ()
result = []
res = []
nselects = 0
c = self._cursor()
c = self.getcursor()
try:
for qs in filter(None, map(strip, split(query_string, '\0'))):
for qs in [x for x in query_string.split('\0') if x]:
if type(qs) == unicode:
if self.encoding:
qs = qs.encode(self.encoding)
try:
if (query_data):
r = c.execute(qs, query_data)
c.execute(qs, query_data)
else:
r = c.execute(qs)
except (psycopg.ProgrammingError,psycopg.IntegrityError), perr:
if perr.args[0].find("concurrent update") > -1:
c.execute(qs)
except (psycopg.ProgrammingError, psycopg.IntegrityError), e:
if e.args[0].find("concurrent update") > -1:
raise ConflictError
raise perr
raise e
if c.description is not None:
nselects = nselects + 1
nselects += 1
if c.description != desc and nselects > 1:
raise 'Query Error', \
'Multiple select schema are not allowed'
raise psycopg.ProgrammingError(
'multiple selects in single query not allowed')
if max_rows:
result = c.fetchmany(max_rows)
res = c.fetchmany(max_rows)
else:
result = c.fetchall()
res = c.fetchall()
desc = c.description
self.failures = 0
@ -247,13 +206,4 @@ class DB(TM,dbi_db.DB):
'null': null_ok,
})
return items, result
def close(self):
"""Close the connection."""
self.db.close()
self.db = None
def sortKey(self):
"""Zope 2.6 added this one."""
return 1
return items, res

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 894 B

After

Width:  |  Height:  |  Size: 894 B