mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Update for PyGreSQL 3.0, from D'Arcy J.M. Cain
This commit is contained in:
		
							parent
							
								
									0bd84442f5
								
							
						
					
					
						commit
						f36e7ff092
					
				
							
								
								
									
										2
									
								
								doc/TODO
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								doc/TODO
									
									
									
									
									
								
							| @ -250,7 +250,7 @@ MISC | ||||
| * allow configuration of maximum number of open files | ||||
| * Remove pg_listener index | ||||
| * 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 VACUUM speed with indexes [vacuum] | ||||
| * -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 | ||||
| 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. | ||||
| you are running NetBSD, look in the packages directory under databases. | ||||
| There is also a package in the FreeBSD ports collection.               | ||||
| 
 | ||||
| PostgreSQL is a database system derived from Postgres4.2. It conforms | ||||
| 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 | ||||
| PostgreSQL features from a Python script. | ||||
| 
 | ||||
| I wanted to have DB-SIG API support in the next release but there are | ||||
| enough fixes and improvements to make one more release before starting | ||||
| on that.  The next version will be 3.0 and have the DB-SIG API support. | ||||
| Note that I said this for 2.4 but some required changes from others have | ||||
| been slow in coming (I'm not complaining, people do have lives) and | ||||
| there were enough fixes that I didn't want to keep them from a release. | ||||
| This release of PyGreSQL is the first DB-SIG API.  That's why we have | ||||
| a bump in the major number.  There is also a potential problem in | ||||
| backwards compatibility.  Previously when there was a NULL in a returned | ||||
| field it was returned as a blank.  Now it is more properly returned as | ||||
| a Python None.  Any scripts that expect NULLs to be blanks will have | ||||
| 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, | ||||
| 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 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: | ||||
|   - 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. | ||||
|   - Added ntuples() method to query object (brit@druid.net) | ||||
|   - 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 | ||||
|     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 | ||||
|  | ||||
| @ -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) | ||||
| 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 | ||||
|   - 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 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 | ||||
|     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  | ||||
|  | ||||
							
								
								
									
										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 | ||||
| =================== | ||||
| 
 | ||||
|   PyGreSQL, version 2.4 | ||||
|   PyGreSQL, version 2.5 | ||||
|   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. | ||||
| @ -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. | ||||
| 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. | ||||
| 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 | ||||
| @ -78,25 +79,90 @@ style prototypes and changed the order of arguments to connect. | ||||
| 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 | ||||
|   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 | ||||
|   different. | ||||
| 
 | ||||
| * Find the directory where your 'Setup' file lives (usually ??/Modules) and | ||||
|   copy or symlink the 'pgmodule.c' file there. | ||||
| * Download and unpack the PyGreSQL tarball if you haven't already done so. | ||||
| 
 | ||||
