mirror of https://github.com/postgres/postgres
remove python module, as its moved to http://www.pygresql.org
parent
2c018f9b10
commit
13a0e910cd
@ -1,158 +0,0 @@ |
||||
|
||||
Announce: Release of PyGreSQL version 3.3 |
||||
========================================= |
||||
|
||||
PyGreSQL v3.3 has been released. |
||||
It is available at: ftp://ftp.druid.net/pub/distrib/PyGreSQL.tgz. If |
||||
you are running NetBSD, look in the packages directory under databases. |
||||
There is also a package in the FreeBSD ports collection. |
||||
|
||||
From March 1 2001 the PyGreSQL development has moved into the PostgreSQL |
||||
development tree. |
||||
|
||||
PostgreSQL is a database system derived from Postgres4.2. It conforms |
||||
to (most of) ANSI SQL and offers many interesting capabilities (C |
||||
dynamic linking for functions or type definition, etc.). This package |
||||
is copyright by the Regents of the University of California, and is |
||||
freely distributable. |
||||
|
||||
Python is an interpreted programming language. It is object oriented, |
||||
simple to use (light syntax, simple and straightforward statements), and |
||||
has many extensions for building GUIs, interfacing with WWW, etc. An |
||||
intelligent web browser (HotJava like) is currently under development |
||||
(November 1995), and this should open programmers many doors. Python is |
||||
copyrighted by Stichting S Mathematisch Centrum, Amsterdam, The |
||||
Netherlands, and is freely distributable. |
||||
|
||||
PyGreSQL is a python module that interfaces to a PostgreSQL database. It |
||||
embeds the PostgreSQL query library to allow easy use of the powerful |
||||
PostgreSQL features from a Python script. |
||||
|
||||
This release fixes a few bugs, adds a few minor features and makes a |
||||
few speedups in the code. |
||||
|
||||
The next release (unless serious bugs are found) will be to match PyGreSQL |
||||
to version 2.0 of Python. |
||||
|
||||
See the other changes below or in the Changelog file. |
||||
|
||||
PyGreSQL 2.0 was developed and tested on a NetBSD 1.3_BETA system. It |
||||
is based on the PyGres95 code written by Pascal Andre, |
||||
andre@chimay.via.ecp.fr. I changed the version to 2.0 and updated the |
||||
code for Python 1.5 and PostgreSQL 6.2.1. While I was at it I upgraded |
||||
the code to use full ANSI style prototypes and changed the order of |
||||
arguments to connect. Later versions are fixes and enhancements to that. |
||||
The latest version of PyGreSQL works with Python 1.5.2 and PostgreSQL 7.0.x |
||||
|
||||
Important changes from PyGreSQL 3.2 to PyGreSQL 3.3 |
||||
- Added NUMERICOID to list of returned types. This fixes a bug when |
||||
returning aggregates in the latest version of PostgreSQL. |
||||
|
||||
Important changes from PyGreSQL 3.1 to PyGreSQL 3.2 |
||||
Note that there are very few changes to PostgreSQL between 3.1 and |
||||
3.2. The main reason for the release is the move into the PostgreSQL |
||||
development tree. Even the WIN32 changes are pretty minor. |
||||
- Add WIN32 support (gerhard@bigfoot.de) |
||||
- Fix some DB-API quoting problems (niall.smart@ebeon.com) |
||||
- Moved development into PostgreSQL development tree. |
||||
|
||||
Important changes from PyGreSQL 3.0 to PyGreSQL 3.1 |
||||
- Fix some quoting functions. In particular handle NULLs better. |
||||
- Use a method to add primary key information rather than direct |
||||
manipulation of the class structures. |
||||
- Break decimal out in _quote (in pg.py) and treat it as float. |
||||
- Treat timestamp like date for quoting purposes. |
||||
- Remove a redundant SELECT from the get method speeding it, and insert |
||||
since it calls get, up a little. |
||||
- Add test for BOOL type in typecast method to pgdbTypeCache class. |
||||
(tv@beamnet.de) |
||||
- Fix pgdb.py to send port as integer to lower level function |
||||
(dildog@l0pht.com) |
||||
- Change pg.py to speed up some operations |
||||
- Allow updates on tables with no primary keys. |
||||
|
||||
Important changes from PyGreSQL 2.4 to PyGreSQL 3.0: |
||||
- Remove strlen() call from pglarge_write() and get size from object. |
||||
(Richard@Bouska.cz) |
||||
- Add a little more error checking to the quote function in the wrapper |
||||
- Add extra checking in _quote function |
||||
- Wrap query in pg.py for debugging |
||||
- Add DB-API 2.0 support to pgmodule.c (andre@via.ecp.fr) |
||||
- Add DB-API 2.0 wrapper pgdb.py (andre@via.ecp.fr) |
||||
- Correct keyword clash (temp) in tutorial |
||||
- Clean up layout of tutorial |
||||
- Return NULL values as None (rlawrence@lastfoot.com) (WARNING: This |
||||
will cause backwards compatibility issues.) |
||||
- Change None to NULL in insert and update |
||||
- Change hash-bang lines to use /usr/bin/env |
||||
- Clearing date should be blank (NULL) not TODAY |
||||
- Quote backslashes in strings in _quote (brian@CSUA.Berkeley.EDU) |
||||
- Expanded and clarified build instructions (tbryan@starship.python.net) |
||||
- Make code thread safe (Jerome.Alet@unice.fr) |
||||
- Add README.distutils (mwa@gate.net & jeremy@cnri.reston.va.us) |
||||
- Many fixes and increased DB-API compliance by chifungfan@yahoo.com, |
||||
tony@printra.net, jeremy@alum.mit.edu and others to get the final |
||||
version ready to release. |
||||
|
||||
Important changes from PyGreSQL 2.3 to PyGreSQL 2.4: |
||||
- Insert returns None if the user doesn't have select permissions |
||||
on the table. It can (and does) happen that one has insert but |
||||
not select permissions on a table. |
||||
- Added ntuples() method to query object (brit@druid.net) |
||||
- Corrected a bug related to getresult() and the money type |
||||
- Corrected a bug related to negative money amounts |
||||
- Allow update based on primary key if munged oid not available and |
||||
table has a primary key |
||||
- Add many __doc__ strings. (andre@via.ecp.fr) |
||||
- Get method works with views if key specified |
||||
|
||||
Important changes from PyGreSQL 2.2 to PyGreSQL 2.3: |
||||
- connect.host returns "localhost" when connected to Unix socket |
||||
(torppa@tuhnu.cutery.fi) |
||||
- Use PyArg_ParseTupleAndKeywords in connect() (torppa@tuhnu.cutery.fi) |
||||
- fixes and cleanups (torppa@tuhnu.cutery.fi) |
||||
- Fixed memory leak in dictresult() (terekhov@emc.com) |
||||
- Deprecated pgext.py - functionality now in pg.py |
||||
- More cleanups to the tutorial |
||||
- Added fileno() method - terekhov@emc.com (Mikhail Terekhov) |
||||
- added money type to quoting function |
||||
- Compiles cleanly with more warnings turned on |
||||
- Returns PostgreSQL error message on error |
||||
- Init accepts keywords (Jarkko Torppa) |
||||
- Convenience functions can be overridden (Jarkko Torppa) |
||||
- added close() method |
||||
|
||||
Important changes from PyGreSQL 2.1 to PyGreSQL 2.2: |
||||
- Added user and password support thanks to Ng Pheng Siong <ngps@post1.com> |
||||
- Insert queries return the inserted oid |
||||
- Add new pg wrapper (C module renamed to _pg) |
||||
- Wrapped database connection in a class. |
||||
- Cleaned up some of the tutorial. (More work needed.) |
||||
- Added version and __version__. Thanks to thilo@eevolute.com for |
||||
the suggestion. |
||||
|
||||
Important changes from PyGreSQL 2.0 to PyGreSQL 2.1: |
||||
- return fields as proper Python objects for field type |
||||
- Cleaned up pgext.py |
||||
- Added dictresult method |
||||
|
||||
Important changes from Pygres95 1.0b to PyGreSQL 2.0: |
||||
- Updated code for PostgreSQL 6.2.1 and Python 1.5. |
||||
- Reformatted code and converted to ANSI . |
||||
- Changed name to PyGreSQL (from PyGres95.) |
||||
- Changed order of arguments to connect function. |
||||
- Created new type pgqueryobject and moved certain methods to it. |
||||
- Added a print function for pgqueryobject |
||||
- Various code changes - mostly stylistic. |
||||
|
||||
For more information about each package, please have a look to their |
||||
web pages: |
||||
- Python : http://www.python.org/ |
||||
- PostgreSQL : http://www.PostgreSQL.org/ |
||||
- PyGreSQL : http://www.druid.net/pygresql/ |
||||
|
||||
|
||||
D'Arcy J.M. Cain |
||||
darcy@druid.net |
||||
|
||||
|
@ -1,125 +0,0 @@ |
||||
PyGreSQL changelog. |
||||
=================== |
||||
|
||||
This software is copyright (c) 1995, Pascal Andre (andre@via.ecp.fr) |
||||
Further copyright 1997, 1998 and 1999 by D'Arcy J.M. Cain (darcy@druid.net) |
||||
See file README for copyright information. |
||||
|
||||
Version 3.3 |
||||
A few cleanups. Mostly there was some confusion about the latest version |
||||
and so I am bumping the number to keep it straight. |
||||
- Added NUMERICOID to list of returned types. This fixes a bug when |
||||
returning aggregates. |
||||
|
||||
Version 3.2 |
||||
- Add WIN32 support (gerhard@bigfoot.de) |
||||
- Fix some DB-API quoting problems (niall.smart@ebeon.com) |
||||
- Moved development into PostgreSQL development tree. |
||||
|
||||
Version 3.1 |
||||
- Fix some quoting functions. In particular handle NULLs better. |
||||
- Use a method to add primary key information rather than direct |
||||
manipulation of the class structures. |
||||
- Break decimal out in _quote (in pg.py) and treat it as float. |
||||
- Treat timestamp like date for quoting purposes. |
||||
- Remove a redundant SELECT from the get method speeding it, and insert |
||||
since it calls get, up a little. |
||||
- Add test for BOOL type in typecast method to pgdbTypeCache class. |
||||
(tv@beamnet.de) |
||||
- Fix pgdb.py to send port as integer to lower level function |
||||
(dildog@l0pht.com) |
||||
- Change pg.py to speed up some operations |
||||
- Allow updates on tables with no primary keys. |
||||
|
||||
Version 3.0 |
||||
- Remove strlen() call from pglarge_write() and get size from object. |
||||
(Richard@Bouska.cz) |
||||
- Add a little more error checking to the quote function in the wrapper |
||||
- Add extra checking in _quote function |
||||
- Wrap query in pg.py for debugging |
||||
- Add DB-API 2.0 support to pgmodule.c (andre@via.ecp.fr) |
||||
- Add DB-API 2.0 wrapper pgdb.py (andre@via.ecp.fr) |
||||
- Correct keyword clash (temp) in tutorial |
||||
- Clean up layout of tutorial |
||||
- Return NULL values as None (rlawrence@lastfoot.com) |
||||
- Change None to NULL in insert and update |
||||
- Change hash-bang lines to use /usr/bin/env |
||||
- Clearing date should be blank (NULL) not TODAY |
||||
- Quote backslashes in strings in _quote (brian@CSUA.Berkeley.EDU) |
||||
- Expanded and clarified build instructions (tbryan@starship.python.net) |
||||
- Make code thread safe (Jerome.Alet@unice.fr) |
||||
- Add README.distutils (mwa@gate.net & jeremy@cnri.reston.va.us) |
||||
- Many fixes and increased DB-API compliance by chifungfan@yahoo.com, |
||||
tony@printra.net, jeremy@alum.mit.edu and others to get the final |
||||
version ready to release. |
||||
|
||||
Version 2.4 |
||||
- Insert returns None if the user doesn't have select permissions |
||||
on the table. It can (and does) happen that one has insert but |
||||
not select permissions on a table. |
||||
- Added ntuples() method to query object (brit@druid.net) |
||||
- Corrected a bug related to getresult() and the money type |
||||
- Corrected a bug related to negative money amounts |
||||
- Allow update based on primary key if munged oid not available and |
||||
table has a primary key |
||||
- Add many __doc__ strings. (andre@via.ecp.fr) |
||||
- Get method works with views if key specified |
||||
|
||||
Version 2.3 |
||||
- connect.host returns "localhost" when connected to Unix socket |
||||
(torppa@tuhnu.cutery.fi) |
||||
- Use PyArg_ParseTupleAndKeywords in connect() (torppa@tuhnu.cutery.fi) |
||||
- fixes and cleanups (torppa@tuhnu.cutery.fi) |
||||
- Fixed memory leak in dictresult() (terekhov@emc.com) |
||||
- Deprecated pgext.py - functionality now in pg.py |
||||
- More cleanups to the tutorial |
||||
- Added fileno() method - terekhov@emc.com (Mikhail Terekhov) |
||||
- added money type to quoting function |
||||
- Compiles cleanly with more warnings turned on |
||||
- Returns PostgreSQL error message on error |
||||
- Init accepts keywords (Jarkko Torppa) |
||||
- Convenience functions can be overridden (Jarkko Torppa) |
||||
- added close() method |
||||
|
||||
Version 2.2 |
||||
- Added user and password support thanks to Ng Pheng Siong <ngps@post1.com> |
||||
- Insert queries return the inserted oid |
||||
- Add new pg wrapper (C modile renamed to _pg) |
||||
- Wrapped database connection in a class. |
||||
- Cleaned up some of the tutorial. (More work needed.) |
||||
- Added version and __version__. Thanks to thilo@eevolute.com for |
||||
the suggestion. |
||||
|
||||
Version 2.1 |
||||
- return fields as proper Python objects for field type |
||||
- Cleaned up pgext.py |
||||
- Added dictresult method |
||||
|
||||
Version 2.0 (23/12/1997): |
||||
- updated code for PostgreSQL 6.2.1 and Python 1.5 |
||||
- reformatted code and converted to ANSI |
||||
- Changed name to PyGreSQL (from PyGres95) |
||||
- changed order of arguments to connect function |
||||
- Created new type pgqueryobject and moved certain methods to it. |
||||
- Added a print function for pgqueryobject |
||||
|
||||
Version 1.0b (4/11/1995): |
||||
- keyword support for connect function moved from library file to C code |
||||
and taken away from library. |
||||
- rewrote documentation |
||||
- bug fix in connect function |
||||
- enhancements in large objects interface methods |
||||
|
||||
Version 1.0a (30/10/1995) (limited release): |
||||
- module adapted to standard Python syntax |
||||
- keyword support for connect function in library file |
||||
- rewrote default parameters interface (internal use of strings) |
||||
- fixed minor bugs in module interface |
||||
- redefinition of error messages |
||||
|
||||
Version 0.9b (10/10/1995) (first public release): |
||||
- large objects implementation |
||||
- many bug fixes, enhancements, ... |
||||
|
||||
Version 0.1a (7/10/1995): |
||||
- basic libpq functions (SQL access) |
@ -1,59 +0,0 @@ |
||||
# $Header: /cvsroot/pgsql/src/interfaces/python/Attic/GNUmakefile,v 1.16 2003/03/21 17:18:34 petere Exp $
|
||||
|
||||
subdir = src/interfaces/python
|
||||
top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global |
||||
|
||||
NAME = _pgmodule
|
||||
SO_MAJOR_VERSION = 2
|
||||
SO_MINOR_VERSION = 4
|
||||
OBJS = pgmodule.o
|
||||
SHLIB_LINK = $(libpq)
|
||||
ifeq ($(PORTNAME), cygwin) |
||||
override CPPFLAGS += -DUSE_DL_IMPORT
|
||||
SHLIB_LINK += $(python_libspec)
|
||||
endif |
||||
|
||||
|
||||
include $(top_srcdir)/src/Makefile.shlib |
||||
|
||||
override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) $(python_includespec) |
||||
|
||||
all: all-lib |
||||
|
||||
all-lib: libpq-all |
||||
|
||||
.PHONY: libpq-all |
||||
libpq-all: |
||||
$(MAKE) -C $(libpq_builddir) all
|
||||
|
||||
install-warning-msg := { \
|
||||
echo "*** Skipping the installation of the Python interface module for lack"; \ |
||||
echo "*** of permissions. To install it, change to the directory"; \ |
||||
echo "*** `pwd`,"; \ |
||||
echo "*** become the appropriate user, and do '$(MAKE) install'."; } |
||||
|
||||
install: all installdirs |
||||
@if test -w $(DESTDIR)$(python_moduleexecdir) && test -w $(DESTDIR)$(python_moduledir); then \
|
||||
echo "$(INSTALL_SHLIB) $(shlib) $(DESTDIR)$(python_moduleexecdir)/_pgmodule$(DLSUFFIX)"; \
|
||||
$(INSTALL_SHLIB) $(shlib) $(DESTDIR)$(python_moduleexecdir)/_pgmodule$(DLSUFFIX); \
|
||||
\
|
||||
echo "$(INSTALL_DATA) $(srcdir)/pg.py $(DESTDIR)$(python_moduledir)/pg.py"; \
|
||||
$(INSTALL_DATA) $(srcdir)/pg.py $(DESTDIR)$(python_moduledir)/pg.py; \
|
||||
\
|
||||
echo "$(INSTALL_DATA) $(srcdir)/pgdb.py $(DESTDIR)$(python_moduledir)/pgdb.py"; \
|
||||
$(INSTALL_DATA) $(srcdir)/pgdb.py $(DESTDIR)$(python_moduledir)/pgdb.py; \
|
||||
else \
|
||||
$(install-warning-msg); \
|
||||
fi
|
||||
|
||||
installdirs: |
||||
$(mkinstalldirs) $(DESTDIR)$(python_moduleexecdir) $(DESTDIR)$(python_moduledir)
|
||||
|
||||
uninstall: |
||||
rm -f $(DESTDIR)$(python_moduleexecdir)/_pgmodule$(DLSUFFIX) \
|
||||
$(DESTDIR)$(python_moduledir)/pg.py \
|
||||
$(DESTDIR)$(python_moduledir)/pgdb.py
|
||||
|
||||
clean distclean maintainer-clean: clean-lib |
||||
rm -f $(OBJS)
|
@ -1,57 +0,0 @@ |
||||
%define version 3.0 |
||||
%define release pre20000310 |
||||
%define name PyGreSQL |
||||
%define pythonversion 1.5 |
||||
Source: %{name}-%{version}-%{release}.tgz |
||||
Summary: A Python interface for PostgreSQL database. |
||||
Name: %{name} |
||||
Version: %{version} |
||||
Release: %{release} |
||||
#Patch: |
||||
Group: Applications/Databases |
||||
BuildRoot: /tmp/rpmbuild_%{name} |
||||
Copyright: GPL-like |
||||
Requires: python >= %{pythonversion}, postgresql |
||||
Packager: Hartmut Goebel <hartmut@goebel.noris.de> |
||||
Vendor: D'Arcy J.M. Cain <darcy@druid.net> |
||||
URL: http://www.druid.net/pygresql/ |
||||
|
||||
%changelog |
||||
#* Tue Oct 06 1998 Fabio Coatti <cova@felix.unife.it> |
||||
#- fixed installation directory files list |
||||
|
||||
%description |
||||
PyGreSQL is a python module that interfaces to a PostgreSQL database. It |
||||
embeds the PostgreSQL query library to allow easy use of the powerful |
||||
PostgreSQL features from a Python script. |
||||
|
||||
Version 3.0 includes DB-API 2.0 support. |
||||
|
||||
%prep |
||||
rm -rf $RPM_BUILD_ROOT |
||||
|
||||
%setup -n %{name}-%{version}-%{release} |
||||
#%patch |
||||
|
||||
%build |
||||
mkdir -p $RPM_BUILD_ROOT/usr/lib/python%{pythonversion}/lib-dynload |
||||
cc -fpic -shared -o $RPM_BUILD_ROOT/usr/lib/python%{pythonversion}/lib-dynload/_pg.so -I/usr/include/pgsql/ -I/usr/include/python1.5 pgmodule.c -lpq |
||||
## import fails, since _pg is not yet installed |
||||
python -c 'import pg' || true |
||||
python -c 'import pgdb' || true |
||||
|
||||
%install |
||||
cp *.py *.pyc $RPM_BUILD_ROOT/usr/lib/python%{pythonversion}/ |
||||
|
||||
cd $RPM_BUILD_ROOT |
||||
find . -type f | sed 's,^\.,\%attr(-\,root\,root) ,' > $RPM_BUILD_DIR/file.list.%{name} |
||||
find . -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name} |
||||
|
||||
%files -f ../file.list.%{name} |
||||
%doc %attr(-,root,root) Announce ChangeLog README tutorial |
||||
|
||||
|
||||
%clean |
||||
rm -rf $RPM_BUILD_ROOT |
||||
cd $RPM_BUILD_DIR |
||||
rm -rf %{name}-%{version}-%{release} file.list.%{name} |
@ -1,264 +0,0 @@ |
||||
|
||||
PyGreSQL - v3.3: PostgreSQL module for Python |
||||
============================================== |
||||
|
||||
0. Copyright notice |
||||
=================== |
||||
|
||||
PyGreSQL, version 3.3 |
||||
A Python interface for PostgreSQL database. |
||||
Written by D'Arcy J.M. Cain, darcy@druid.net<BR> |
||||
Based heavily on code written by Pascal Andre, andre@chimay.via.ecp.fr. |
||||
Copyright (c) 1995, Pascal ANDRE (andre@via.ecp.fr) |
||||
|
||||
Permission to use, copy, modify, and distribute this software and its |
||||
documentation for any purpose, without fee, and without a written agreement |
||||
is hereby granted, provided that the above copyright notice and this |
||||
paragraph and the following two paragraphs appear in all copies or in any |
||||
new file that contains a substantial portion of this file. |
||||
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, |
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, |
||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE |
||||
AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE |
||||
AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, |
||||
ENHANCEMENTS, OR MODIFICATIONS. |
||||
|
||||
Further modifications copyright 1997 - 2000 by D'Arcy J.M. Cain |
||||
(darcy@druid.net) subject to the same terms and conditions as above. |
||||
|
||||
Note that as of March 1 2001 the development of PyGreSQL has been moved |
||||
directly into the PostgreSQL development tree and is subject to the |
||||
PostgreSQL copyright except where contradicted by the above copyrights |
||||
in which case the above copyrights apply. |
||||
|
||||
|
||||
1. Presentation |
||||
=============== |
||||
|
||||
1.1. Introduction |
||||
----------------- |
||||
|
||||
PostgreSQL is a database system derived from Postgres4.2. It conforms to |
||||
(most of) ANSI SQL and offers many interesting capabilities (C dynamic linking |
||||
for functions or type definition, etc.). This package is copyright by the |
||||
Regents of the University of California, and is freely distributable. |
||||
|
||||
Python is an interpreted programming language. It is object oriented, simple |
||||
to use (light syntax, simple and straightforward statements), and has many |
||||
extensions for building GUIs, interfacing with WWW, etc. An intelligent web |
||||
browser (HotJava like) is currently under development (November 1995), and |
||||
this should open programmers many doors. Python is copyrighted by Stichting S |
||||
Mathematisch Centrum, Amsterdam, The Netherlands, and is freely distributable. |
||||
|
||||
PyGreSQL is a python module that interfaces to a PostgreSQL database. It |
||||
embeds the PostgreSQL query library to allow easy use of the powerful |
||||
PostgreSQL features from a Python script. |
||||
|
||||
PyGreSQL 2.0 was developed and tested on a NetBSD 1.3_BETA system. It is |
||||
based on the PyGres95 code written by Pascal Andre, andre@chimay.via.ecp.fr. |
||||
I changed the version to 2.0 and updated the code for Python 1.5 and |
||||
PostgreSQL 6.2.1. While I was at it I upgraded the code to use full ANSI |
||||
style prototypes and changed the order of arguments to connect. |
||||
|
||||
|
||||
1.2. Distribution files |
||||
----------------------- |
||||
|
||||
README - this file |
||||
Announce - announcement of this release |
||||
ChangeLog - changes that affected this package during its history |
||||
pgmodule.c - the C python module |
||||
pg.py - PyGreSQL DB class. |
||||
pgdb.py - DB-SIG DB-API 2.0 compliant API wrapper for PygreSQL |
||||
tutorial/ - demos directory |
||||
Content: basics.py, syscat.py, advanced.py, func.py and |
||||
pgtools.py. The samples here have been taken from the |
||||
PostgreSQL manual and were used for module testing. They |
||||
demonstrate some PostgreSQL features. Pgtools.py is an |
||||
add-in used for demonstration. |
||||
|
||||
1.3. Installation |
||||
----------------- |
||||
|
||||
* If you are building this from source on most systems you can simply add |
||||
the flag "--with-python" to the Configure command when building PostgreSQL. |
||||
This will cause PyGreSQL to be built at the same time. For this to work |
||||
you must already have built Python as well as the mxDateTime package |
||||
from http://starship.python.net/~lemburg/mxDateTime.html. |
||||
|
||||
* For a Linux x86 system that uses RPMs, you can pick up an RPM at |
||||
ftp://ftp.druid.net/pub/distrib/pygresql.i386.rpm |
||||
|
||||
* Note that if you are using the DB-API module you must also install |
||||
mxDateTime from http://starship.python.net/~lemburg/mxDateTime.html. |
||||
|
||||
* Also, check out setup.py for an alternate method of installing the package. |
||||
|
||||
You have two options. You can compile PyGreSQL as a stand-alone module |
||||
or you can build it into the Python interpreter. |
||||
|
||||
GENERAL |
||||
|
||||
* You must first have installed Python and PostgreSQL on your system. |
||||
The header files and developer's libraries for both Python and PostgreSQL |
||||
must be installed on your system before you can build PyGreSQL. If you |
||||
built both Python and PostgreSQL from source, you should be fine. If your |
||||
system uses some package mechanism (such as RPMs or NetBSD packages), then |
||||
you probably need to install packages such as Python-devel in addition to |
||||
the Python package. |
||||
|
||||
* PyGreSQL is implemented as three parts, a C module labeled _pg and two |
||||
Python wrappers called pg.py and pgdb.py. This changed between 2.1 and |
||||
2.2 and again in 3.0. These changes should not affect any existing |
||||
programs but the installation is slightly different. |
||||
|
||||
* Download and unpack the PyGreSQL tarball if you haven't already done so. |
||||
|
||||
STAND-ALONE |
||||
|
||||
* In the directory containing pgmodule.c, run the following command |
||||
cc -fpic -shared -o _pg.so -I[pyInc] -I[pgInc] -L[pgLib] -lpq pgmodule.c |
||||
where: |
||||
[pyInc] = path of the Python include (usually Python.h) |
||||
[pgInc] = path of the PostgreSQL include (usually postgres.h) |
||||
[pgLib] = path of the PostgreSQL libraries (usually libpq.so or libpq.a) |
||||
Some options may be added to this line: |
||||
-DNO_DEF_VAR - no default variables support |
||||
-DNO_DIRECT - no direct access methods |
||||
-DNO_LARGE - no large object support |
||||
-DNO_SNPRINTF - if running a system with no snprintf call |
||||
-DNO_PQSOCKET - if running an older PostgreSQL |
||||
|
||||
On some systems you may need to include -lcrypt in the list of libraries |
||||
to make it compile. |
||||
|
||||
Define NO_PQSOCKET if you are using a version of PostgreSQL before 6.4 |
||||
that does not have the PQsocket function. The other options will be |
||||
described in the next sections. |
||||
|
||||
* Test the new module. Something like the following should work. |
||||
|
||||
$ python |
||||
|
||||
>>> import _pg |
||||
>>> db = _pg.connect('thilo','localhost') |
||||
>>> db.query("INSERT INTO test VALUES ('ping','pong')") |
||||
18304 |
||||
>>> db.query("SELECT * FROM test") |
||||
eins|zwei |
||||
----+---- |
||||
ping|pong |
||||
(1 row) |
||||
|
||||
* Finally, move the _pg.so, pg.py, and pgdb.py to a directory in your |
||||
PYTHONPATH. A good place would be /usr/lib/python1.5/site-python if |
||||
your Python modules are in /usr/lib/python1.5. |
||||
|
||||
BUILT-IN TO PYTHON INTERPRETER |
||||
|
||||
* Find the directory where your 'Setup' file lives (usually ??/Modules) in |
||||
the Python source hierarchy and copy or symlink the 'pgmodule.c' file there. |
||||
|
||||
* Add the following line to your Setup file |
||||
_pg pgmodule.c -I[pgInc] -L[pgLib] -lpq # -lcrypt # needed on some systems |
||||
where: |
||||
[pgInc] = path of PostgreSQL include (often /usr/local/include/python1.5) |
||||
[pgLib] = path of the PostgreSQL libraries (often /usr/local/lib/python1.5) |
||||
Some options may be added to this line: |
||||
-DNO_DEF_VAR - no default variables support |
||||
-DNO_DIRECT - no direct access methods |
||||
-DNO_LARGE - no large object support |
||||
-DNO_SNPRINTF - if running a system with no snprintf call |
||||
-DNO_PQSOCKET - if running an older PostgreSQL |
||||
|
||||
Define NO_PQSOCKET if you are using a version of PostgreSQL before 6.4 |
||||
that does not have the PQsocket function. The other options will be |
||||
described in the next sections. |
||||
|
||||
* If you want a shared module, make sure that the "*shared*" keyword is |
||||
uncommented and add the above line below it. You used to need to install |
||||
your shared modules with "make sharedinstall but this no longer seems |
||||
to be true." |
||||
|
||||
* Copy pg.py to the lib directory where the rest of your modules are. For |
||||
example, that's /usr/local/lib/Python on my system. |
||||
|
||||
* Rebuild Python from the root directory of the Python source hierarchy by |
||||
running 'make -f Makefile.pre.in boot' and 'make && make install' |
||||
|
||||
* For more details read the documentation at the top of Makefile.pre.in |
||||
|
||||
|
||||
1.4. Where to get ... ? |
||||
----------------------- |
||||
|
||||
The home sites of the different packages are: |
||||
|
||||
- Python: http://www.python.org/ |
||||
- PosgreSQL: http://www.PostgreSQL.org/ |
||||
- PyGreSQL: http://www.druid.net/pygresql/ |
||||
|
||||
A Linux RPM can be picked up from |
||||
ftp://ftp.druid.net/pub/distrib/pygresql.i386.rpm. A NetBSD package thould |
||||
be in the distribution soon and is available at |
||||
ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz. A WIN32 package is |
||||
available at http://highqualdev.com/. |
||||
|
||||
1.5. Information and support |
||||
---------------------------- |
||||
|
||||
If you need information about these packages please check their web sites: |
||||
|
||||
- Python: http://www.python.org/ |
||||
- PostgreSQL: http://www.postgresql.org/ |
||||
- PyGres95: http://www.via.ecp.fr/via/products/pygres.html |
||||
- PyGreSQL: http://www.druid.net/pygresql/ |
||||
|
||||
For support: |
||||
|
||||
- Python: newgroup comp.lang.python |
||||
- PostgreSQL: mailing list (see package documentation for information) |
||||
- PyGres95: contact me (andre@via.ecp.fr) for bug reports, ideas, |
||||
remarks I will try to answer as long as my free time allow |
||||
me to do that. |
||||
- PyGreSQL: contact me (darcy@druid.net) concerning the changes to 2.x |
||||
and up. If you would like to proposes changes please |
||||
join the PyGreSQL mailing list and send context diffs |
||||
there. See http://www.vex.net/mailman/listinfo/pygresql |
||||
to join the mailing list. |
||||
|
||||
|
||||
2. Programming information |
||||
========================== |
||||
|
||||
See main PostgreSQL documentation. |
||||
|
||||
|
||||
3. Todo |
||||
======= |
||||
|
||||
The large object and direct access functions need much more attention. |
||||
|
||||
An update query should return the number of rows affected. |
||||
|
||||
The C module needs to be cleaned up and redundant code merged. |
||||
|
||||
The DB-API module needs to be documented. |
||||
|
||||
The fetch method should use real cursors. |
||||
|
||||
|
||||
4. Future directions |
||||
==================== |
||||
|
||||
Users should be able to register their own types with _pg. |
||||
|
||||
I would like a new method that returns a dictionary of dictionaries from |
||||
a SELECT. |
||||
|
||||
|
@ -1,3 +0,0 @@ |
||||
*shared* |
||||
|
||||
_pg pgmodule.c -I@libpq_srcdir@ @INCLUDES@ -L@libpq_builddir@ -lpq @EXTRA_LIBS@ |
@ -1,302 +0,0 @@ |
||||
# pg.py |
||||
# Written by D'Arcy J.M. Cain |
||||
|
||||
# This library implements some basic database management stuff. It |
||||
# includes the pg module and builds on it. This is known as the |
||||
# "Classic" interface. For DB-API compliance use the pgdb module. |
||||
|
||||
from _pg import * |
||||
from types import * |
||||
import string, re, sys |
||||
|
||||
# utility function |
||||
# We expect int, seq, decimal, text or date (more later) |
||||
def _quote(d, t): |
||||
if d == None: |
||||
return "NULL" |
||||
|
||||
if t in ['int', 'seq']: |
||||
if d == "": return "NULL" |
||||
return "%d" % long(d) |
||||
|
||||
if t == 'decimal': |
||||
if d == "": return "NULL" |
||||
return "%f" % float(d) |
||||
|
||||
if t == 'money': |
||||
if d == "": return "NULL" |
||||
return "'%.2f'" % float(d) |
||||
|
||||
if t == 'bool': |
||||
# Can't run upper() on these |
||||
if d in (0, 1): return ("'f'", "'t'")[d] |
||||
|
||||
if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', '1', 'ON']: |
||||
return "'t'" |
||||
else: |
||||
return "'f'" |
||||
|
||||
if t == 'date' and d == '': return "NULL" |
||||
if t in ('inet', 'cidr') and d == '': return "NULL" |
||||
|
||||
return "'%s'" % string.strip(re.sub("'", "''", \ |
||||
re.sub("\\\\", "\\\\\\\\", "%s" % d))) |
||||
|
||||
class DB: |
||||
"""This class wraps the pg connection type""" |
||||
|
||||
def __init__(self, *args, **kw): |
||||
self.db = apply(connect, args, kw) |
||||
|
||||
# Create convience methods, in a way that is still overridable |
||||
# (members are not copied because they are actually functions) |
||||
for e in self.db.__methods__: |
||||
setattr(self, e, getattr(self.db, e)) |
||||
|
||||
self.__attnames__ = {} |
||||
self.__pkeys__ = {} |
||||
self.debug = None # For debugging scripts, set to output format |
||||
# that takes a single string arg. For example |
||||
# in a CGI set to "%s<BR>" |
||||
|
||||
def _do_debug(self, s): |
||||
if not self.debug: return |
||||
if type(self.debug) == StringType: print self.debug % s |
||||
if type(self.debug) == FunctionType: self.debug(s) |
||||
if type(self.debug) == FileType: print >> self.debug, s |
||||
|
||||
# wrap query for debugging |
||||
def query(self, qstr): |
||||
self._do_debug(qstr) |
||||
return self.db.query(qstr) |
||||
|
||||
def pkey(self, cl, newpkey = None): |
||||
"""This method returns the primary key of a class. If newpkey |
||||
is set and is set and is not a dictionary then set that |
||||
value as the primary key of the class. If it is a dictionary |
||||
then replace the __pkeys__ dictionary with it.""" |
||||
# Get all the primary keys at once |
||||
if type(newpkey) == DictType: |
||||
self.__pkeys__ = newpkey |
||||
return |
||||
|
||||
if newpkey: |
||||
self.__pkeys__[cl] = newpkey |
||||
return newpkey |
||||
|
||||
if self.__pkeys__ == {}: |
||||
for rel, att in self.db.query("""SELECT |
||||
pg_class.relname, pg_attribute.attname |
||||
FROM pg_class, pg_attribute, pg_index |
||||
WHERE pg_class.oid = pg_attribute.attrelid AND |
||||
pg_class.oid = pg_index.indrelid AND |
||||
pg_index.indkey[0] = pg_attribute.attnum AND |
||||
pg_index.indisprimary = 't' AND |
||||
pg_attribute.attisdropped = 'f'""").getresult(): |
||||
self.__pkeys__[rel] = att |
||||
|
||||
# will raise an exception if primary key doesn't exist |
||||
return self.__pkeys__[cl] |
||||
|
||||
def get_databases(self): |
||||
l = [] |
||||
for n in self.db.query("SELECT datname FROM pg_database").getresult(): |
||||
l.append(n[0]) |
||||
return l |
||||
|
||||
def get_tables(self): |
||||
l = [] |
||||
for n in self.db.query("""SELECT relname FROM pg_class |
||||
WHERE relkind = 'r' AND |
||||
relname !~ '^Inv' AND |
||||
relname !~ '^pg_'""").getresult(): |
||||
l.append(n[0]) |
||||
return l |
||||
|
||||
def get_attnames(self, cl, newattnames = None): |
||||
"""This method gets a list of attribute names for a class. If |
||||
the optional newattnames exists it must be a dictionary and |
||||
will become the new attribute names dictionary.""" |
||||
|
||||
if type(newattnames) == DictType: |
||||
self.__attnames__ = newattnames |
||||
return |
||||
elif newattnames: |
||||
raise error, "If supplied, newattnames must be a dictionary" |
||||
|
||||
# May as well cache them |
||||
if self.__attnames__.has_key(cl): |
||||
return self.__attnames__[cl] |
||||
|
||||
query = """SELECT pg_attribute.attname, pg_type.typname |
||||
FROM pg_class, pg_attribute, pg_type |
||||
WHERE pg_class.relname = '%s' AND |
||||
pg_attribute.attnum > 0 AND |
||||
pg_attribute.attrelid = pg_class.oid AND |
||||
pg_attribute.atttypid = pg_type.oid AND |
||||
pg_attribute.attisdropped = 'f'""" |
||||
|
||||
l = {} |
||||
for attname, typname in self.db.query(query % cl).getresult(): |
||||
if re.match("^int", typname): |
||||
l[attname] = 'int' |
||||
elif re.match("^oid", typname): |
||||
l[attname] = 'int' |
||||
elif re.match("^text", typname): |
||||
l[attname] = 'text' |
||||
elif re.match("^char", typname): |
||||
l[attname] = 'text' |
||||
elif re.match("^name", typname): |
||||
l[attname] = 'text' |
||||
elif re.match("^abstime", typname): |
||||
l[attname] = 'date' |
||||
elif re.match("^date", typname): |
||||
l[attname] = 'date' |
||||
elif re.match("^timestamp", typname): |
||||
l[attname] = 'date' |
||||
elif re.match("^bool", typname): |
||||
l[attname] = 'bool' |
||||
elif re.match("^float", typname): |
||||
l[attname] = 'decimal' |
||||
elif re.match("^money", typname): |
||||
l[attname] = 'money' |
||||
else: |
||||
l[attname] = 'text' |
||||
|
||||
l['oid'] = 'int' # every table has this |
||||
self.__attnames__[cl] = l # cache it |
||||
return self.__attnames__[cl] |
||||
|
||||
# return a tuple from a database |
||||
def get(self, cl, arg, keyname = None, view = 0): |
||||
if cl[-1] == '*': # need parent table name |
||||
xcl = cl[:-1] |
||||
else: |
||||
xcl = cl |
||||
|
||||
if keyname == None: # use the primary key by default |
||||
keyname = self.pkey(xcl) |
||||
|
||||
fnames = self.get_attnames(xcl) |
||||
|
||||
if type(arg) == DictType: |
||||
# To allow users to work with multiple tables we munge the |
||||
# name when the key is "oid" |
||||
if keyname == 'oid': k = arg['oid_%s' % xcl] |
||||
else: k = arg[keyname] |
||||
else: |
||||
k = arg |
||||
arg = {} |
||||
|
||||
# We want the oid for later updates if that isn't the key |
||||
if keyname == 'oid': |
||||
q = "SELECT * FROM %s WHERE oid = %s" % (cl, k) |
||||
elif view: |
||||
q = "SELECT * FROM %s WHERE %s = %s" % \ |
||||
(cl, keyname, _quote(k, fnames[keyname])) |
||||
else: |
||||
q = "SELECT oid AS oid_%s, %s FROM %s WHERE %s = %s" % \ |
||||
(xcl, string.join(fnames.keys(), ','),\ |
||||
cl, keyname, _quote(k, fnames[keyname])) |
||||
|
||||
self._do_debug(q) |
||||
res = self.db.query(q).dictresult() |
||||
if res == []: |
||||
raise error, \ |
||||
"No such record in %s where %s is %s" % \ |
||||
(cl, keyname, _quote(k, fnames[keyname])) |
||||
return None |
||||
|
||||
for k in res[0].keys(): |
||||
arg[k] = res[0][k] |
||||
|
||||
return arg |
||||
|
||||
# Inserts a new tuple into a table |
||||
# We currently don't support insert into views although PostgreSQL does |
||||
def insert(self, cl, a): |
||||
fnames = self.get_attnames(cl) |
||||
l = [] |
||||
n = [] |
||||
for f in fnames.keys(): |
||||
if f != 'oid' and a.has_key(f): |
||||
l.append(_quote(a[f], fnames[f])) |
||||
n.append(f) |
||||
|
||||
try: |
||||
q = "INSERT INTO %s (%s) VALUES (%s)" % \ |
||||
(cl, string.join(n, ','), string.join(l, ',')) |
||||
self._do_debug(q) |
||||
a['oid_%s' % cl] = self.db.query(q) |
||||
except: |
||||
raise error, "Error inserting into %s: %s" % (cl, sys.exc_value) |
||||
|
||||
# reload the dictionary to catch things modified by engine |
||||
# note that get() changes 'oid' below to oid_table |
||||
# if no read perms (it can and does happen) return None |
||||
try: return self.get(cl, a, 'oid') |
||||
except: return None |
||||
|
||||
# Update always works on the oid which get returns if available |
||||
# otherwise use the primary key. Fail if neither. |
||||
def update(self, cl, a): |
||||
self.pkey(cl) # make sure we have a self.__pkeys__ dictionary |
||||
|
||||
foid = 'oid_%s' % cl |
||||
if a.has_key(foid): |
||||
where = "oid = %s" % a[foid] |
||||
elif self.__pkeys__.has_key(cl) and a.has_key(self.__pkeys__[cl]): |
||||
where = "%s = '%s'" % (self.__pkeys__[cl], a[self.__pkeys__[cl]]) |
||||
else: |
||||
raise error, "Update needs primary key or oid as %s" % foid |
||||
|
||||
v = [] |
||||
k = 0 |
||||
fnames = self.get_attnames(cl) |
||||
|
||||
for ff in fnames.keys(): |
||||
if ff != 'oid' and a.has_key(ff): |
||||
v.append("%s = %s" % (ff, _quote(a[ff], fnames[ff]))) |
||||
|
||||
if v == []: |
||||
return None |
||||
|
||||
try: |
||||
q = "UPDATE %s SET %s WHERE %s" % \ |
||||
(cl, string.join(v, ','), where) |
||||
self._do_debug(q) |
||||
self.db.query(q) |
||||
except: |
||||
raise error, "Can't update %s: %s" % (cl, sys.exc_value) |
||||
|
||||
# reload the dictionary to catch things modified by engine |
||||
if a.has_key(foid): |
||||
return self.get(cl, a, 'oid') |
||||
else: |
||||
return self.get(cl, a) |
||||
|
||||
# At some point we will need a way to get defaults from a table |
||||
def clear(self, cl, a = {}): |
||||
fnames = self.get_attnames(cl) |
||||
for ff in fnames.keys(): |
||||
if fnames[ff] in ['int', 'decimal', 'seq', 'money']: |
||||
a[ff] = 0 |
||||
else: |
||||
a[ff] = "" |
||||
|
||||
a['oid'] = 0 |
||||
return a |
||||
|
||||
# Like update, delete works on the oid |
||||
# one day we will be testing that the record to be deleted |
||||
# isn't referenced somewhere (or else PostgreSQL will) |
||||
def delete(self, cl, a): |
||||
try: |
||||
q = "DELETE FROM %s WHERE oid = %s" % (cl, a['oid_%s' % cl]) |
||||
self._do_debug(q) |
||||
self.db.query(q) |
||||
except: |
||||
raise error, "Can't delete %s: %s" % (cl, sys.exc_value) |
||||
|
||||
return None |
||||
|
@ -1,452 +0,0 @@ |
||||
""" pgdb - DB-SIG compliant module for PygreSQL. |
||||
|
||||
(c) 1999, Pascal Andre <andre@via.ecp.fr>. |
||||
See package documentation for further information on copyright. |
||||
|
||||
Inline documentation is sparse. See DB-SIG 2.0 specification for |
||||
usage information. |
||||
|
||||
basic usage: |
||||
|
||||
pgdb.connect(connect_string) -> connection |
||||
connect_string = 'host:database:user:password:opt:tty' |
||||
All parts are optional. You may also pass host through |
||||
password as keyword arguments. To pass a port, pass it in |
||||
the host keyword parameter: |
||||
pgdb.connect(host='localhost:5432') |
||||
|
||||
connection.cursor() -> cursor |
||||
|
||||
connection.commit() |
||||
|
||||
connection.close() |
||||
|
||||
connection.rollback() |
||||
|
||||
cursor.execute(query[, params]) |
||||
execute a query, binding params (a dictionary) if it is |
||||
passed. The binding syntax is the same as the % operator |
||||
for dictionaries, and no quoting is done. |
||||
|
||||
cursor.executemany(query, list of params) |
||||
execute a query many times, binding each param dictionary |
||||
from the list. |
||||
|
||||
cursor.fetchone() -> [value, value, ...] |
||||
|
||||
cursor.fetchall() -> [[value, value, ...], ...] |
||||
|
||||
cursor.fetchmany([size]) -> [[value, value, ...], ...] |
||||
returns size or cursor.arraysize number of rows from result |
||||
set. Default cursor.arraysize is 1. |
||||
|
||||
cursor.description -> [(column_name, type_name, display_size, |
||||
internal_size, precision, scale, null_ok), ...] |
||||
|
||||
Note that precision, scale and null_ok are not implemented. |
||||
|
||||
cursor.rowcount |
||||
number of rows available in the result set. Available after |
||||
a call to execute. |
||||
|
||||
cursor.close() |
||||
|
||||
""" |
||||
|
||||
import _pg |
||||
import string |
||||
import exceptions |
||||
import types |
||||
import time |
||||
import types |
||||
|
||||
# Marc-Andre is changing where DateTime goes. This handles it either way. |
||||
try: from mx import DateTime |
||||
except ImportError: import DateTime |
||||
|
||||
### module constants |
||||
|
||||
# compliant with DB SIG 2.0 |
||||
apilevel = '2.0' |
||||
|
||||
# module may be shared, but not connections |
||||
threadsafety = 1 |
||||
|
||||
# this module use extended python format codes |
||||
paramstyle = 'pyformat' |
||||
|
||||
### exception hierarchy |
||||
|
||||
class Warning(StandardError): |
||||
pass |
||||
|
||||
class Error(StandardError): |
||||
pass |
||||
|
||||
class InterfaceError(Error): |
||||
pass |
||||
|
||||
class DatabaseError(Error): |
||||
pass |
||||
|
||||
class DataError(DatabaseError): |
||||
pass |
||||
|
||||
class OperationalError(DatabaseError): |
||||
pass |
||||
|
||||
class IntegrityError(DatabaseError): |
||||
pass |
||||
|
||||
class InternalError(DatabaseError): |
||||
pass |
||||
|
||||
class ProgrammingError(DatabaseError): |
||||
pass |
||||
|
||||
class NotSupportedError(DatabaseError): |
||||
pass |
||||
|
||||
### internal type handling class |
||||
class pgdbTypeCache: |
||||
|
||||
def __init__(self, cnx): |
||||
self.__source = cnx.source() |
||||
self.__type_cache = {} |
||||
|
||||
def typecast(self, typ, value): |
||||
# for NULL values, no typecast is necessary |
||||
if value == None: |
||||
return value |
||||
|
||||
if typ == STRING: |
||||
pass |
||||
elif typ == BINARY: |
||||
pass |
||||
elif typ == BOOL: |
||||
value = (value[:1] in ['t','T']) |
||||
elif typ == INTEGER: |
||||
value = int(value) |
||||
elif typ == LONG: |
||||
value = long(value) |
||||
elif typ == FLOAT: |
||||
value = float(value) |
||||
elif typ == MONEY: |
||||
value = string.replace(value, "$", "") |
||||
value = string.replace(value, ",", "") |
||||
value = float(value) |
||||
elif typ == DATETIME: |
||||
# format may differ ... we'll give string |
||||
pass |
||||
elif typ == ROWID: |
||||
value = long(value) |
||||
return value |
||||
|
||||
def getdescr(self, oid): |
||||
try: |
||||
return self.__type_cache[oid] |
||||
except: |
||||
self.__source.execute( |
||||
"SELECT typname, typlen " |
||||
"FROM pg_type WHERE oid = %s" % oid |
||||
) |
||||
res = self.__source.fetch(1)[0] |
||||
# column name is omitted from the return value. It will |
||||
# have to be prepended by the caller. |
||||
res = ( |
||||
res[0], |
||||
None, string.atoi(res[1]), |
||||
None, None, None |
||||
) |
||||
self.__type_cache[oid] = res |
||||
return res |
||||
|
||||
### cursor object |
||||
|
||||
class pgdbCursor: |
||||
|
||||
def __init__(self, src, cache): |
||||
self.__cache = cache |
||||
self.__source = src |
||||
self.description = None |
||||
self.rowcount = -1 |
||||
self.arraysize = 1 |
||||
|
||||
def close(self): |
||||
self.__source.close() |
||||
self.description = None |
||||
self.rowcount = -1 |
||||
|
||||
def execute(self, operation, params = None): |
||||
# "The parameters may also be specified as list of |
||||
# tuples to e.g. insert multiple rows in a single |
||||
# operation, but this kind of usage is deprecated: |
||||
if params and type(params) == types.ListType and \ |
||||
type(params[0]) == types.TupleType: |
||||
self.executemany(operation, params) |
||||
else: |
||||
# not a list of tuples |
||||
self.executemany(operation, (params,)) |
||||
|
||||
def executemany(self, operation, param_seq): |
||||
self.description = None |
||||
self.rowcount = -1 |
||||
|
||||
# first try to execute all queries |
||||
totrows = 0 |
||||
sql = "INIT" |
||||
try: |
||||
for params in param_seq: |
||||
if params != None: |
||||
sql = _quoteparams(operation, params) |
||||
else: |
||||
sql = operation |
||||
rows = self.__source.execute(sql) |
||||
if rows != None: # true is __source is NOT a DQL |
||||
totrows = totrows + rows |
||||
except _pg.error, msg: |
||||
raise DatabaseError, "error '%s' in '%s'" % ( msg, sql ) |
||||
except: |
||||
raise OperationalError, "internal error in '%s'" % sql |
||||
|
||||
# then initialize result raw count and description |
||||
if self.__source.resulttype == _pg.RESULT_DQL: |
||||
self.rowcount = self.__source.ntuples |
||||
d = [] |
||||
for typ in self.__source.listinfo(): |
||||
# listinfo is a sequence of |
||||
# (index, column_name, type_oid) |
||||
# getdescr returns all items needed for a |
||||
# description tuple except the column_name. |
||||
desc = typ[1:2]+self.__cache.getdescr(typ[2]) |
||||
d.append(desc) |
||||
self.description = d |
||||
else: |
||||
self.rowcount = totrows |
||||
self.description = None |
||||
|
||||
def fetchone(self): |
||||
res = self.fetchmany(1, 0) |
||||
try: |
||||
return res[0] |
||||
except: |
||||
return None |
||||
|
||||
def fetchall(self): |
||||
return self.fetchmany(-1, 0) |
||||
|
||||
def fetchmany(self, size = None, keep = 1): |
||||
if size == None: |
||||
size = self.arraysize |
||||
if keep == 1: |
||||
self.arraysize = size |
||||
|
||||
try: res = self.__source.fetch(size) |
||||
except _pg.error, e: raise DatabaseError, str(e) |
||||
|
||||
result = [] |
||||
for r in res: |
||||
row = [] |
||||
for i in range(len(r)): |
||||
row.append(self.__cache.typecast( |
||||
self.description[i][1], |
||||
r[i] |
||||
) |
||||
) |
||||
result.append(row) |
||||
return result |
||||
|
||||
def nextset(self): |
||||
raise NotSupportedError, "nextset() is not supported" |
||||
|
||||
def setinputsizes(self, sizes): |
||||
pass |
||||
|
||||
def setoutputsize(self, size, col = 0): |
||||
pass |
||||
|
||||
|
||||
try: |
||||
_quote = _pg.quote_fast |
||||
_quoteparams = _pg.quoteparams_fast |
||||
except (NameError, AttributeError): |
||||
def _quote(x): |
||||
if type(x) == DateTime.DateTimeType: |
||||
x = str(x) |
||||
if type(x) == types.StringType: |
||||
x = "'" + string.replace( |
||||
string.replace(str(x), '\\', '\\\\'), "'", "''") + "'" |
||||
|
||||
elif type(x) in (types.IntType, types.LongType, types.FloatType): |
||||
pass |
||||
elif x is None: |
||||
x = 'NULL' |
||||
elif type(x) in (types.ListType, types.TupleType): |
||||
x = '(%s)' % string.join(map(lambda x: str(_quote(x)), x), ',') |
||||
elif hasattr(x, '__pg_repr__'): |
||||
x = x.__pg_repr__() |
||||
else: |
||||
raise InterfaceError, 'do not know how to handle type %s' % type(x) |
||||
|
||||
return x |
||||
|
||||
def _quoteparams(s, params): |
||||
if hasattr(params, 'has_key'): |
||||
x = {} |
||||
for k, v in params.items(): |
||||
x[k] = _quote(v) |
||||
params = x |
||||
else: |
||||
params = tuple(map(_quote, params)) |
||||
|
||||
return s % params |
||||
|
||||
### connection object |
||||
|
||||
class pgdbCnx: |
||||
|
||||
def __init__(self, cnx): |
||||
self.__cnx = cnx |
||||
self.__cache = pgdbTypeCache(cnx) |
||||
try: |
||||
src = self.__cnx.source() |
||||
src.execute("BEGIN") |
||||
except: |
||||
raise OperationalError, "invalid connection." |
||||
|
||||
def close(self): |
||||
self.__cnx.close() |
||||
|
||||
def commit(self): |
||||
try: |
||||
src = self.__cnx.source() |
||||
src.execute("COMMIT") |
||||
src.execute("BEGIN") |
||||
except: |
||||
raise OperationalError, "can't commit." |
||||
|
||||
def rollback(self): |
||||
try: |
||||
src = self.__cnx.source() |
||||
src.execute("ROLLBACK") |
||||
src.execute("BEGIN") |
||||
except: |
||||
raise OperationalError, "can't rollback." |
||||
|
||||
def cursor(self): |
||||
try: |
||||
src = self.__cnx.source() |
||||
return pgdbCursor(src, self.__cache) |
||||
except: |
||||
raise pgOperationalError, "invalid connection." |
||||
|
||||
### module interface |
||||
|
||||
# connects to a database |
||||
def connect(dsn = None, user = None, password = None, host = None, database = None): |
||||
# first get params from DSN |
||||
dbport = -1 |
||||
dbhost = "" |
||||
dbbase = "" |
||||
dbuser = "" |
||||
dbpasswd = "" |
||||
dbopt = "" |
||||
dbtty = "" |
||||
try: |
||||
params = string.split(dsn, ":") |
||||
dbhost = params[0] |
||||
dbbase = params[1] |
||||
dbuser = params[2] |
||||
dbpasswd = params[3] |
||||
dbopt = params[4] |
||||
dbtty = params[5] |
||||
except: |
||||
pass |
||||
|
||||
# override if necessary |
||||
if user != None: |
||||
dbuser = user |
||||
if password != None: |
||||
dbpasswd = password |
||||
if database != None: |
||||
dbbase = database |
||||
if host != None: |
||||
try: |
||||
params = string.split(host, ":") |
||||
dbhost = params[0] |
||||
dbport = int(params[1]) |
||||
except: |
||||
pass |
||||
|
||||
# empty host is localhost |
||||
if dbhost == "": |
||||
dbhost = None |
||||
if dbuser == "": |
||||
dbuser = None |
||||
|
||||
# open the connection |
||||
cnx = _pg.connect(dbbase, dbhost, dbport, dbopt, |
||||
dbtty, dbuser, dbpasswd) |
||||
return pgdbCnx(cnx) |
||||
|
||||
### types handling |
||||
|
||||
# PostgreSQL is object-oriented: types are dynamic. We must thus use type names |
||||
# as internal type codes. |
||||
|
||||
class pgdbType: |
||||
|
||||
def __init__(self, *values): |
||||
self.values= values |
||||
|
||||
def __cmp__(self, other): |
||||
if other in self.values: |
||||
return 0 |
||||
if other < self.values: |
||||
return 1 |
||||
else: |
||||
return -1 |
||||
|
||||
STRING = pgdbType( |
||||
'char', 'bpchar', 'name', 'text', 'varchar' |
||||
) |
||||
|
||||
# BLOB support is pg specific |
||||
BINARY = pgdbType() |
||||
INTEGER = pgdbType('int2', 'int4', 'serial') |
||||
LONG = pgdbType('int8') |
||||
FLOAT = pgdbType('float4', 'float8', 'numeric') |
||||
BOOL = pgdbType('bool') |
||||
MONEY = pgdbType('money') |
||||
|
||||
# this may be problematic as type are quite different ... I hope it won't hurt |
||||
DATETIME = pgdbType( |
||||
'abstime', 'reltime', 'tinterval', 'date', 'time', 'timespan', 'timestamp', 'timestamptz', 'interval' |
||||
) |
||||
|
||||
# OIDs are used for everything (types, tables, BLOBs, rows, ...). This may cause |
||||
# confusion, but we are unable to find out what exactly is behind the OID (at |
||||
# least not easily enough). Should this be undefined as BLOBs ? |
||||
ROWID = pgdbType( |
||||
'oid', 'oid8' |
||||
) |
||||
|
||||
# mandatory type helpers |
||||
def Date(year, month, day): |
||||
return DateTime.DateTime(year, month, day) |
||||
|
||||
def Time(hour, minute, second): |
||||
return DateTime.TimeDelta(hour, minute, second) |
||||
|
||||
def Timestamp(year, month, day, hour, minute, second): |
||||
return DateTime.DateTime(year, month, day, hour, minute, second) |
||||
|
||||
def DateFromTicks(ticks): |
||||
return apply(Date, time.localtime(ticks)[:3]) |
||||
|
||||
def TimeFromTicks(ticks): |
||||
return apply(Time, time.localtime(ticks)[3:6]) |
||||
|
||||
def TimestampFromTicks(ticks): |
||||
return apply(Timestamp, time.localtime(ticks)[:6]) |
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,56 +0,0 @@ |
||||
#!/usr/bin/env python |
||||
|
||||
# Setup script for the PyGreSQL version 3 |
||||
# created 2000/04 Mark Alexander <mwa@gate.net> |
||||
# tweaked 2000/05 Jeremy Hylton <jeremy@cnri.reston.va.us> |
||||
# win32 support 2001/01 Gerhard Haering <gerhard@bigfoot.de> |
||||
|
||||
# requires distutils; standard in Python 1.6, otherwise download from |
||||
# http://www.python.org/sigs/distutils-sig/download.html |
||||
|
||||
# You may have to change the first 3 variables (include_dirs, |
||||
# library_dirs, optional_libs) to match your postgres distribution. |
||||
|
||||
# Now, you can: |
||||
# python setup.py build # to build the module |
||||
# python setup.py install # to install it |
||||
|
||||
# See http://www.python.org/sigs/distutils-sig/doc/ for more information |
||||
# on using distutils to install Python programs. |
||||
|
||||
from distutils.core import setup |
||||
from distutils.extension import Extension |
||||
import sys |
||||
|
||||
if sys.platform == "win32": |
||||
# If you want to build from source; you must have built a win32 native libpq # before and copied libpq.dll into the PyGreSQL root directory. |
||||
win_pg_build_root = 'd:/dev/pg/postgresql-7.0.2/' |
||||
include_dirs=[ win_pg_build_root + 'src/include', win_pg_build_root + '/src/include/libpq', win_pg_build_root + 'src', win_pg_build_root + 'src/interfaces/libpq' ] |
||||
library_dirs=[ win_pg_build_root + 'src/interfaces/libpq/Release' ] |
||||
optional_libs=[ 'libpqdll', 'wsock32', 'advapi32' ] |
||||
data_files = [ 'libpq.dll' ] |
||||
else: |
||||
include_dirs=['../../include','../libpq','/usr/include/pgsql'] |
||||
library_dirs=['../libpq','/usr/lib/pgsql'] |
||||
optional_libs=['pq'] |
||||
data_files = [] |
||||
|
||||
setup (name = "PyGreSQL", |
||||
version = "3.3", |
||||
description = "Python PostgreSQL Interfaces", |
||||
author = "D'Arcy J. M. Cain", |
||||
author_email = "darcy@druid.net", |
||||
url = "http://www.druid.net/pygresql/", |
||||
licence = "Python", |
||||
|
||||
py_modules = ['pg', 'pgdb'], |
||||
ext_modules = [ Extension( |
||||
name='_pg', |
||||
sources = ['pgmodule.c'], |
||||
include_dirs = include_dirs, |
||||
library_dirs = library_dirs, |
||||
libraries = optional_libs |
||||
)], |
||||
data_files = data_files |
||||
) |
||||
|
@ -1,198 +0,0 @@ |
||||
#! /usr/bin/env python |
||||
# advanced.py - demo of advanced features of PostGres. Some may not be ANSI. |
||||
# inspired from the Postgres tutorial |
||||
# adapted to Python 1995 by Pascal Andre |
||||
|
||||
print """ |
||||
__________________________________________________________________ |
||||
MODULE ADVANCED.PY : ADVANCED POSTGRES SQL COMMANDS TUTORIAL |
||||
|
||||
This module is designed for being imported from python prompt |
||||
|
||||
In order to run the samples included here, first create a connection |
||||
using : cnx = advanced.DB(...) |
||||
|
||||
The "..." should be replaced with whatever arguments you need to open an |
||||
existing database. Usually all you need is the name of the database and, |
||||
in fact, if it is the same as your login name, you can leave it empty. |
||||
|
||||
then start the demo with: advanced.demo(cnx) |
||||
__________________________________________________________________ |
||||
""" |
||||
|
||||
from pg import DB |
||||
import sys |
||||
|
||||
# waits for a key |
||||
def wait_key(): |
||||
print "Press <enter>" |
||||
sys.stdin.read(1) |
||||
|
||||
# inheritance features |
||||
def inherit_demo(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Inheritance:" |
||||
print "-- a table can inherit from zero or more tables. A query" |
||||
print "-- can reference either all rows of a table or all rows " |
||||
print "-- of a table plus all of its descendants." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- For example, the capitals table inherits from cities table." |
||||
print "-- (It inherits all data fields from cities.)" |
||||
print |
||||
print "CREATE TABLE cities (" |
||||
print " name text," |
||||
print " population float8," |
||||
print " altitude int" |
||||
print ")" |
||||
print |
||||
print "CREATE TABLE capitals (" |
||||
print " state varchar(2)" |
||||
print ") INHERITS (cities)" |
||||
pgcnx.query("""CREATE TABLE cities ( |
||||
name text, |
||||
population float8, |
||||
altitude int)""") |
||||
pgcnx.query("""CREATE TABLE capitals ( |
||||
state varchar(2)) INHERITS (cities)""") |
||||
wait_key() |
||||
print |
||||
print "-- now, let's populate the tables" |
||||
print |
||||
print "INSERT INTO cities VALUES ('San Francisco', 7.24E+5, 63)" |
||||
print "INSERT INTO cities VALUES ('Las Vegas', 2.583E+5, 2174)" |
||||
print "INSERT INTO cities VALUES ('Mariposa', 1200, 1953)" |
||||
print |
||||
print "INSERT INTO capitals VALUES ('Sacramento', 3.694E+5, 30, 'CA')" |
||||
print "INSERT INTO capitals VALUES ('Madison', 1.913E+5, 845, 'WI')" |
||||
print |
||||
pgcnx.query("INSERT INTO cities VALUES ('San Francisco', 7.24E+5, 63)") |
||||
pgcnx.query("INSERT INTO cities VALUES ('Las Vegas', 2.583E+5, 2174)") |
||||
pgcnx.query("INSERT INTO cities VALUES ('Mariposa', 1200, 1953)") |
||||
pgcnx.query("INSERT INTO capitals VALUES ('Sacramento',3.694E+5,30,'CA')") |
||||
pgcnx.query("INSERT INTO capitals VALUES ('Madison', 1.913E+5, 845, 'WI')") |
||||
print |
||||
print "SELECT * FROM cities" |
||||
print pgcnx.query("SELECT * FROM cities") |
||||
print "SELECT * FROM capitals" |
||||
print pgcnx.query("SELECT * FROM capitals") |
||||
print |
||||
print "-- like before, a regular query references rows of the base" |
||||
print "-- table only" |
||||
print |
||||
print "SELECT name, altitude" |
||||
print "FROM cities" |
||||
print "WHERE altitude > 500;" |
||||
print pgcnx.query("""SELECT name, altitude |
||||
FROM cities |
||||
WHERE altitude > 500""") |
||||
print |
||||
print "-- on the other hand, you can find all cities, including " |
||||
print "-- capitals, that are located at an altitude of 500 'ft " |
||||
print "-- or higher by:" |
||||
print |
||||
print "SELECT c.name, c.altitude" |
||||
print "FROM cities* c" |
||||
print "WHERE c.altitude > 500" |
||||
print pgcnx.query("""SELECT c.name, c.altitude |
||||
FROM cities* c |
||||
WHERE c.altitude > 500""") |
||||
|
||||
# arrays attributes |
||||
def array_demo(pgcnx): |
||||
print "----------------------" |
||||
print "-- Arrays:" |
||||
print "-- attributes can be arrays of base types or user-defined " |
||||
print "-- types" |
||||
print "----------------------" |
||||
print |
||||
print "CREATE TABLE sal_emp (" |
||||
print " name text," |
||||
print " pay_by_quarter int4[]," |
||||
print " pay_by_extra_quarter int8[]," |
||||
print " schedule text[][]" |
||||
print ")" |
||||
pgcnx.query("""CREATE TABLE sal_emp ( |
||||
name text, |
||||
pay_by_quarter int4[], |
||||
pay_by_extra_quarter int8[], |
||||
schedule text[][])""") |
||||
wait_key() |
||||
print |
||||
print "-- insert instances with array attributes. " |
||||
print " Note the use of braces" |
||||
print |
||||
print "INSERT INTO sal_emp VALUES (" |
||||
print " 'Bill'," |
||||
print " '{10000,10000,10000,10000}'," |
||||
print " '{9223372036854775800,9223372036854775800,9223372036854775800}'," |
||||
print " '{{\"meeting\", \"lunch\"}, {}}')" |
||||
print |
||||
print "INSERT INTO sal_emp VALUES (" |
||||
print " 'Carol'," |
||||
print " '{20000,25000,25000,25000}'," |
||||
print " '{9223372036854775807,9223372036854775807,9223372036854775807}'," |
||||
print " '{{\"talk\", \"consult\"}, {\"meeting\"}}')" |
||||
print |
||||
pgcnx.query("""INSERT INTO sal_emp VALUES ( |
||||
'Bill', '{10000,10000,10000,10000}', |
||||
'{9223372036854775800,9223372036854775800,9223372036854775800}', |
||||
'{{\"meeting\", \"lunch\"}, {}}')""") |
||||
pgcnx.query("""INSERT INTO sal_emp VALUES ( |
||||
'Carol', '{20000,25000,25000,25000}', |
||||
'{9223372036854775807,9223372036854775807,9223372036854775807}', |
||||
'{{\"talk\", \"consult\"}, {\"meeting\"}}')""") |
||||
wait_key() |
||||
print |
||||
print "----------------------" |
||||
print "-- queries on array attributes" |
||||
print "----------------------" |
||||
print |
||||
print "SELECT name FROM sal_emp WHERE" |
||||
print " sal_emp.pay_by_quarter[1] <> sal_emp.pay_by_quarter[2]" |
||||
print |
||||
print pgcnx.query("""SELECT name FROM sal_emp WHERE |
||||
sal_emp.pay_by_quarter[1] <> sal_emp.pay_by_quarter[2]""") |
||||
print |
||||
print pgcnx.query("""SELECT name FROM sal_emp WHERE |
||||
sal_emp.pay_by_extra_quarter[1] <> sal_emp.pay_by_extra_quarter[2]""") |
||||
print |
||||
print "-- retrieve third quarter pay of all employees" |
||||
print |
||||
print "SELECT sal_emp.pay_by_quarter[3] FROM sal_emp" |
||||
print |
||||
print pgcnx.query("SELECT sal_emp.pay_by_quarter[3] FROM sal_emp") |
||||
print |
||||
print "-- retrieve third quarter extra pay of all employees" |
||||
print |
||||
print "SELECT sal_emp.pay_by_extra_quarter[3] FROM sal_emp" |
||||
print pgcnx.query("SELECT sal_emp.pay_by_extra_quarter[3] FROM sal_emp") |
||||
print |
||||
print "-- retrieve first two quarters of extra quarter pay of all employees" |
||||
print |
||||
print "SELECT sal_emp.pay_by_extra_quarter[1:2] FROM sal_emp" |
||||
print |
||||
print pgcnx.query("SELECT sal_emp.pay_by_extra_quarter[1:2] FROM sal_emp") |
||||
print |
||||
print "-- select subarrays" |
||||
print |
||||
print "SELECT sal_emp.schedule[1:2][1:1] FROM sal_emp WHERE" |
||||
print " sal_emp.name = 'Bill'" |
||||
print pgcnx.query("SELECT sal_emp.schedule[1:2][1:1] FROM sal_emp WHERE " \ |
||||
"sal_emp.name = 'Bill'") |
||||
|
||||
# base cleanup |
||||
def demo_cleanup(pgcnx): |
||||
print "-- clean up (you must remove the children first)" |
||||
print "DROP TABLE sal_emp" |
||||
print "DROP TABLE capitals" |
||||
print "DROP TABLE cities;" |
||||
pgcnx.query("DROP TABLE sal_emp") |
||||
pgcnx.query("DROP TABLE capitals") |
||||
pgcnx.query("DROP TABLE cities") |
||||
|
||||
# main demo function |
||||
def demo(pgcnx): |
||||
inherit_demo(pgcnx) |
||||
array_demo(pgcnx) |
||||
demo_cleanup(pgcnx) |
@ -1,296 +0,0 @@ |
||||
#! /usr/bin/env python |
||||
# basics.py - basic SQL commands tutorial |
||||
# inspired from the Postgres95 tutorial |
||||
# adapted to Python 1995 by Pascal ANDRE |
||||
|
||||
print """ |
||||
__________________________________________________________________ |
||||
MODULE BASICS.PY : BASIC POSTGRES SQL COMMANDS TUTORIAL |
||||
|
||||
This module is designed for being imported from python prompt |
||||
|
||||
In order to run the samples included here, first create a connection |
||||
using : cnx = basics.DB(...) |
||||
|
||||
The "..." should be replaced with whatever arguments you need to open an |
||||
existing database. Usually all you need is the name of the database and, |
||||
in fact, if it is the same as your login name, you can leave it empty. |
||||
|
||||
then start the demo with: basics.demo(cnx) |
||||
__________________________________________________________________ |
||||
""" |
||||
|
||||
from pg import DB |
||||
import sys |
||||
|
||||
# waits for a key |
||||
def wait_key(): |
||||
print "Press <enter>" |
||||
sys.stdin.read(1) |
||||
|
||||
# table creation commands |
||||
def create_table(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating a table:" |
||||
print "-- a CREATE TABLE is used to create base tables. POSTGRES" |
||||
print "-- SQL has its own set of built-in types. (Note that" |
||||
print "-- keywords are case-insensitive but identifiers are " |
||||
print "-- case-sensitive.)" |
||||
print "-----------------------------" |
||||
print |
||||
print "Sending query :" |
||||
print "CREATE TABLE weather (" |
||||
print " city varchar(80)," |
||||
print " temp_lo int," |
||||
print " temp_hi int," |
||||
print " prcp float8," |
||||
print " date date" |
||||
print ")" |
||||
pgcnx.query("""CREATE TABLE weather (city varchar(80), temp_lo int, |
||||
temp_hi int, prcp float8, date date)""") |
||||
print |
||||
print "Sending query :" |
||||
print "CREATE TABLE cities (" |
||||
print " name varchar(80)," |
||||
print " location point" |
||||
print ")" |
||||
pgcnx.query("""CREATE TABLE cities ( |
||||
name varchar(80), |
||||
location point)""") |
||||
|
||||
# data insertion commands |
||||
def insert_data(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Inserting data:" |
||||
print "-- an INSERT statement is used to insert a new row into" |
||||
print "-- a table. There are several ways you can specify what" |
||||
print "-- columns the data should go to." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- 1. the simplest case is when the list of value correspond to" |
||||
print "-- the order of the columns specified in CREATE TABLE." |
||||
print |
||||
print "Sending query :" |
||||
print "INSERT INTO weather " |
||||
print " VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')" |
||||
pgcnx.query("""INSERT INTO weather |
||||
VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')""") |
||||
print |
||||
print "Sending query :" |
||||
print "INSERT INTO cities " |
||||
print " VALUES ('San Francisco', '(-194.0, 53.0)')" |
||||
pgcnx.query("""INSERT INTO cities |
||||
VALUES ('San Francisco', '(-194.0, 53.0)')""") |
||||
print |
||||
wait_key() |
||||
print "-- 2. you can also specify what column the values correspond " |
||||
print " to. (The columns can be specified in any order. You may " |
||||
print " also omit any number of columns. eg. unknown precipitation" |
||||
print " below)" |
||||
print "Sending query :" |
||||
print "INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)" |
||||
print " VALUES ('San Francisco', 43, 57, 0.0, '11/29/1994')" |
||||
pgcnx.query("INSERT INTO weather (date, city, temp_hi, temp_lo)" \ |
||||
"VALUES ('11/29/1994', 'Hayward', 54, 37)") |
||||
|
||||
# direct selection commands |
||||
def select_data1(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Retrieving data:" |
||||
print "-- a SELECT statement is used for retrieving data. The " |
||||
print "-- basic syntax is:" |
||||
print "-- SELECT columns FROM tables WHERE predicates" |
||||
print "-----------------------------" |
||||
print |
||||
print "-- a simple one would be the query:" |
||||
print "SELECT * FROM weather" |
||||
print |
||||
print "The result is :" |
||||
q = pgcnx.query("SELECT * FROM weather") |
||||
print q |
||||
print |
||||
print "-- you may also specify expressions in the target list (the " |
||||
print "-- 'AS column' specifies the column name of the result. It is " |
||||
print "-- optional.)" |
||||
print "The query :" |
||||
print " SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date " |
||||
print " FROM weather" |
||||
print "Gives :" |
||||
print pgcnx.query("""SELECT city, (temp_hi+temp_lo)/2 |
||||
AS temp_avg, date FROM weather""") |
||||
print |
||||
print "-- if you want to retrieve rows that satisfy certain condition" |
||||
print "-- (ie. a restriction), specify the condition in WHERE. The " |
||||
print "-- following retrieves the weather of San Francisco on rainy " |
||||
print "-- days." |
||||
print "SELECT *" |
||||
print "FROM weather" |
||||
print "WHERE city = 'San Francisco' " |
||||
print " and prcp > 0.0" |
||||
print pgcnx.query("""SELECT * FROM weather WHERE city = 'San Francisco' |
||||
AND prcp > 0.0""") |
||||
print |
||||
print "-- here is a more complicated one. Duplicates are removed when " |
||||
print "-- DISTINCT is specified. ORDER BY specifies the column to sort" |
||||
print "-- on. (Just to make sure the following won't confuse you, " |
||||
print "-- DISTINCT and ORDER BY can be used separately.)" |
||||
print "SELECT DISTINCT city" |
||||
print "FROM weather" |
||||
print "ORDER BY city;" |
||||
print pgcnx.query("SELECT DISTINCT city FROM weather ORDER BY city") |
||||
|
||||
# selection to a temporary table |
||||
def select_data2(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Retrieving data into other classes:" |
||||
print "-- a SELECT ... INTO statement can be used to retrieve " |
||||
print "-- data into another class." |
||||
print "-----------------------------" |
||||
print |
||||
print "The query :" |
||||
print "SELECT * INTO TABLE temptab " |
||||
print "FROM weather" |
||||
print "WHERE city = 'San Francisco' " |
||||
print " and prcp > 0.0" |
||||
pgcnx.query("""SELECT * INTO TABLE temptab FROM weather |
||||
WHERE city = 'San Francisco' and prcp > 0.0""") |
||||
print "Fills the table temptab, that can be listed with :" |
||||
print "SELECT * from temptab" |
||||
print pgcnx.query("SELECT * from temptab") |
||||
|
||||
# aggregate creation commands |
||||
def create_aggregate(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Aggregates" |
||||
print "-----------------------------" |
||||
print |
||||
print "Let's consider the query :" |
||||
print "SELECT max(temp_lo)" |
||||
print "FROM weather;" |
||||
print pgcnx.query("SELECT max(temp_lo) FROM weather") |
||||
print |
||||
print "-- Aggregate with GROUP BY" |
||||
print "SELECT city, max(temp_lo)" |
||||
print "FROM weather " |
||||
print "GROUP BY city;" |
||||
print pgcnx.query( """SELECT city, max(temp_lo) |
||||
FROM weather GROUP BY city""") |
||||
|
||||
# table join commands |
||||
def join_table(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Joining tables:" |
||||
print "-- queries can access multiple tables at once or access" |
||||
print "-- the same table in such a way that multiple instances" |
||||
print "-- of the table are being processed at the same time." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- suppose we want to find all the records that are in the " |
||||
print "-- temperature range of other records. W1 and W2 are aliases " |
||||
print "--for weather." |
||||
print |
||||
print "SELECT W1.city, W1.temp_lo, W1.temp_hi, " |
||||
print " W2.city, W2.temp_lo, W2.temp_hi" |
||||
print "FROM weather W1, weather W2" |
||||
print "WHERE W1.temp_lo < W2.temp_lo " |
||||
print " and W1.temp_hi > W2.temp_hi" |
||||
print |
||||
print pgcnx.query("""SELECT W1.city, W1.temp_lo, W1.temp_hi, |
||||
W2.city, W2.temp_lo, W2.temp_hi FROM weather W1, weather W2 |
||||
WHERE W1.temp_lo < W2.temp_lo and W1.temp_hi > W2.temp_hi""") |
||||
print |
||||
print "-- let's join two tables. The following joins the weather table" |
||||
print "-- and the cities table." |
||||
print |
||||
print "SELECT city, location, prcp, date" |
||||
print "FROM weather, cities" |
||||
print "WHERE name = city" |
||||
print |
||||
print pgcnx.query("""SELECT city, location, prcp, date FROM weather, cities |
||||
WHERE name = city""") |
||||
print |
||||
print "-- since the column names are all different, we don't have to " |
||||
print "-- specify the table name. If you want to be clear, you can do " |
||||
print "-- the following. They give identical results, of course." |
||||
print |
||||
print "SELECT w.city, c.location, w.prcp, w.date" |
||||
print "FROM weather w, cities c" |
||||
print "WHERE c.name = w.city;" |
||||
print |
||||
print pgcnx.query("""SELECT w.city, c.location, w.prcp, w.date |
||||
FROM weather w, cities c WHERE c.name = w.city""") |
||||
|
||||
# data updating commands |
||||
def update_data(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Updating data:" |
||||
print "-- an UPDATE statement is used for updating data. " |
||||
print "-----------------------------" |
||||
print |
||||
print "-- suppose you discover the temperature readings are all off by" |
||||
print "-- 2 degrees as of Nov 28, you may update the data as follow:" |
||||
print |
||||
print "UPDATE weather" |
||||
print " SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2" |
||||
print " WHERE date > '11/28/1994'" |
||||
print |
||||
pgcnx.query("""UPDATE weather |
||||
SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2 |
||||
WHERE date > '11/28/1994'""") |
||||
print |
||||
print "SELECT * from weather" |
||||
print pgcnx.query("SELECT * from weather") |
||||
|
||||
# data deletion commands |
||||
def delete_data(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Deleting data:" |
||||
print "-- a DELETE statement is used for deleting rows from a " |
||||
print "-- table." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- suppose you are no longer interested in the weather of " |
||||
print "-- Hayward, you can do the following to delete those rows from" |
||||
print "-- the table" |
||||
print |
||||
print "DELETE FROM weather WHERE city = 'Hayward'" |
||||
pgcnx.query("DELETE FROM weather WHERE city = 'Hayward'") |
||||
print |
||||
print "SELECT * from weather" |
||||
print |
||||
print pgcnx.query("SELECT * from weather") |
||||
print |
||||
print "-- you can also delete all the rows in a table by doing the " |
||||
print "-- following. (This is different from DROP TABLE which removes " |
||||
print "-- the table in addition to the removing the rows.)" |
||||
print |
||||
print "DELETE FROM weather" |
||||
pgcnx.query("DELETE FROM weather") |
||||
print |
||||
print "SELECT * from weather" |
||||
print pgcnx.query("SELECT * from weather") |
||||
|
||||
# table removal commands |
||||
def remove_table(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Removing the tables:" |
||||
print "-- DROP TABLE is used to remove tables. After you have" |
||||
print "-- done this, you can no longer use those tables." |
||||
print "-----------------------------" |
||||
print |
||||
print "DROP TABLE weather, cities, temptab" |
||||
pgcnx.query("DROP TABLE weather, cities, temptab") |
||||
|
||||
# main demo function |
||||
def demo(pgcnx): |
||||
create_table(pgcnx) |
||||
wait_key() |
||||
insert_data(pgcnx) |
||||
wait_key() |
||||
select_data1(pgcnx) |
||||
select_data2(pgcnx) |
||||
create_aggregate(pgcnx) |
||||
join_table(pgcnx) |
||||
update_data(pgcnx) |
||||
delete_data(pgcnx) |
||||
remove_table(pgcnx) |
@ -1,205 +0,0 @@ |
||||
# func.py - demonstrate the use of SQL functions |
||||
# inspired from the PostgreSQL tutorial |
||||
# adapted to Python 1995 by Pascal ANDRE |
||||
|
||||
print """ |
||||
__________________________________________________________________ |
||||
MODULE FUNC.PY : SQL FUNCTION DEFINITION TUTORIAL |
||||
|
||||
This module is designed for being imported from python prompt |
||||
|
||||
In order to run the samples included here, first create a connection |
||||
using : cnx = func.DB(...) |
||||
|
||||
The "..." should be replaced with whatever arguments you need to open an |
||||
existing database. Usually all you need is the name of the database and, |
||||
in fact, if it is the same as your login name, you can leave it empty. |
||||
|
||||
then start the demo with: func.demo(cnx) |
||||
__________________________________________________________________ |
||||
""" |
||||
|
||||
from pg import DB |
||||
import sys |
||||
|
||||
# waits for a key |
||||
def wait_key(): |
||||
print "Press <enter>" |
||||
sys.stdin.read(1) |
||||
|
||||
# basic functions declaration |
||||
def base_func(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating SQL Functions on Base Types" |
||||
print "-- a CREATE FUNCTION statement lets you create a new " |
||||
print "-- function that can be used in expressions (in SELECT, " |
||||
print "-- INSERT, etc.). We will start with functions that " |
||||
print "-- return values of base types." |
||||
print "-----------------------------" |
||||
print |
||||
print "--" |
||||
print "-- let's create a simple SQL function that takes no arguments" |
||||
print "-- and returns 1" |
||||
print |
||||
print "CREATE FUNCTION one() RETURNS int4" |
||||
print " AS 'SELECT 1 as ONE' LANGUAGE 'sql'" |
||||
pgcnx.query("""CREATE FUNCTION one() RETURNS int4 |
||||
AS 'SELECT 1 as ONE' LANGUAGE 'sql'""") |
||||
wait_key() |
||||
print |
||||
print "--" |
||||
print "-- functions can be used in any expressions (eg. in the target" |
||||
print "-- list or qualifications)" |
||||
print |
||||
print "SELECT one() AS answer" |
||||
print pgcnx.query("SELECT one() AS answer") |
||||
print |
||||
print "--" |
||||
print "-- here's how you create a function that takes arguments. The" |
||||
print "-- following function returns the sum of its two arguments:" |
||||
print |
||||
print "CREATE FUNCTION add_em(int4, int4) RETURNS int4" |
||||
print " AS 'SELECT $1 + $2' LANGUAGE 'sql'" |
||||
pgcnx.query("""CREATE FUNCTION add_em(int4, int4) RETURNS int4 |
||||
AS 'SELECT $1 + $2' LANGUAGE 'sql'""") |
||||
print |
||||
print "SELECT add_em(1, 2) AS answer" |
||||
print pgcnx.query("SELECT add_em(1, 2) AS answer") |
||||
|
||||
# functions on composite types |
||||
def comp_func(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating SQL Functions on Composite Types" |
||||
print "-- it is also possible to create functions that return" |
||||
print "-- values of composite types." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- before we create more sophisticated functions, let's " |
||||
print "-- populate an EMP table" |
||||
print |
||||
print "CREATE TABLE EMP (" |
||||
print " name text," |
||||
print " salary int4," |
||||
print " age int4," |
||||
print " dept varchar(16)" |
||||
print ")" |
||||
pgcnx.query("""CREATE TABLE EMP ( |
||||
name text, |
||||
salary int4, |
||||
age int4, |
||||
dept varchar(16))""") |
||||
print |
||||
print "INSERT INTO EMP VALUES ('Sam', 1200, 16, 'toy')" |
||||
print "INSERT INTO EMP VALUES ('Claire', 5000, 32, 'shoe')" |
||||
print "INSERT INTO EMP VALUES ('Andy', -1000, 2, 'candy')" |
||||
print "INSERT INTO EMP VALUES ('Bill', 4200, 36, 'shoe')" |
||||
print "INSERT INTO EMP VALUES ('Ginger', 4800, 30, 'candy')" |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Sam', 1200, 16, 'toy')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Claire', 5000, 32, 'shoe')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Andy', -1000, 2, 'candy')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Bill', 4200, 36, 'shoe')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Ginger', 4800, 30, 'candy')") |
||||
wait_key() |
||||
print |
||||
print "-- the argument of a function can also be a tuple. For " |
||||
print "-- instance, double_salary takes a tuple of the EMP table" |
||||
print |
||||
print "CREATE FUNCTION double_salary(EMP) RETURNS int4" |
||||
print " AS 'SELECT $1.salary * 2 AS salary' LANGUAGE 'sql'" |
||||
pgcnx.query("""CREATE FUNCTION double_salary(EMP) RETURNS int4 |
||||
AS 'SELECT $1.salary * 2 AS salary' LANGUAGE 'sql'""") |
||||
print |
||||
print "SELECT name, double_salary(EMP) AS dream" |
||||
print "FROM EMP" |
||||
print "WHERE EMP.dept = 'toy'" |
||||
print pgcnx.query("""SELECT name, double_salary(EMP) AS dream |
||||
FROM EMP WHERE EMP.dept = 'toy'""") |
||||
print |
||||
print "-- the return value of a function can also be a tuple. However," |
||||
print "-- make sure that the expressions in the target list is in the " |
||||
print "-- same order as the columns of EMP." |
||||
print |
||||
print "CREATE FUNCTION new_emp() RETURNS EMP" |
||||
print " AS 'SELECT \'None\'::text AS name," |
||||
print " 1000 AS salary," |
||||
print " 25 AS age," |
||||
print " \'none\'::varchar(16) AS dept'" |
||||
print " LANGUAGE 'sql'" |
||||
pgcnx.query("""CREATE FUNCTION new_emp() RETURNS EMP |
||||
AS 'SELECT \\\'None\\\'::text AS name, |
||||
1000 AS salary, |
||||
25 AS age, |
||||
\\\'none\\\'::varchar(16) AS dept' |
||||
LANGUAGE 'sql'""") |
||||
wait_key() |
||||
print |
||||
print "-- you can then project a column out of resulting the tuple by" |
||||
print "-- using the \"function notation\" for projection columns. " |
||||
print "-- (ie. bar(foo) is equivalent to foo.bar) Note that we don't" |
||||
print "-- support new_emp().name at this moment." |
||||
print |
||||
print "SELECT name(new_emp()) AS nobody" |
||||
print pgcnx.query("SELECT name(new_emp()) AS nobody") |
||||
print |
||||
print "-- let's try one more function that returns tuples" |
||||
print "CREATE FUNCTION high_pay() RETURNS setof EMP" |
||||
print " AS 'SELECT * FROM EMP where salary > 1500'" |
||||
print " LANGUAGE 'sql'" |
||||
pgcnx.query("""CREATE FUNCTION high_pay() RETURNS setof EMP |
||||
AS 'SELECT * FROM EMP where salary > 1500' |
||||
LANGUAGE 'sql'""") |
||||
print |
||||
print "SELECT name(high_pay()) AS overpaid" |
||||
print pgcnx.query("SELECT name(high_pay()) AS overpaid") |
||||
|
||||
# function with multiple SQL commands |
||||
def mult_func(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating SQL Functions with multiple SQL statements" |
||||
print "-- you can also create functions that do more than just a" |
||||
print "-- SELECT." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- you may have noticed that Andy has a negative salary. We'll" |
||||
print "-- create a function that removes employees with negative " |
||||
print "-- salaries." |
||||
print |
||||
print "SELECT * FROM EMP" |
||||
print pgcnx.query("SELECT * FROM EMP") |
||||
print |
||||
print "CREATE FUNCTION clean_EMP () RETURNS int4" |
||||
print " AS 'DELETE FROM EMP WHERE EMP.salary <= 0" |
||||
print " SELECT 1 AS ignore_this'" |
||||
print " LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION clean_EMP () RETURNS int4 AS 'DELETE FROM EMP WHERE EMP.salary <= 0; SELECT 1 AS ignore_this' LANGUAGE 'sql'") |
||||
print |
||||
print "SELECT clean_EMP()" |
||||
print pgcnx.query("SELECT clean_EMP()") |
||||
print |
||||
print "SELECT * FROM EMP" |
||||
print pgcnx.query("SELECT * FROM EMP") |
||||
|
||||
# base cleanup |
||||
def demo_cleanup(pgcnx): |
||||
print "-- remove functions that were created in this file" |
||||
print |
||||
print "DROP FUNCTION clean_EMP()" |
||||
print "DROP FUNCTION high_pay()" |
||||
print "DROP FUNCTION new_emp()" |
||||
print "DROP FUNCTION add_em(int4, int4)" |
||||
print "DROP FUNCTION one()" |
||||
print |
||||
print "DROP TABLE EMP CASCADE" |
||||
pgcnx.query("DROP FUNCTION clean_EMP()") |
||||
pgcnx.query("DROP FUNCTION high_pay()") |
||||
pgcnx.query("DROP FUNCTION new_emp()") |
||||
pgcnx.query("DROP FUNCTION add_em(int4, int4)") |
||||
pgcnx.query("DROP FUNCTION one()") |
||||
pgcnx.query("DROP TABLE EMP CASCADE") |
||||
|
||||
# main demo function |
||||
def demo(pgcnx): |
||||
base_func(pgcnx) |
||||
comp_func(pgcnx) |
||||
mult_func(pgcnx) |
||||
demo_cleanup(pgcnx) |
@ -1,149 +0,0 @@ |
||||
# syscat.py - parses some system catalogs |
||||
# inspired from the PostgreSQL tutorial |
||||
# adapted to Python 1995 by Pascal ANDRE |
||||
|
||||
print """ |
||||
__________________________________________________________________ |
||||
MODULE SYSCAT.PY : PARSES SOME POSTGRESQL SYSTEM CATALOGS |
||||
|
||||
This module is designed for being imported from python prompt |
||||
|
||||
In order to run the samples included here, first create a connection |
||||
using : cnx = syscat.DB(...) |
||||
|
||||
The "..." should be replaced with whatever arguments you need to open an |
||||
existing database. Usually all you need is the name of the database and, |
||||
in fact, if it is the same as your login name, you can leave it empty. |
||||
|
||||
then start the demo with: syscat.demo(cnx) |
||||
|
||||
Some results may be empty, depending on your base status." |
||||
|
||||
__________________________________________________________________ |
||||
""" |
||||
|
||||
from pg import DB |
||||
import sys |
||||
|
||||
# waits for a key |
||||
def wait_key(): |
||||
print "Press <enter>" |
||||
sys.stdin.read(1) |
||||
|
||||
# lists all simple indices |
||||
def list_simple_ind(pgcnx): |
||||
result = pgcnx.query("""SELECT bc.relname AS class_name, |
||||
ic.relname AS index_name, a.attname |
||||
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a |
||||
WHERE i.indrelid = bc.oid AND i.indexrelid = bc.oid |
||||
AND i.indkey[0] = a.attnum AND i.indnatts = 1 |
||||
AND a.attrelid = bc.oid AND a.attisdropped = 'f' |
||||
ORDER BY class_name, index_name, attname""") |
||||
return result |
||||
|
||||
# list all user defined attributes and their type in user-defined classes |
||||
def list_all_attr(pgcnx): |
||||
result = pgcnx.query("""SELECT c.relname, a.attname, t.typname |
||||
FROM pg_class c, pg_attribute a, pg_type t |
||||
WHERE c.relkind = 'r' and c.relname !~ '^pg_' |
||||
AND c.relname !~ '^Inv' and a.attnum > 0 |
||||
AND a.attrelid = c.oid and a.atttypid = t.oid |
||||
AND a.attisdropped = 'f' |
||||
ORDER BY relname, attname""") |
||||
return result |
||||
|
||||
# list all user defined base type |
||||
def list_user_base_type(pgcnx): |
||||
result = pgcnx.query("""SELECT u.usename, t.typname |
||||
FROM pg_type t, pg_user u |
||||
WHERE u.usesysid = int2in(int4out(t.typowner)) |
||||
AND t.typrelid = '0'::oid and t.typelem = '0'::oid |
||||
AND u.usename <> 'postgres' order by usename, typname""") |
||||
return result |
||||
|
||||
# list all right-unary operators |
||||
def list_right_unary_operator(pgcnx): |
||||
result = pgcnx.query("""SELECT o.oprname AS right_unary, |
||||
lt.typname AS operand, result.typname AS return_type |
||||
FROM pg_operator o, pg_type lt, pg_type result |
||||
WHERE o.oprkind='r' and o.oprleft = lt.oid |
||||
AND o.oprresult = result.oid |
||||
ORDER BY operand""") |
||||
return result |
||||
|
||||
# list all left-unary operators |
||||
def list_left_unary_operator(pgcnx): |
||||
result = pgcnx.query("""SELECT o.oprname AS left_unary, |
||||
rt.typname AS operand, result.typname AS return_type |
||||
FROM pg_operator o, pg_type rt, pg_type result |
||||
WHERE o.oprkind='l' AND o.oprright = rt.oid |
||||
AND o.oprresult = result.oid |
||||
ORDER BY operand""") |
||||
return result |
||||
|
||||
# list all binary operators |
||||
def list_binary_operator(pgcnx): |
||||
result = pgcnx.query("""SELECT o.oprname AS binary_op, |
||||
rt.typname AS right_opr, lt.typname AS left_opr, |
||||
result.typname AS return_type |
||||
FROM pg_operator o, pg_type rt, pg_type lt, pg_type result |
||||
WHERE o.oprkind = 'b' AND o.oprright = rt.oid |
||||
AND o.oprleft = lt.oid AND o.oprresult = result.oid""") |
||||
return result |
||||
|
||||
# returns the name, args and return type from all function of lang l |
||||
def list_lang_func(pgcnx, l): |
||||
result = pgcnx.query("""SELECT p.proname, p.pronargs, t.typname |
||||
FROM pg_proc p, pg_language l, pg_type t |
||||
WHERE p.prolang = l.oid AND p.prorettype = t.oid |
||||
AND l.lanname = '%s' |
||||
ORDER BY proname""" % l) |
||||
return result |
||||
|
||||
# lists all the aggregate functions and the type to which they can be applied |
||||
def list_agg_func(pgcnx): |
||||
result = pgcnx.query("""SELECT p.proname, t.typname |
||||
FROM pg_aggregate a, pg_proc p, pg_type t |
||||
WHERE a.aggfnoid = p.oid |
||||
and p.proargtypes[0] = t.oid |
||||
ORDER BY proname, typname""") |
||||
return result |
||||
|
||||
# lists all the operator classes that can be used with each access method as |
||||
# well as the operators that can be used with the respective operator classes |
||||
def list_op_class(pgcnx): |
||||
result = pgcnx.query("""SELECT am.amname, opc.opcname, opr.oprname |
||||
FROM pg_am am, pg_amop amop, pg_opclass opc, pg_operator opr |
||||
WHERE amop.amopid = am.oid and amop.amopclaid = opc.oid |
||||
AND amop.amopopr = opr.oid order by amname, opcname, oprname""") |
||||
return result |
||||
|
||||
# demo function - runs all examples |
||||
def demo(pgcnx): |
||||
import sys, os |
||||
save_stdout = sys.stdout |
||||
sys.stdout = os.popen("more", "w") |
||||
print "Listing simple indices ..." |
||||
print list_simple_ind(pgcnx) |
||||
print "Listing all attributes ..." |
||||
print list_all_attr(pgcnx) |
||||
print "Listing all user-defined base types ..." |
||||
print list_user_base_type(pgcnx) |
||||
print "Listing all left-unary operators defined ..." |
||||
print list_left_unary_operator(pgcnx) |
||||
print "Listing all right-unary operators defined ..." |
||||
print list_right_unary_operator(pgcnx) |
||||
print "Listing all binary operators ..." |
||||
print list_binary_operator(pgcnx) |
||||
print "Listing C external function linked ..." |
||||
print list_lang_func(pgcnx, 'C') |
||||
print "Listing C internal functions ..." |
||||
print list_lang_func(pgcnx, 'internal') |
||||
print "Listing SQL functions defined ..." |
||||
print list_lang_func(pgcnx, 'sql') |
||||
print "Listing 'aggregate functions' ..." |
||||
print list_agg_func(pgcnx) |
||||
print "Listing 'operator classes' ..." |
||||
print list_op_class(pgcnx) |
||||
del sys.stdout |
||||
sys.stdout = save_stdout |
Loading…
Reference in new issue