mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Update for PyGreSQL 3.0, from D'Arcy J.M. Cain
This commit is contained in:
2
doc/TODO
2
doc/TODO
@ -250,7 +250,7 @@ MISC
|
|||||||
* allow configuration of maximum number of open files
|
* allow configuration of maximum number of open files
|
||||||
* Remove pg_listener index
|
* Remove pg_listener index
|
||||||
* Remove ANALYZE from VACUUM so it can be run separately without locks
|
* Remove ANALYZE from VACUUM so it can be run separately without locks
|
||||||
* Gather more accurate statistics using indexes
|
* Gather more accurate disbursion statistics using indexes
|
||||||
* Improve statistics storage in pg_class [performance]
|
* Improve statistics storage in pg_class [performance]
|
||||||
* Improve VACUUM speed with indexes [vacuum]
|
* Improve VACUUM speed with indexes [vacuum]
|
||||||
* -BSD/OS does not support locale because there is no LC_MESSAGES (Bruce)
|
* -BSD/OS does not support locale because there is no LC_MESSAGES (Bruce)
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
|
|
||||||
Announce: Release of PyGreSQL version 2.4
|
Announce: Release of PyGreSQL version 3.0
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
PyGreSQL v2.4 has been released.
|
PyGreSQL v3.0 has been released.
|
||||||
It is available at: ftp://ftp.druid.net/pub/distrib/PyGreSQL.tgz. If
|
It is available at: ftp://ftp.druid.net/pub/distrib/PyGreSQL.tgz. If
|
||||||
you are on NetBSD, look in the packages directory under databases. If
|
you are running NetBSD, look in the packages directory under databases.
|
||||||
it isn't there yet, it should be there shortly. You can also pick up the
|
There is also a package in the FreeBSD ports collection.
|
||||||
package files from ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz.
|
|
||||||
There is also a package in the FreeBSD ports collection but as I write
|
|
||||||
this it is at version 2.1. I will try to get that updated as well.
|
|
||||||
|
|
||||||
PostgreSQL is a database system derived from Postgres4.2. It conforms
|
PostgreSQL is a database system derived from Postgres4.2. It conforms
|
||||||
to (most of) ANSI SQL and offers many interesting capabilities (C
|
to (most of) ANSI SQL and offers many interesting capabilities (C
|
||||||
@ -28,19 +25,49 @@ PyGreSQL is a python module that interfaces to a PostgreSQL database. It
|
|||||||
embeds the PostgreSQL query library to allow easy use of the powerful
|
embeds the PostgreSQL query library to allow easy use of the powerful
|
||||||
PostgreSQL features from a Python script.
|
PostgreSQL features from a Python script.
|
||||||
|
|
||||||
I wanted to have DB-SIG API support in the next release but there are
|
This release of PyGreSQL is the first DB-SIG API. That's why we have
|
||||||
enough fixes and improvements to make one more release before starting
|
a bump in the major number. There is also a potential problem in
|
||||||
on that. The next version will be 3.0 and have the DB-SIG API support.
|
backwards compatibility. Previously when there was a NULL in a returned
|
||||||
Note that I said this for 2.4 but some required changes from others have
|
field it was returned as a blank. Now it is more properly returned as
|
||||||
been slow in coming (I'm not complaining, people do have lives) and
|
a Python None. Any scripts that expect NULLs to be blanks will have
|
||||||
there were enough fixes that I didn't want to keep them from a release.
|
problems with this.
|
||||||
|
|
||||||
PyGreSQL 2.3 was developed and tested on a NetBSD 1.3_BETA system. It
|
Due to the fact that the DB-API is brand new, it is expected that there
|
||||||
|
will be a 3.1 release shortly with corrections once many people have
|
||||||
|
had a chance to test it.
|
||||||
|
|
||||||
|
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,
|
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
|
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
|
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
|
the code to use full ANSI style prototypes and changed the order of
|
||||||
arguments to connect. Later versions are fixes and enhancements to that.
|
arguments to connect. Later versions are fixes and enhancements to that.
|
||||||
|
The latest version of PyGreSQL works with Python 1.5.2 and PostgreSQL 6.5.
|
||||||
|
|
||||||
|
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:
|
Important changes from PyGreSQL 2.3 to PyGreSQL 2.4:
|
||||||
- Insert returns None if the user doesn't have select permissions
|
- Insert returns None if the user doesn't have select permissions
|
||||||
@ -48,10 +75,11 @@ Important changes from PyGreSQL 2.3 to PyGreSQL 2.4:
|
|||||||
not select permissions on a table.
|
not select permissions on a table.
|
||||||
- Added ntuples() method to query object (brit@druid.net)
|
- Added ntuples() method to query object (brit@druid.net)
|
||||||
- Corrected a bug related to getresult() and the money type
|
- Corrected a bug related to getresult() and the money type
|
||||||
- Corrected a but related to negative money amounts
|
- Corrected a bug related to negative money amounts
|
||||||
- Allow update based on primary key if munged oid not available and
|
- Allow update based on primary key if munged oid not available and
|
||||||
table has a primary key
|
table has a primary key
|
||||||
- Add many __doc__ strings. (andre@via.ecp.fr)
|
- 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:
|
Important changes from PyGreSQL 2.2 to PyGreSQL 2.3:
|
||||||
- connect.host returns "localhost" when connected to Unix socket
|
- connect.host returns "localhost" when connected to Unix socket
|
||||||
|
@ -5,16 +5,39 @@ 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)
|
Further copyright 1997, 1998 and 1999 by D'Arcy J.M. Cain (darcy@druid.net)
|
||||||
See file README for copyright information.
|
See file README for copyright information.
|
||||||
|
|
||||||
|
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
|
Version 2.4
|
||||||
- Insert returns None if the user doesn't have select permissions
|
- Insert returns None if the user doesn't have select permissions
|
||||||
on the table. It can (and does) happen that one has insert but
|
on the table. It can (and does) happen that one has insert but
|
||||||
not select permissions on a table.
|
not select permissions on a table.
|
||||||
- Added ntuples() method to query object (brit@druid.net)
|
- Added ntuples() method to query object (brit@druid.net)
|
||||||
- Corrected a bug related to getresult() and the money type
|
- Corrected a bug related to getresult() and the money type
|
||||||
- Corrected a but related to negative money amounts
|
- Corrected a bug related to negative money amounts
|
||||||
- Allow update based on primary key if munged oid not available and
|
- Allow update based on primary key if munged oid not available and
|
||||||
table has a primary key
|
table has a primary key
|
||||||
- Add many __doc__ strings. (andre@via.ecp.fr)
|
- Add many __doc__ strings. (andre@via.ecp.fr)
|
||||||
|
- Get method works with views if key specified
|
||||||
|
|
||||||
Version 2.3
|
Version 2.3
|
||||||
- connect.host returns "localhost" when connected to Unix socket
|
- connect.host returns "localhost" when connected to Unix socket
|
||||||
|
57
src/interfaces/python/PyGreSQL.spec
Normal file
57
src/interfaces/python/PyGreSQL.spec
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
%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,11 +1,11 @@
|
|||||||
|
|
||||||
PyGreSQL - v2.4: PostgreSQL module for Python
|
PyGreSQL - v2.5: PostgreSQL module for Python
|
||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
0. Copyright notice
|
0. Copyright notice
|
||||||
===================
|
===================
|
||||||
|
|
||||||
PyGreSQL, version 2.4
|
PyGreSQL, version 2.5
|
||||||
A Python interface for PostgreSQL database.
|
A Python interface for PostgreSQL database.
|
||||||
Written by D'Arcy J.M. Cain, darcy@druid.net<BR>
|
Written by D'Arcy J.M. Cain, darcy@druid.net<BR>
|
||||||
Based heavily on code written by Pascal Andre, andre@chimay.via.ecp.fr.
|
Based heavily on code written by Pascal Andre, andre@chimay.via.ecp.fr.
|
||||||
@ -57,7 +57,8 @@ 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.
|
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
|
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
|
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.
|
style prototypes and changed the order of arguments to connect. The latest
|
||||||
|
version of PyGreSQL works with PostgreSQL 6.5 and Python 1.5.2.
|
||||||
|
|
||||||
|
|
||||||
1.2. Distribution files
|
1.2. Distribution files
|
||||||
@ -78,25 +79,90 @@ style prototypes and changed the order of arguments to connect.
|
|||||||
1.3. Installation
|
1.3. Installation
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
* You first have to get and build Python and PostgreSQL.
|
* If you are on NetBSD, look in the packages directory under databases. If
|
||||||
|
it isn't there yet, it should be there shortly. You can also pick up the
|
||||||
|
package files from ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz.
|
||||||
|
There is also a package in the FreeBSD ports collection but as I write
|
||||||
|
this it is at version 2.1. I will try to get that updated as well.
|
||||||
|
|
||||||
|
* For Linux installation look at README.linux. If you're on an x86 system
|
||||||
|
that uses RPMs, then you can pick up an RPM at
|
||||||
|
ftp://ftp.druid.net/pub/distrib/pygresql.i386.rpm
|
||||||
|
|
||||||
|
* 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 two parts, a C module labeled _pg and a
|
* PyGreSQL is implemented as two parts, a C module labeled _pg and a
|
||||||
Python wrapper called pg.py. This changed between 2.1 and 2.2. This
|
Python wrapper called pg.py. This changed between 2.1 and 2.2. This
|
||||||
should not affect any existing programs but the installation is slightly
|
should not affect any existing programs but the installation is slightly
|
||||||
different.
|
different.
|
||||||
|
|
||||||
* Find the directory where your 'Setup' file lives (usually ??/Modules) and
|
* Download and unpack the PyGreSQL tarball if you haven't already done so.
|
||||||
copy or symlink the 'pgmodule.c' file there.
|
|
||||||
|
|
||||||
* Add the following line to your Setup file
|
STAND-ALONE
|
||||||
_pg pgmodule.c -I[pgInc] -L[pgLib] -lpq # -lcrypt # needed on some systems
|
|
||||||
|
* In the directory containing pgmodule.c, run the following command
|
||||||
|
cc -fpic -shared -o _pg.so -I[pyInc] -I[pgInc] -L[pgLib] -lpq # -lcrypt # needed on some systems
|
||||||
where:
|
where:
|
||||||
[pgInc] = path of the PostgreSQL include
|
[pyInc] = path of the Python include (usually Python.h)
|
||||||
[pgLib] = path of the PostgreSQL libraries
|
[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:
|
Some options may be added to this line:
|
||||||
-DNO_DEF_VAR - no default variables support
|
-DNO_DEF_VAR - no default variables support
|
||||||
-DNO_DIRECT - no direct access methods
|
-DNO_DIRECT - no direct access methods
|
||||||
-DNO_LARGE - no large object support
|
-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.
|
||||||
|
|
||||||
|
* 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
|
-DNO_PQSOCKET - if running an older PostgreSQL
|
||||||
|
|
||||||
Define NO_PQSOCKET if you are using a version of PostgreSQL before 6.4
|
Define NO_PQSOCKET if you are using a version of PostgreSQL before 6.4
|
||||||
@ -108,21 +174,14 @@ style prototypes and changed the order of arguments to connect.
|
|||||||
your shared modules with "make sharedinstall but this no longer seems
|
your shared modules with "make sharedinstall but this no longer seems
|
||||||
to be true."
|
to be true."
|
||||||
|
|
||||||
* Copy pg.py to the lib directory where the rest of your modules are. For
|
* 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.
|
example, that's /usr/local/lib/Python on my system.
|
||||||
|
|
||||||
* Do 'make -f Makefile.pre.in boot' and do 'make && make install'
|
* 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
|
* For more details read the documentation at the top of Makefile.pre.in
|
||||||
|
|
||||||
* If you are on NetBSD, look in the packages directory under databases. If
|
|
||||||
it isn't there yet, it should be there shortly. You can also pick up the
|
|
||||||
package files from ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz.
|
|
||||||
There is also a package in the FreeBSD ports collection but as I write
|
|
||||||
this it is at version 2.1. I will try to get that updated as well.
|
|
||||||
|
|
||||||
* For Linux installation look at README.linux
|
|
||||||
|
|
||||||
|
|
||||||
1.4. Where to get ... ?
|
1.4. Where to get ... ?
|
||||||
-----------------------
|
-----------------------
|
||||||
@ -133,9 +192,10 @@ The home sites of the different packages are:
|
|||||||
- PosgreSQL: http://www.PostgreSQL.org/
|
- PosgreSQL: http://www.PostgreSQL.org/
|
||||||
- PyGreSQL: http://www.druid.net/pygresql/
|
- PyGreSQL: http://www.druid.net/pygresql/
|
||||||
|
|
||||||
A Linux RPM can be picked up from ftp://www.eevolute.com/pub/python/.
|
A Linux RPM can be picked up from
|
||||||
A NetBSD package thould be in the distribution soon and is available
|
ftp://ftp.druid.net/pub/distrib/pygresql.i386.rpm. A NetBSD package thould
|
||||||
at ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz.
|
be in the distribution soon and is available at
|
||||||
|
ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz.
|
||||||
|
|
||||||
1.5. Information and support
|
1.5. Information and support
|
||||||
----------------------------
|
----------------------------
|
||||||
@ -394,7 +454,7 @@ methods are specified by the tag [LO].
|
|||||||
inserted row. If it is otherwise a query that does not return a result
|
inserted row. If it is otherwise a query that does not return a result
|
||||||
(ie. is not a some kind of SELECT statement), it returns None.
|
(ie. is not a some kind of SELECT statement), it returns None.
|
||||||
Otherwise, it returns a pgqueryobject that can be accessed via the
|
Otherwise, it returns a pgqueryobject that can be accessed via the
|
||||||
getresult method or printed.
|
getresult or dictresult method or simply printed.
|
||||||
|
|
||||||
pgqueryobject methods
|
pgqueryobject methods
|
||||||
---------------------
|
---------------------
|
||||||
@ -411,8 +471,8 @@ methods are specified by the tag [LO].
|
|||||||
pg.error - invalid previous result
|
pg.error - invalid previous result
|
||||||
Description:
|
Description:
|
||||||
This method returns the list of the values returned by the query.
|
This method returns the list of the values returned by the query.
|
||||||
More information about this result may be get using listfields,
|
More information about this result may be accessed using listfields,
|
||||||
fieldname and fiednum methods.
|
fieldname and fieldnum methods.
|
||||||
|
|
||||||
2.2.1.2. dictresult - like getresult but returns list of dictionaries
|
2.2.1.2. dictresult - like getresult but returns list of dictionaries
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
@ -839,8 +899,8 @@ has a class called DB. The above functions are also included in the
|
|||||||
name space so it isn't necessary to import both modules. The preferred
|
name space so it isn't necessary to import both modules. The preferred
|
||||||
way to use this module is as follows.
|
way to use this module is as follows.
|
||||||
|
|
||||||
from pg import DB
|
import pg
|
||||||
db = DB(...) # See description of the initialization method below.
|
db = pg.DB(...) # See description of the initialization method below.
|
||||||
|
|
||||||
The following describes the methods and variables of this class.
|
The following describes the methods and variables of this class.
|
||||||
|
|
||||||
@ -973,11 +1033,30 @@ The following describes the methods and variables of this class.
|
|||||||
as munged as described above.
|
as munged as described above.
|
||||||
|
|
||||||
|
|
||||||
4. Future directions
|
4. DB-API reference
|
||||||
====================
|
===================
|
||||||
|
|
||||||
|
This section needs to be written.
|
||||||
|
|
||||||
|
|
||||||
|
5. Todo
|
||||||
|
=======
|
||||||
|
|
||||||
The large object and direct access functions need much more attention.
|
The large object and direct access functions need much more attention.
|
||||||
|
|
||||||
I want to add a DB-SIG API wrapper around the underlying module. This
|
An update query should return the number of rows affected.
|
||||||
will be in 3.0.
|
|
||||||
|
The C module needs to be cleaned up and redundant code merged.
|
||||||
|
|
||||||
|
The DB-API module needs to be documented.
|
||||||
|
|
||||||
|
|
||||||
|
6. 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,5 +1,10 @@
|
|||||||
Thanks to thilo@eevolute.com for this README and the RPM
|
Thanks to thilo@eevolute.com for this README and the RPM
|
||||||
|
|
||||||
|
Note: The precompiled RPM package is not available at www.eevolute.com.
|
||||||
|
You may use the spec file provided with PyGreSQL to build your
|
||||||
|
own package.
|
||||||
|
Hartmut Goebel <hartmut@goebel.noris.de>
|
||||||
|
|
||||||
|
|
||||||
INSTALLING PyGreSQL on Redhat Linux 5.1 or 5.2
|
INSTALLING PyGreSQL on Redhat Linux 5.1 or 5.2
|
||||||
==============================================
|
==============================================
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#! /usr/local/bin/python
|
#! /usr/bin/env python
|
||||||
|
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
@ -10,13 +10,16 @@ import string, re, sys
|
|||||||
# utility function
|
# utility function
|
||||||
# We expect int, seq, decimal, text or date (more later)
|
# We expect int, seq, decimal, text or date (more later)
|
||||||
def _quote(d, t):
|
def _quote(d, t):
|
||||||
|
if d == None:
|
||||||
|
return "NULL"
|
||||||
|
|
||||||
if t in ['int', 'decimal', 'seq']:
|
if t in ['int', 'decimal', 'seq']:
|
||||||
if d == "": return 0
|
if d == "": return 0
|
||||||
return "%s" % d
|
return "%d" % int(d)
|
||||||
|
|
||||||
if t == 'money':
|
if t == 'money':
|
||||||
if d == "": return '0.00'
|
if d == "": return '0.00'
|
||||||
return "'%.2f'" % d
|
return "'%.2f'" % float(d)
|
||||||
|
|
||||||
if t == 'bool':
|
if t == 'bool':
|
||||||
if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', 1, '1', 'ON']:
|
if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', 1, '1', 'ON']:
|
||||||
@ -25,7 +28,8 @@ def _quote(d, t):
|
|||||||
return "'f'"
|
return "'f'"
|
||||||
|
|
||||||
if d == "": return "null"
|
if d == "": return "null"
|
||||||
return "'%s'" % string.strip(re.sub("'", "''", "%s" % d))
|
return "'%s'" % string.strip(re.sub("'", "''", \
|
||||||
|
re.sub("\\\\", "\\\\\\\\", "%s" %d)))
|
||||||
|
|
||||||
class DB:
|
class DB:
|
||||||
"""This class wraps the pg connection type"""
|
"""This class wraps the pg connection type"""
|
||||||
@ -42,8 +46,8 @@ class DB:
|
|||||||
if not hasattr(self,e) and hasattr(self.db,e):
|
if not hasattr(self,e) and hasattr(self.db,e):
|
||||||
exec 'self.%s = self.db.%s' % ( e, e )
|
exec 'self.%s = self.db.%s' % ( e, e )
|
||||||
|
|
||||||
self.attnames = {}
|
self.__attnames__ = {}
|
||||||
self.pkeys = {}
|
self.__pkeys__ = {}
|
||||||
self.debug = None # For debugging scripts, set to output format
|
self.debug = None # For debugging scripts, set to output format
|
||||||
# that takes a single string arg. For example
|
# that takes a single string arg. For example
|
||||||
# in a CGI set to "%s<BR>"
|
# in a CGI set to "%s<BR>"
|
||||||
@ -56,11 +60,17 @@ class DB:
|
|||||||
pg_class.oid = pg_index.indrelid AND
|
pg_class.oid = pg_index.indrelid AND
|
||||||
pg_index.indkey[0] = pg_attribute.attnum AND
|
pg_index.indkey[0] = pg_attribute.attnum AND
|
||||||
pg_index.indisprimary = 't'""").getresult():
|
pg_index.indisprimary = 't'""").getresult():
|
||||||
self.pkeys[rel] = att
|
self.__pkeys__[rel] = att
|
||||||
|
|
||||||
|
# wrap query for debugging
|
||||||
|
def query(self, qstr):
|
||||||
|
if self.debug != None:
|
||||||
|
print self.debug % qstr
|
||||||
|
return self.db.query(qstr)
|
||||||
|
|
||||||
def pkey(self, cl):
|
def pkey(self, cl):
|
||||||
# will raise an exception if primary key doesn't exist
|
# will raise an exception if primary key doesn't exist
|
||||||
return self.pkeys[cl]
|
return self.__pkeys__[cl]
|
||||||
|
|
||||||
def get_databases(self):
|
def get_databases(self):
|
||||||
l = []
|
l = []
|
||||||
@ -79,8 +89,8 @@ class DB:
|
|||||||
|
|
||||||
def get_attnames(self, cl):
|
def get_attnames(self, cl):
|
||||||
# May as well cache them
|
# May as well cache them
|
||||||
if self.attnames.has_key(cl):
|
if self.__attnames__.has_key(cl):
|
||||||
return self.attnames[cl]
|
return self.__attnames__[cl]
|
||||||
|
|
||||||
query = """SELECT pg_attribute.attname, pg_type.typname
|
query = """SELECT pg_attribute.attname, pg_type.typname
|
||||||
FROM pg_class, pg_attribute, pg_type
|
FROM pg_class, pg_attribute, pg_type
|
||||||
@ -114,13 +124,13 @@ class DB:
|
|||||||
else:
|
else:
|
||||||
l[attname] = 'text'
|
l[attname] = 'text'
|
||||||
|
|
||||||
self.attnames[cl] = l
|
self.__attnames__[cl] = l
|
||||||
return self.attnames[cl]
|
return self.__attnames__[cl]
|
||||||
|
|
||||||
# return a tuple from a database
|
# return a tuple from a database
|
||||||
def get(self, cl, arg, keyname = None):
|
def get(self, cl, arg, keyname = None, view = 0):
|
||||||
if keyname == None: # use the primary key by default
|
if keyname == None: # use the primary key by default
|
||||||
keyname = self.pkeys[cl]
|
keyname = self.__pkeys__[cl]
|
||||||
|
|
||||||
fnames = self.get_attnames(cl)
|
fnames = self.get_attnames(cl)
|
||||||
|
|
||||||
@ -136,6 +146,9 @@ class DB:
|
|||||||
# We want the oid for later updates if that isn't the key
|
# We want the oid for later updates if that isn't the key
|
||||||
if keyname == 'oid':
|
if keyname == 'oid':
|
||||||
q = "SELECT * FROM %s WHERE oid = %s" % (cl, k)
|
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:
|
else:
|
||||||
q = "SELECT oid AS oid_%s, %s FROM %s WHERE %s = %s" % \
|
q = "SELECT oid AS oid_%s, %s FROM %s WHERE %s = %s" % \
|
||||||
(cl, string.join(fnames.keys(), ','),\
|
(cl, string.join(fnames.keys(), ','),\
|
||||||
@ -155,6 +168,7 @@ class DB:
|
|||||||
return arg
|
return arg
|
||||||
|
|
||||||
# Inserts a new tuple into a table
|
# Inserts a new tuple into a table
|
||||||
|
# We currently don't support insert into views although PostgreSQL does
|
||||||
def insert(self, cl, a):
|
def insert(self, cl, a):
|
||||||
fnames = self.get_attnames(cl)
|
fnames = self.get_attnames(cl)
|
||||||
l = []
|
l = []
|
||||||
@ -183,7 +197,7 @@ class DB:
|
|||||||
# otherwise use the primary key. Fail if neither.
|
# otherwise use the primary key. Fail if neither.
|
||||||
def update(self, cl, a):
|
def update(self, cl, a):
|
||||||
foid = 'oid_%s' % cl
|
foid = 'oid_%s' % cl
|
||||||
pk = self.pkeys[cl]
|
pk = self.__pkeys__[cl]
|
||||||
if a.has_key(foid):
|
if a.has_key(foid):
|
||||||
where = "oid = %s" % a[foid]
|
where = "oid = %s" % a[foid]
|
||||||
elif a.has_key(pk):
|
elif a.has_key(pk):
|
||||||
@ -228,8 +242,6 @@ class DB:
|
|||||||
for ff in fnames.keys():
|
for ff in fnames.keys():
|
||||||
if fnames[ff] in ['int', 'decimal', 'seq', 'money']:
|
if fnames[ff] in ['int', 'decimal', 'seq', 'money']:
|
||||||
a[ff] = 0
|
a[ff] = 0
|
||||||
elif fnames[ff] == 'date':
|
|
||||||
a[ff] = 'TODAY'
|
|
||||||
else:
|
else:
|
||||||
a[ff] = ""
|
a[ff] = ""
|
||||||
|
|
||||||
|
401
src/interfaces/python/pgdb.py
Normal file
401
src/interfaces/python/pgdb.py
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
""" pgdb - DB-SIG compliant module for PygreSQL.
|
||||||
|
|
||||||
|
(c) 1999, Pascal Andre <andre@via.ecp.fr>.
|
||||||
|
See package documentation for further information on copyright.
|
||||||
|
|
||||||
|
Even though this file is distributed with a release version of
|
||||||
|
PyGreSQL, this is beta software. 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 DateTime
|
||||||
|
import time
|
||||||
|
|
||||||
|
### 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 == 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, typprtlen, 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],
|
||||||
|
string.atoi(res[1]), string.atoi(res[2]),
|
||||||
|
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 = 5
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.__source.close()
|
||||||
|
self.description = None
|
||||||
|
self.rowcount = -1
|
||||||
|
|
||||||
|
def execute(self, operation, params = None):
|
||||||
|
if type(params) == types.TupleType or type(params) == types.ListType:
|
||||||
|
self.executemany(operation, params)
|
||||||
|
else:
|
||||||
|
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 = 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
|
||||||
|
res = self.__source.fetch(size)
|
||||||
|
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 setinputsizes(self, sizes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setoutputsize(self, size, col = 0):
|
||||||
|
pass
|
||||||
|
|
||||||
|
### 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 = params[1]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# empty host is localhost
|
||||||
|
if dbhost == "":
|
||||||
|
dbhost = None
|
||||||
|
if dbuser == "":
|
||||||
|
dbuser = None
|
||||||
|
|
||||||
|
# open the connection
|
||||||
|
cnx = _pg.connect(host = dbhost, dbname = dbbase, port = dbport,
|
||||||
|
opt = dbopt, tty = dbtty,
|
||||||
|
user = dbuser, passwd = 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', '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'
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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,46 +0,0 @@
|
|||||||
# pgsqldb.py
|
|
||||||
# Written by D'Arcy J.M. Cain
|
|
||||||
|
|
||||||
# This library implements the DB-SIG API
|
|
||||||
# It includes the pg module and builds on it
|
|
||||||
|
|
||||||
from _pg import *
|
|
||||||
|
|
||||||
import string
|
|
||||||
|
|
||||||
class _cursor:
|
|
||||||
"""For cursor object"""
|
|
||||||
|
|
||||||
def __init__(self, conn):
|
|
||||||
self.conn = conn
|
|
||||||
self.cursor = None
|
|
||||||
self.arraysize = 1
|
|
||||||
self.description = None
|
|
||||||
self.name = string.split(`self`)[3][:-1]
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
if self.conn == None: raise self.conn.error, "Cursor has been closed"
|
|
||||||
if self.cursor == None: raise self.conn.error, "No cursor created"
|
|
||||||
self.conn.query('CLOSE %s' % self.name)
|
|
||||||
self.conn = None
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if self.cursor != None and self.conn != None:
|
|
||||||
self.conn.query('CLOSE %s' % self.name)
|
|
||||||
|
|
||||||
|
|
||||||
class pgsqldb:
|
|
||||||
"""This class wraps the pg connection type in a DB-SIG API interface"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kw):
|
|
||||||
self.db = apply(connect, args, kw)
|
|
||||||
|
|
||||||
# Create convience methods, in a way that is still overridable.
|
|
||||||
for e in ('query', 'reset', 'close', 'getnotify', 'inserttable',
|
|
||||||
'putline', 'getline', 'endcopy',
|
|
||||||
'host', 'port', 'db', 'options',
|
|
||||||
'tty', 'error', 'status', 'user',
|
|
||||||
'locreate', 'getlo', 'loimport'):
|
|
||||||
if not hasattr(self,e) and hasattr(self.db,e):
|
|
||||||
exec 'self.%s = self.db.%s' % ( e, e )
|
|
||||||
|
|
43
src/interfaces/python/setup.py
Executable file
43
src/interfaces/python/setup.py
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
include_dirs=['/usr/include/pgsql']
|
||||||
|
library_dirs=['usr/lib/pgsql']
|
||||||
|
optional_libs=['pq']
|
||||||
|
|
||||||
|
# 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>
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
setup (name = "PyGreSQL",
|
||||||
|
version = "3.0",
|
||||||
|
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 = [ ('_pgmodule', {
|
||||||
|
'sources': ['pgmodule.c'],
|
||||||
|
'include_dirs': include_dirs,
|
||||||
|
'library_dirs': library_dirs,
|
||||||
|
'libraries': optional_libs
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
|
@ -1,171 +0,0 @@
|
|||||||
#! /usr/local/bin/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 "__________________________________________________________________"
|
|
||||||
print "MODULE ADVANCED.PY : ADVANCED POSTGRES SQL COMMANDS TUTORIAL"
|
|
||||||
print
|
|
||||||
print "This module is designed for being imported from python prompt"
|
|
||||||
print
|
|
||||||
print "In order to run the samples included here, first create a connection"
|
|
||||||
print "using : cnx = advanced.DB(...)"
|
|
||||||
print "then start the demo with: advanced.demo(cnx)"
|
|
||||||
print "__________________________________________________________________"
|
|
||||||
|
|
||||||
from pgtools import *
|
|
||||||
from pg import DB
|
|
||||||
|
|
||||||
# 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 " schedule text[][]"
|
|
||||||
print ")"
|
|
||||||
pgcnx.query("CREATE TABLE sal_emp (" \
|
|
||||||
"name text," \
|
|
||||||
"pay_by_quarter int4[]," \
|
|
||||||
"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 " '{{\"meeting\", \"lunch\"}, {}}')"
|
|
||||||
print
|
|
||||||
print "INSERT INTO sal_emp VALUES ("
|
|
||||||
print " 'Carol',"
|
|
||||||
print " '{20000,25000,25000,25000}',"
|
|
||||||
print " '{{\"talk\", \"consult\"}, {\"meeting\"}}')"
|
|
||||||
print
|
|
||||||
pgcnx.query("INSERT INTO sal_emp VALUES (" \
|
|
||||||
"'Bill', '{10000,10000,10000,10000}'," \
|
|
||||||
"'{{\"meeting\", \"lunch\"}, {}}')")
|
|
||||||
pgcnx.query("INSERT INTO sal_emp VALUES (" \
|
|
||||||
"'Carol', '{20000,25000,25000,25000}'," \
|
|
||||||
"'{{\"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 "-- 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 "-- 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,284 +0,0 @@
|
|||||||
#! /usr/local/bin/python
|
|
||||||
# basics.py - basic SQL commands tutorial
|
|
||||||
# inspired from the Postgres95 tutorial
|
|
||||||
# adapted to Python 1995 by Pascal ANDRE
|
|
||||||
|
|
||||||
print "__________________________________________________________________"
|
|
||||||
print "MODULE BASICS.PY : BASIC SQL COMMANDS TUTORIAL"
|
|
||||||
print
|
|
||||||
print "This module is designed for being imported from python prompt"
|
|
||||||
print
|
|
||||||
print "In order to run the samples included here, first create a connection"
|
|
||||||
print "using : cnx = basics.DB(...)"
|
|
||||||
print "then start the demo with: basics.demo(cnx)"
|
|
||||||
print "__________________________________________________________________"
|
|
||||||
|
|
||||||
from pg import DB
|
|
||||||
from pgtools import *
|
|
||||||
|
|
||||||
# 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 temp "
|
|
||||||
print "FROM weather"
|
|
||||||
print "WHERE city = 'San Francisco' "
|
|
||||||
print " and prcp > 0.0"
|
|
||||||
pgcnx.query("SELECT * INTO TABLE temp FROM weather " \
|
|
||||||
"WHERE city = 'San Francisco' and prcp > 0.0")
|
|
||||||
print "Fills the table temp, that can be listed with :"
|
|
||||||
print "SELECT * from temp"
|
|
||||||
print pgcnx.query("SELECT * from temp")
|
|
||||||
|
|
||||||
# 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, temp"
|
|
||||||
pgcnx.query("DROP TABLE weather, cities, temp")
|
|
||||||
|
|
||||||
# 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,193 +0,0 @@
|
|||||||
# func.py - demonstrate the use of SQL functions
|
|
||||||
# inspired from the PostgreSQL tutorial
|
|
||||||
# adapted to Python 1995 by Pascal ANDRE
|
|
||||||
|
|
||||||
print "__________________________________________________________________"
|
|
||||||
print "MODULE FUNC.PY : SQL FUNCTION DEFINITION TUTORIAL"
|
|
||||||
print
|
|
||||||
print "This module is designed for being imported from python prompt"
|
|
||||||
print
|
|
||||||
print "In order to run the samples included here, first create a connection"
|
|
||||||
print "using : cnx = func.DB(...)"
|
|
||||||
print "then start the demo with: func.demo(cnx)"
|
|
||||||
print "__________________________________________________________________"
|
|
||||||
|
|
||||||
from pgtools import *
|
|
||||||
from pg import DB
|
|
||||||
|
|
||||||
# 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"
|
|
||||||
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")
|
|
||||||
|
|
||||||
# main demo function
|
|
||||||
def demo(pgcnx):
|
|
||||||
base_func(pgcnx)
|
|
||||||
comp_func(pgcnx)
|
|
||||||
mult_func(pgcnx)
|
|
||||||
demo_cleanup(pgcnx)
|
|
@ -1,48 +0,0 @@
|
|||||||
#! /usr/local/bin/python
|
|
||||||
# pgtools.py - valuable functions for PostGreSQL tutorial
|
|
||||||
# written 1995 by Pascal ANDRE
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# number of rows
|
|
||||||
scr_size = 24
|
|
||||||
|
|
||||||
# waits for a key
|
|
||||||
def wait_key():
|
|
||||||
print "Press <enter>"
|
|
||||||
sys.stdin.read(1)
|
|
||||||
|
|
||||||
# displays a table for a select query result
|
|
||||||
def display(fields, result):
|
|
||||||
print result
|
|
||||||
# gets cols width
|
|
||||||
fmt = []
|
|
||||||
sep = '+'
|
|
||||||
head = '|'
|
|
||||||
for i in range(0, len(fields)):
|
|
||||||
max = len(fields[i])
|
|
||||||
for j in range(0, len(result)):
|
|
||||||
if i < len(result[j]):
|
|
||||||
if len(result[j][i]) > max:
|
|
||||||
max = len(result[j][i])
|
|
||||||
fmt.append(" %%%ds |" % max)
|
|
||||||
for j in range(0, max):
|
|
||||||
sep = sep + '-'
|
|
||||||
sep = sep + '--+'
|
|
||||||
for i in range(0, len(fields)):
|
|
||||||
head = head + fmt[i] % fields[i]
|
|
||||||
print sep + '\n' + head + '\n' + sep
|
|
||||||
pos = 6
|
|
||||||
for i in range(0, len(result)):
|
|
||||||
str = '|'
|
|
||||||
for j in range(0, len(result[i])):
|
|
||||||
str = str + fmt[j] % result[i][j]
|
|
||||||
print str
|
|
||||||
pos = pos + 1
|
|
||||||
if pos == scr_size:
|
|
||||||
print sep
|
|
||||||
wait_key()
|
|
||||||
print sep + '\n' + head + '\n' + sep
|
|
||||||
pos = 6
|
|
||||||
print sep
|
|
||||||
wait_key()
|
|
@ -1,133 +0,0 @@
|
|||||||
# syscat.py - parses some system catalogs
|
|
||||||
# inspired from the PostgreSQL tutorial
|
|
||||||
# adapted to Python 1995 by Pascal ANDRE
|
|
||||||
|
|
||||||
print "____________________________________________________________________"
|
|
||||||
print
|
|
||||||
print "MODULE SYSCAT.PY : PARSES SOME POSTGRESQL SYSTEM CATALOGS"
|
|
||||||
print
|
|
||||||
print "This module is designed for being imported from python prompt"
|
|
||||||
print
|
|
||||||
print "In order to run the samples included here, first create a connection"
|
|
||||||
print "using : cnx = syscat.DB(...)"
|
|
||||||
print "then start the demo with: syscat.demo(cnx)"
|
|
||||||
print
|
|
||||||
print "Some results may be empty, depending on your base status."
|
|
||||||
print
|
|
||||||
print "____________________________________________________________________"
|
|
||||||
print
|
|
||||||
|
|
||||||
from pg import DB
|
|
||||||
from pgtools import *
|
|
||||||
|
|
||||||
# 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 a.attrelid = bc.oid " \
|
|
||||||
" and i.indproc = '0'::oid " \
|
|
||||||
"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 " \
|
|
||||||
"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 a.aggname, t.typname " \
|
|
||||||
"from pg_aggregate a, pg_type t " \
|
|
||||||
"where a.aggbasetype = t.oid order by aggname, 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
|
|
Reference in New Issue
Block a user