| * Add the following line to your Setup file | ||||
|     _pg  pgmodule.c -I[pgInc] -L[pgLib] -lpq # -lcrypt # needed on some systems | ||||
| 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 # -lcrypt # needed on some systems | ||||
|   where: | ||||
|     [pgInc] = path of the PostgreSQL include  | ||||
|     [pgLib] = path of the PostgreSQL libraries  | ||||
|     [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 | ||||
| 
 | ||||
|   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 | ||||
| @ -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 | ||||
|   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. | ||||
| 
 | ||||
| * 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 | ||||
| 
 | ||||
| * 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 ... ? | ||||
| ----------------------- | ||||
| @ -133,9 +192,10 @@ The home sites of the different packages are: | ||||
|   - PosgreSQL:  http://www.PostgreSQL.org/ | ||||
|   - PyGreSQL:   http://www.druid.net/pygresql/ | ||||
| 
 | ||||
| A Linux RPM can be picked up from ftp://www.eevolute.com/pub/python/. | ||||
| A NetBSD package thould be in the distribution soon and is available | ||||
| at ftp://ftp.druid.net/pub/distrib/pygresql.pkg.tgz. | ||||
| 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. | ||||
| 
 | ||||
| 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 | ||||
|     (ie. is not a some kind of SELECT statement), it returns None. | ||||
|     Otherwise, it returns a pgqueryobject that can be accessed via the | ||||
|     getresult method or printed. | ||||
|     getresult or dictresult method or simply printed. | ||||
| 
 | ||||
|   pgqueryobject methods | ||||
|   --------------------- | ||||
| @ -411,8 +471,8 @@ methods are specified by the tag [LO]. | ||||
|       pg.error      - invalid previous result | ||||
|     Description: | ||||
|       This method returns the list of the values returned by the query. | ||||
|       More information about this result may be get using listfields, | ||||
|       fieldname and fiednum methods. | ||||
|       More information about this result may be accessed using listfields, | ||||
|       fieldname and fieldnum methods. | ||||
| 
 | ||||
|     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 | ||||
| way to use this module is as follows. | ||||
| 
 | ||||
| from pg import DB | ||||
| db = DB(...) # See description of the initialization method below. | ||||
| import pg | ||||
| db = pg.DB(...) # See description of the initialization method below. | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
| I want to add a DB-SIG API wrapper around the underlying module.  This | ||||
| will be in 3.0. | ||||
| 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. | ||||
| 
 | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| 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 | ||||
| ============================================== | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| #! /usr/local/bin/python | ||||
| #! /usr/bin/env python | ||||
| 
 | ||||
| import string | ||||
| 
 | ||||
|  | ||||
| @ -10,13 +10,16 @@ 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', 'decimal', 'seq']: | ||||
| 		if d == "": return 0 | ||||
| 		return "%s" % d | ||||
| 		return "%d" % int(d) | ||||
| 
 | ||||
| 	if t == 'money': | ||||
| 		if d == "": return '0.00' | ||||
| 		return "'%.2f'" % d | ||||
| 		return "'%.2f'" % float(d) | ||||
| 
 | ||||
| 	if t == 'bool': | ||||
| 		if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', 1, '1', 'ON']: | ||||
| @ -25,7 +28,8 @@ def _quote(d, t): | ||||
| 			return "'f'" | ||||
| 
 | ||||
| 	if d == "": return "null" | ||||
| 	return "'%s'" % string.strip(re.sub("'", "''", "%s" % d)) | ||||
| 	return "'%s'" % string.strip(re.sub("'", "''", \ | ||||
| 							 re.sub("\\\\", "\\\\\\\\", "%s" %d))) | ||||
| 
 | ||||
| class DB: | ||||
| 	"""This class wraps the pg connection type""" | ||||
| @ -42,8 +46,8 @@ class DB: | ||||
| 			if not hasattr(self,e) and hasattr(self.db,e): | ||||
| 				exec 'self.%s = self.db.%s' % ( e, e ) | ||||
| 
 | ||||
| 		self.attnames = {} | ||||
| 		self.pkeys = {} | ||||
| 		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>" | ||||
| @ -56,11 +60,17 @@ class DB: | ||||
| 							pg_class.oid = pg_index.indrelid AND | ||||
| 							pg_index.indkey[0] = pg_attribute.attnum AND  | ||||
| 							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): | ||||
| 		# will raise an exception if primary key doesn't exist | ||||
| 		return self.pkeys[cl] | ||||
| 		return self.__pkeys__[cl] | ||||
| 
 | ||||
| 	def get_databases(self): | ||||
| 		l = [] | ||||
| @ -79,8 +89,8 @@ class DB: | ||||
| 
 | ||||
| 	def get_attnames(self, cl): | ||||
| 		# May as well cache them | ||||
| 		if self.attnames.has_key(cl): | ||||
| 			return self.attnames[cl] | ||||
| 		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 | ||||
| @ -114,13 +124,13 @@ class DB: | ||||
| 			else: | ||||
| 				l[attname] = 'text' | ||||
| 
 | ||||
| 		self.attnames[cl] = l | ||||
| 		return self.attnames[cl] | ||||
| 		self.__attnames__[cl] = l | ||||
| 		return self.__attnames__[cl] | ||||
| 
 | ||||
| 	# 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 | ||||
| 			keyname = self.pkeys[cl] | ||||
| 			keyname = self.__pkeys__[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 | ||||
| 		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" % \ | ||||
| 				(cl, string.join(fnames.keys(), ','),\ | ||||
| @ -155,6 +168,7 @@ class DB: | ||||
| 		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 = [] | ||||
| @ -183,7 +197,7 @@ class DB: | ||||
| 	# otherwise use the primary key.  Fail if neither. | ||||
| 	def update(self, cl, a): | ||||
| 		foid = 'oid_%s' % cl | ||||
| 		pk = self.pkeys[cl] | ||||
| 		pk = self.__pkeys__[cl] | ||||
| 		if a.has_key(foid): | ||||
| 			where = "oid = %s" % a[foid] | ||||
| 		elif a.has_key(pk): | ||||
| @ -228,8 +242,6 @@ class DB: | ||||
| 		for ff in fnames.keys(): | ||||
| 			if fnames[ff] in ['int', 'decimal', 'seq', 'money']: | ||||
| 				a[ff] = 0 | ||||
| 			elif fnames[ff] == 'date': | ||||
| 				a[ff] = 'TODAY' | ||||
| 			else: | ||||
| 				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 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user