Skip to content
Snippets Groups Projects
Commit 9848d365 authored by Marc G. Fournier's avatar Marc G. Fournier
Browse files

Support Docs & Contrib

parent 1960a3b9
Branches
Tags
No related merge requests found
Showing
with 1832 additions and 0 deletions
POSTGRES95 Data Base Management System
Copyright (c) 1994-6 Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this
paragraph and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
HISTORY 0 → 100644
Postgres95 1.02 Thu Aug 1 18:00:00 EDT 1996
-------------------------------------------------------------
Source code maintainenance and development
* worldwide team of volunteers
* the source tree now in CVS at ftp.ki.net
* developers mailing list - pg95-dev@ki.net
Enhancements
* psql (and underlying libpq library) now has many more options for
formatting output, including HTML
* pg_dump now output the schema and/or the data, with many fixes to
enhance completeness.
* psql used in place of monitor in administration shell scripts.
monitor to be depreciated in next release.
* date/time functions enhanced
* NULL insert/update/comparison fixed/enhanced
* TCL/TK lib and shell fixed to work with both tck7.4/tk4.0 and tcl7.5/tk4.1
Bug Fixes (almost too numerous to mention)
* indexes
* storage management
* check for NULL pointer before dereferencing
* Makefile fixes
New Ports
* added SolarisX86 port
* added BSDI 2.1 port
* added DGUX port
Contributors (appologies to any missed)
* Kurt J. Lidl <lidl@va.pubnix.com>
(missed in first run, but no less important)
* Erich Stamberger <eberger@gewi.kfunigraz.ac.at>
* Jason Wright <jason@shiloh.vnet.net>
* Cees de Groot <C.deGroot@inter.NL.net>
* ernst.molitor@uni-bonn.de
* michael.siebenborn@ae3.Hypo.DE (Michael Siebenborn (6929))
* Brian E. Gallew <geek+@cmu.edu>
* Vadim B. Mikheev <vadim@sable.krasnoyarsk.su>
* Adam Sussman <myddryn@vidya.com>
* Chris Dunlop <chris@onthe.net.au>
* Marc G. Fournier <scrappy@ki.net>
* Dan McGuirk <mcguirk@indirect.com>
* Dr_George_D_Detlefsen <drgeorge@ilt.com>
* Erich Stamberger <eberger@gewi.kfunigraz.ac.at>
* Massimo Dal Zotto <dz@cs.unitn.it>
* Randy Kunkee <kunkee@Starbase.NeoSoft.COM>
* Rick Weldon <rick@wisetech.com>
* Thomas van Reimersdahl <reimersd@dali.techinfo.rwth-aachen.de>
* david bennett <dave@bensoft.com>
* ernst.molitor@uni-bonn.de
* Julian Assange <proff@suburbia.net>
* Bruce Momjian <maillist@candle.pha.pa.us>
* Paul "Shag" Walmsley <ccshag@cclabs.missouri.edu>
* "Alistair G. Crooks" <azcb0@sde.uts.amdahl.com>
Postgres95 1.01 Fri Feb 23 18:20:36 PST 1996
-------------------------------------------------------------
Incompatibilities:
* 1.01 is backwards compatible with 1.0 database provided the user
follow the steps outlined in the MIGRATION_from_1.0_to_1.01 file.
If those steps are not taken, 1.01 is not compatible with 1.0 database.
Enhancements:
* added PQdisplayTuples() to libpq and changed monitor and psql to use it
* added NeXT port (requires SysVIPC implementation)
* added CAST .. AS ... syntax
* added ASC and DESC keywords
* added 'internal' as a possible language for CREATE FUNCTION
internal functions are C functions which have been statically linked
into the postgres backend.
* a new type "name" has been added for system identifiers (table names,
attribute names, etc.) This replaces the old char16 type. The
of name is set by the NAMEDATALEN #define in src/Makefile.global
* a readable reference manual that describes the query language.
* added host-based access control. A configuration file ($PGDATA/pg_hba)
is used to hold the configuration data. If host-based access control
is not desired, comment out HBA=1 in src/Makefile.global.
* changed regex handling to be uniform use of Henry Spencer's regex code
regardless of platform. The regex code is included in the distribution
* added functions and operators for case-insensitive regular expressions.
The operators are ~* and !~*.
* pg_dump uses COPY instead of SELECT loop for better performance
Bug fixes:
* fixed an optimizer bug that was causing core dumps when
functions calls were used in comparisons in the WHERE clause
* changed all uses of getuid to geteuid so that effective uids are used
* psql now returns non-zero status on errors when using -c
* applied public patches 1-14
Postgres95 1.0 Tue Sep 5 11:24:11 PDT 1995
-------------------------------------------------------------
Copyright change:
* The copyright of Postgres 1.0 has been loosened to be freely modifiable
and modifiable for any purpose. Please read the COPYRIGHT file.
Thanks to Professor Michael Stonebraker for making this possible.
Incompatibilities:
* date formats have to be MM-DD-YYYY (or DD-MM-YYYY if you're using
EUROPEAN STYLE). This follows SQL-92 specs.
* "delimiters" is now a keyword
Enhancements:
* sql LIKE syntax has been added
* copy command now takes an optional USING DELIMITER specification.
delimiters can be any single-character string.
* IRIX 5.3 port has been added.
Thanks to Paul Walmsley (ccshag@everest.cclabs.missouri.edu) and others.
* updated pg_dump to work with new libpq
* \d has been added psql
Thanks to Keith Parks (emkxp01@mtcc.demon.co.uk)
* regexp performance for architectures that use POSIX regex has been
improved due to caching of precompiled patterns.
Thanks to Alistair Crooks (agc@uts.amdahl.com)
* a new version of libpq++
Thanks to William Wanders (wwanders@sci.kun.nl)
Bug fixes:
* arbitrary userids can be specified in the createuser script
* \c to connect to other databases in psql now works.
* bad pg_proc entry for float4inc() is fixed
* users with usecreatedb field set can now create databases without
having to be usesuper
* remove access control entries when the entry no longer has any
permissions
* fixed non-portable datetimes implementation
* added kerberos flags to the src/backend/Makefile
* libpq now works with kerberos
* typographic errors in the user manual have been corrected.
* btrees with multiple index never worked, now we tell you they don't
work when you try to use them
Postgres95 Beta 0.03 Fri Jul 21 14:49:31 PDT 1995
------------------------------------------------------
Incompatible changes:
* BETA-0.3 IS INCOMPATIBLE WITH DATABASES CREATED WITH PREVIOUS VERSIONS
(due to system catalog changes and indexing structure changes).
* double-quote (") is deprecated as a quoting character for string literals;
you need to convert them to single quotes (').
* name of aggregates (eg. int4sum) are renamed in accordance with the
SQL standard (eg. sum).
* CHANGE ACL syntax is replaced by GRANT/REVOKE syntax.
* float literals (eg. 3.14) are now of type float4 (instead of float8 in
previous releases); you might have to do typecasting if you depend on it
being of type float8. If you neglect to do the typecasting and you assign
a float literal to a field of type float8, you may get incorrect values
stored!
* LIBPQ has been totally revamped so that frontend applications
can connect to multiple backends
* the usesysid field in pg_user has been changed from int2 to int4 to
allow wider range of Unix user ids.
* the netbsd/freebsd/bsd o/s ports have been consolidated into a
single BSD44_derived port. (thanks to Alistair Crooks)
SQL standard-compliance (the following details changes that makes postgres95
more compliant to the SQL-92 standard):
* the following SQL types are now built-in: smallint, int(eger), float, real,
char(N), varchar(N), date and time.
The following are aliases to existing postgres types:
smallint -> int2
integer, int -> int4
float, real -> float4
char(N) and varchar(N) are implemented as truncated text types. In
addition, char(N) does blank-padding.
* single-quote (') is used for quoting string literals; '' (in addition to
\') is supported as means of inserting a single quote in a string
* SQL standard aggregate names (MAX, MIN, AVG, SUM, COUNT) are used
(Also, aggregates can now be overloaded, i.e. you can define your
own MAX aggregate to take in a user-defined type.)
* CHANGE ACL removed. GRANT/REVOKE syntax added.
- Privileges can be given to a group using the "GROUP" keyword.
For example:
GRANT SELECT ON foobar TO GROUP my_group;
The keyword 'PUBLIC' is also supported to mean all users.
Privileges can only be granted or revoked to one user or group
at a time.
"WITH GRANT OPTION" is not supported. Only class owners can change
access control
- The default access control is to to grant users readonly access.
You must explicitly grant insert/update access to users. To change
this, modify the line in
src/backend/utils/acl.h
that defines ACL_WORLD_DEFAULT
Bug fixes:
* the bug where aggregates of empty tables were not run has been fixed. Now,
aggregates run on empty tables will return the initial conditions of the
aggregates. Thus, COUNT of an empty table will now properly return 0.
MAX/MIN of an empty table will return a tuple of value NULL.
* allow the use of \; inside the monitor
* the LISTEN/NOTIFY asynchronous notification mechanism now work
* NOTIFY in rule action bodies now work
* hash indices work, and access methods in general should perform better.
creation of large btree indices should be much faster. (thanks to Paul
Aoki)
Other changes and enhancements:
* addition of an EXPLAIN statement used for explaining the query execution
plan (eg. "EXPLAIN SELECT * FROM EMP" prints out the execution plan for
the query).
* WARN and NOTICE messages no longer have timestamps on them. To turn on
timestamps of error messages, uncomment the line in
src/backend/utils/elog.h:
/* define ELOG_TIMESTAMPS */
* On an access control violation, the message
"Either no such class or insufficient privilege"
will be given. This is the same message that is returned when
a class is not found. This dissuades non-privileged users from
guessing the existence of privileged classes.
* some additional system catalog changes have been made that are not
visible to the user.
libpgtcl changes:
* The -oid option has been added to the "pg_result" tcl command.
pg_result -oid returns oid of the last tuple inserted. If the
last command was not an INSERT, then pg_result -oid returns "".
* the large object interface is available as pg_lo* tcl commands:
pg_lo_open, pg_lo_close, pg_lo_creat, etc.
Portability enhancements and New Ports:
* flex/lex problems have been cleared up. Now, you should be able to use
flex instead of lex on any platforms. We no longer make assumptions of
what lexer you use based on the platform you use.
* The Linux-ELF port is now supported. Various configuration have been
tested: The following configuration is known to work:
kernel 1.2.10, gcc 2.6.3, libc 4.7.2, flex 2.5.2, bison 1.24
with everything in ELF format,
New utilities:
* ipcclean added to the distribution
ipcclean usually does not need to be run, but if your backend crashes
and leaves shared memory segments hanging around, ipcclean will
clean them up for you.
New documentation:
* the user manual has been revised and libpq documentation added.
Postgres95 Beta 0.02 (Thu May 25 16:54:46 PDT 1995)
------------------------------------------------------
Incompatible changes:
* The SQL statement for creating a database is 'CREATE DATABASE' instead
of 'CREATEDB'. Similarly, dropping a database is 'DROP DATABASE' instead
of 'DESTROYDB'. However, the names of the executables 'createdb' and
'destroydb' remain the same.
New tools:
* pgperl - a Perl (4.036) interface to Postgres95
* pg_dump - a utility for dumping out a postgres database into a
script file containing query commands. The script files are in a ASCII
format and can be used to reconstruct the database, even on other
machines and other architectures. (Also good for converting
a Postgres 4.2 database to Postgres95 database.)
The following ports have been incorporated into postgres95-beta-0.02:
* the NetBSD port by Alistair Crooks
* the AIX port by Mike Tung
* the Windows NT port by Jon Forrest (more stuff but not done yet)
* the Linux ELF port by Brian Gallew
The following bugs have been fixed in postgres95-beta-0.02:
* new lines not escaped in COPY OUT and problem with COPY OUT when first
attribute is a '.'
* cannot type return to use the default user id in createuser
* SELECT DISTINCT on big tables crashes
* Linux installation problems
* monitor doesn't allow use of 'localhost' as PGHOST
* psql core dumps when doing \c or \l
* the "pgtclsh" target missing from src/bin/pgtclsh/Makefile
* libpgtcl has a hard-wired default port number
* SELECT DISTINCT INTO TABLE hangs
* CREATE TYPE doesn't accept 'variable' as the internallength
* wrong result using more than 1 aggregate in a SELECT
Postgres95 Beta 0.01 (Mon May 1 19:03:10 PDT 1995)
------------------------------------------------------
Initial release.
INSTALL 0 → 100644
POSTGRES95 INSTALLATION INSTRUCTIONS
Copyright (c) 1996 Regents of the University of California
This directory contains the source and documentation for Postgres95
(version 1.02) Postgres95 is a derivative of POSTGRES 4.2 (the last
release of the UC Berkeley research project). For copyright terms
for postgres95, please see the file named COPYRIGHT. This version
was developed by a team of developers on the postgres developers
mailing list. Version 1.01 was developed by Jolly Chen and Andrew Yu.
Postgres95 has been tested on the following platforms:
alpha - DEC Alpha AXP on OSF/1 2.0
hpux - HP PA-RISC on HP-UX 9.0
i386_solaris - i386 Solaris
sparc_solaris - SUN SPARC on Solaris 2.4
sparc - SUN SPARC on SunOS 4.1.3
ultrix4 - DEC MIPS on Ultrix 4.4
linux - Intel x86 on Linux 1.2 and Linux ELF
BSD44_derived - OSs derived from 4.4-lite BSD (NetBSD, FreeBSD)
bsdi - BSD/OS 2.0 and 2.01
bsdi_2_1 - BSD/OS 2.1
aix - IBM on AIX 3.2.5
irix5 - SGI MIPS on IRIX 5.3
dgux - DG/UX 5.4R3.10
Some hooks are provided for
svr4 - Intel x86 on Intel SVR4
next - Motorola MC68K or Intel x86 on NeXTSTEP 3.2
but these are guaranteed not to work as of yet.
Postgres95 is also known to work on a number of other platforms that
the authors have not personally tested.
You should have at least 8 MB of memory and at least 30 MB of disk space to
hold the source, binaries, and user databases.
If you would like to migrate your databases from postgres 1.0 to
postgres 1.02, see the directory called MIGRATION_1.0_TO_1.02. People
upgrading from version 1.01 do not have to make any database changes.
----------------------------------------------------------------------
To install Postgres95 on UNIX platforms:
1. Create the postgres login.
Create a login called postgres (this requires root privileges). We
recommend that you run the postmaster as the user postgres for security
reasons.
If you run the postmaster as yourself, be warned that you essentially
grant all database users the ability to execute arbitrary C functions
as you without your password. (In any case, DO NOT run the postmaster
as root.)
2. Compile and install Postgres95.
If you have earlier versions of Postgres installed, you might want
to install Postgres95 in a different place.
If you're installing Postgres95 on Ultrix 4.x or Linux, see the
porting notes at the end for additional packages that you need to install
before installing Postgres95.
Our Makefiles require GNU make (called gmake in this document) and
also assume that "install" accepts BSD options. The INSTALL
variable in the Makefiles is set to the BSD-compatible version of
install. On some systems, you will have to find a BSD-compatible
install to the location of this program. (eg. bsdinst, which comes
with the MIT X Window System distribution)
Customization can be done by editing src/Makefile.global. You may change
the various configuration options here, such as where the Postgres95
executable files are installed and where postgres looks for the database
directory. The configuration switches are fairly self-explanatory, but we
will go over some of the more commonly-changed options:
- PORTNAME specifies the platform on which Postgres95 is being build
(linux is the default). You might need to change it to reflect your
platform. (sparc for SunOS 4.1.x, sparc_solaris for Solaris 2.4,
ultrix4 for Ultrix 4.4, and hpux for HP-UX 9.0)
- SRCDIR specifies where the source files are located. (defaults
to $(POSTGRESDIR)/src.)
- POSTSGRESDIR specifies the top-level directory where Postgres95
binaries, header files, libraries, and databases are installed.
- POSTGRESLOGIN specifies the user who will be doing initdb and
running the postmaster (defaults to postgres). Do not set
this to root, or any users with UID = 0!
- NAMEDATALEN and OIDNAMELEN allows you to set the maximum
length of system identifiers (table names, function names, etc.)
It defaults to 32. You may alter this if you like, but
be aware that databases created with different NAMEDATALEN's
do not interoperate.
- USE_READLINE specifies whether you want to use the GNU
readline and history libraries for the psql interactive
frontend program.
GNU readline is not supplied with postgres95 and can be found
in the usual ftp sites for GNU software.
- HBA specifies whether you wish to use host-based
authentication for postgres95. If you do use host-based
authentication, after installing, modify the file
$PGDATA/pg_hba accordingly.
After editing src/Makefile.global, you are ready to compile and
install Postgres95 (it takes about 10 minutes on a 133Mhz Pentium
running linux):
% cd src
% gmake
% gmake install
The first gmake ultimately issues the message "All of Postgres95 is
successfully made. Ready to install." If you don't get that, the make
failed, and there should be error messages at the end detailing why.
After the installation is complete, check that you have the following files
in the top level Postgres95 directory (eg. /usr/local/postgres95).
You will find the following executables in the bin directory (which
should be included in the search path of your shell):
% ls /usr/local/postgres95/bin
cleardbdir* destroydb* pg_dump* postgres*
createdb* destroyuser* pg_id* postmaster@
createuser* initdb* pg_version* psql*
You will find the following in the database directory:
% ls -R /usr/local/postgres95/data
files/
pg_hba
data/files:
global1.bki local1_template1.bki
global1.bki.source local1_template1.bki.source
3. Initialize the database.
After you have installed Postgres95, initialize the database by typing:
% initdb
4. Start the postmaster.
Now, you are ready to make the system operational by running the
postmaster daemon. There are a few environment variables which affect
its operation:
PGDATA - location of the database (eg. /usr/local/postgres95/data)
PGPORT - TCP port where it listens for connection (eg. 5432)
You don't have to set these variables if you use the (compile time)
default.
% postmaster -S
5. Testing.
We suggest you run the regression tests to make sure the release
was installed successfully. The regression tests can be found in
src/test/regress. (see src/test/regress/README for more details)
% cd /usr/local/postgres95/src/test/regress
% gmake all runtest
This will run a whole slew of regression tests and might take a long
time to run. When it's done, the output is in the file obj/regress.out.
You can compare this to a sample run that we supply in the file
sample.regress.out. (You should get roughly the same output except
for some pathnames.)
% diff obj/regress.out sample.regress.out
The regression test takes about half an hour to run on a Sparc 10.
You may want to use 'grep -v' to remove unsignificant differences.
6. Run queries.
After the database is initialized, you can create a new database. To
create a database, do the following:
% createdb foo
To connect to the postmaster, you have a choice of two front-end programs.
("psql" is recommended. "monitor" is the old terminal monitor
supplied in earlier versions of Postgres)
% psql foo
Please read the file COPYRIGHT for copyright terms of POSTGRES95
type \? for help on slash commands
type \q to quit
type \g or terminate with semicolon to execute query
You are currently connected to the database: foo
foo=>
----------------------------------------------------------------------
Questions? Bugs? Feedback?
First, please read the Frequently Asked Questions and answers
in the file called FAQ.
If you still have questions, please send them to
postgres95@postgres95.vnet.net.
If you have a bug report to make, please send a filled out version of
the file named "bug.template" to pg95-dev@ki.net.
If you would like to help out with the development and maintenance of
postgres95, send subscribe to the developers mailing list. See
README.support for more information
----------------------------------------------------------------------
Porting Notes:
-------------
Ultrix4.x:
You need to install the libdl-1.1 package since Ultrix 4.x doesn't
have a dynamic loader. It's available in
s2k-ftp.CS.Berkeley.EDU:pub/personal/andrew/libdl-1.1.tar.Z
Linux:
The linux port defaults to the ELF binary format. (Note that if you're
using ELF, you don't need dld because you'll be using the dl library
that comes with Linux ELF instead.)
To compile on non-ELF Linux, comment out the LINUX_ELF line in
src/mk/port/postgres.mk.linux. Also, the dld library MUST be obtained
and installed on the system. It enables dynamic link loading capability
to the postgres port. The dld library can be obtained from the sunsite
linux distributions. The current name is dld-3.2.5.
(Jalon Q. Zimmerman
<sneaker@powergrid.electriciti.com> 5/11/95)
To compile with flex, you need a recent version (2.5.2 or
later). Otherwise, you will get a 'yy_flush_buffer' undefined error.
BSD/OS:
For BSD/OS 2.0 and 2.01, you will need to get flex version 2.5.2
as well as the GNU dld library. Flex version 2.5.3 has a known bug.
NeXT:
The NeXT port was supplied by Tom R. Hageman <tom@basil.icce.rug.nl>.
It requires a SysV IPC emulation library and header files for
shared libary and semaphore stuff. Tom just happens to sell such
a product so contact him for information. He has also indicated that
binary releases of postgres95 for NEXTSTEP will be made available to
the general public. Contact Info@RnA.nl for information.
#!/bin/sh
trap "rm -f /tmp/$$" 0 1 2 3 15
rm -f ./tags
find `pwd`/ -type f -name '*.[chyl]' -print|xargs ctags -t -a -f tags
sort tags >/tmp/$$ && mv /tmp/$$ tags
find . -type d -print |while read DIR
do
[ "$DIR" != "." ] && ln -f -s `pwd`/tags $DIR/tags
done
From scrappy@ki.net Wed Aug 14 20:41:08 1996
Status: RO
X-Status:
Received: from candle.pha.pa.us (maillist@s1-03.ppp.op.net [206.84.209.132]) by quagmire.ki.net (8.7.5/8.7.5) with ESMTP id UAA01234 for <scrappy@ki.net>; Wed, 14 Aug 1996 20:41:00 -0400 (EDT)
Received: (from maillist@localhost) by candle.pha.pa.us (8.7.4/8.7.3) id UAA13966 for scrappy@ki.net; Wed, 14 Aug 1996 20:40:48 -0400 (EDT)
From: Bruce Momjian <maillist@candle.pha.pa.us>
Message-Id: <199608150040.UAA13966@candle.pha.pa.us>
Subject: New migration file
To: scrappy@ki.net (Marc G. Fournier)
Date: Wed, 14 Aug 1996 20:40:47 -0400 (EDT)
X-Mailer: ELM [version 2.4 PL25]
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Here is a new migratoin file for 1.02.1. It includes the 'copy' change
and a script to convert old ascii files.
---------------------------------------------------------------------------
The following notes are for the benefit of users who want to migrate
databases from postgres95 1.01 and 1.02 to postgres95 1.02.1.
If you are starting afresh with postgres95 1.02.1 and do not need
to migrate old databases, you do not need to read any further.
----------------------------------------------------------------------
In order to upgrade older postgres95 version 1.01 or 1.02 databases to
version 1.02.1, the following steps are required:
1) start up a new 1.02.1 postmaster
2) Add the new built-in functions and operators of 1.02.1 to 1.01 or 1.02
databases. This is done by running the new 1.02.1 server against
your own 1.01 or 1.02 database and applying the queries attached at
the end of thie file. This can be done easily through psql. If your
1.01 or 1.02 database is named "testdb" and you have cut the commands
from the end of this file and saved them in addfunc.sql:
% psql testdb -f addfunc.sql
Those upgrading 1.02 databases will get a warning when executing the
last two statements because they are already present in 1.02. This is
not a cause for concern.
* * *
If you are trying to reload a pg_dump or text-mode 'copy tablename to
stdout' generated with a previous version, you will need to run the
attached sed script on the ASCII file before loading it into the
database. The old format used '.' as end-of-data, while '\.' is now the
end-of-data marker. Also, empty strings are now loaded in as '' rather
than NULL. See the copy manual page for full details.
sed 's/^\.$/\\./g' <in_file >out_file
If you are loading an older binary copy or non-stdout copy, there is no
end-of-data character, and hence no conversion necessary.
---------------------------------------------------------------------------
-- following lines added by agc to reflect the case-insensitive
-- regexp searching for varchar (in 1.02), and bpchar (in 1.02.1)
create operator ~* (leftarg = bpchar, rightarg = text, procedure = texticregexeq);
create operator !~* (leftarg = bpchar, rightarg = text, procedure = texticregexne);
create operator ~* (leftarg = varchar, rightarg = text, procedure = texticregexeq);
create operator !~* (leftarg = varchar, rightarg = text, procedure = texticregexne);
README 0 → 100644
POSTGRES95 Data Base Management System
This directory contains the 1.02 release of Postgres95. See INSTALL for
the installation notes and HISTORY for the changes.
We also have a WWW home page located at:
http://www.ki.net/postgres95
Postgres95 is not public domain software. It is copyrighted by the
University of California but may be used according to the licensing
terms of the the copyright below:
------------------------------------------------------------------------
POSTGRES95 Data Base Management System
Copyright (c) 1994-6 Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this
paragraph and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
/*
* array_iterator.c --
*
* This file defines a new group of operators which take an
* array and a scalar value, iterate a scalar operator over the
* elements of the array and the value and compute a result as
* the logical OR or AND of the results.
* For example array_int4eq returns true if some of the elements
* of an array of int4 is equal to the given value:
*
* array_int4eq({1,2,3}, 1) --> true
* array_int4eq({1,2,3}, 4) --> false
*
* If we have defined T array types and O scalar operators
* we can define T x O array operators, each of them has a name
* like "array_<basetype><operation>" and takes an array of type T
* iterating the operator O over all the elements. Note however
* that some of the possible combination are invalid, for example
* the array_int4_like because there is no like operator for int4.
* It is now possible to write queries which look inside the arrays:
*
* create table t(id int4[], txt text[]);
* select * from t where t.id *= 123;
* select * from t where t.txt *~ '[a-z]';
* select * from t where t.txt[1:3] **~ '[a-z]';
*
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it>
*/
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include "postgres.h"
#include "pg_type.h"
#include "miscadmin.h"
#include "syscache.h"
#include "access/xact.h"
#include "utils/builtins.h"
#include "utils/elog.h"
static int32
array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
{
HeapTuple typ_tuple;
TypeTupleForm typ_struct;
bool typbyval;
int typlen;
func_ptr proc_fn;
int pronargs;
int nitems, i, result;
int ndim, *dim;
char *p;
/* Sanity checks */
if ((array == (ArrayType *) NULL)
|| (ARR_IS_LO(array) == true)) {
/* elog(NOTICE, "array_iterator: array is null"); */
return (0);
}
ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
nitems = getNitems(ndim, dim);
if (nitems == 0) {
/* elog(NOTICE, "array_iterator: nitems = 0"); */
return (0);
}
/* Lookup element type information */
typ_tuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(elemtype),0,0,0);
if (!HeapTupleIsValid(typ_tuple)) {
elog(WARN,"array_iterator: cache lookup failed for type %d", elemtype);
return 0;
}
typ_struct = (TypeTupleForm) GETSTRUCT(typ_tuple);
typlen = typ_struct->typlen;
typbyval = typ_struct->typbyval;
/* Lookup the function entry point */
proc_fn == (func_ptr) NULL;
fmgr_info(proc, &proc_fn, &pronargs);
if ((proc_fn == NULL) || (pronargs != 2)) {
elog(WARN, "array_iterator: fmgr_info lookup failed for oid %d", proc);
return (0);
}
/* Scan the array and apply the operator to each element */
result = 0;
p = ARR_DATA_PTR(array);
for (i = 0; i < nitems; i++) {
if (typbyval) {
switch(typlen) {
case 1:
result = (int) (*proc_fn)(*p, value);
break;
case 2:
result = (int) (*proc_fn)(* (int16 *) p, value);
break;
case 3:
case 4:
result = (int) (*proc_fn)(* (int32 *) p, value);
break;
}
p += typlen;
} else {
result = (int) (*proc_fn)(p, value);
if (typlen > 0) {
p += typlen;
} else {
p += INTALIGN(* (int32 *) p);
}
}
if (result) {
if (!and) {
return (1);
}
} else {
if (and) {
return (0);
}
}
}
if (and && result) {
return (1);
} else {
return (0);
}
}
/*
* Iterators for type _text
*/
int32
array_texteq(ArrayType *array, char* value)
{
return array_iterator((Oid) 25, /* text */
(Oid) 67, /* texteq */
0, /* logical or */
array, (Datum)value);
}
int32
array_all_texteq(ArrayType *array, char* value)
{
return array_iterator((Oid) 25, /* text */
(Oid) 67, /* texteq */
1, /* logical and */
array, (Datum)value);
}
int32
array_textregexeq(ArrayType *array, char* value)
{
return array_iterator((Oid) 25, /* text */
(Oid) 81, /* textregexeq */
0, /* logical or */
array, (Datum)value);
}
int32
array_all_textregexeq(ArrayType *array, char* value)
{
return array_iterator((Oid) 25, /* text */
(Oid) 81, /* textregexeq */
1, /* logical and */
array, (Datum)value);
}
/*
* Iterators for type _char16. Note that the regexp operators
* take the second argument of type text.
*/
int32
array_char16eq(ArrayType *array, char* value)
{
return array_iterator((Oid) 20, /* char16 */
(Oid) 490, /* char16eq */
0, /* logical or */
array, (Datum)value);
}
int32
array_all_char16eq(ArrayType *array, char* value)
{
return array_iterator((Oid) 20, /* char16 */
(Oid) 490, /* char16eq */
1, /* logical and */
array, (Datum)value);
}
int32
array_char16regexeq(ArrayType *array, char* value)
{
return array_iterator((Oid) 20, /* char16 */
(Oid) 700, /* char16regexeq */
0, /* logical or */
array, (Datum)value);
}
int32
array_all_char16regexeq(ArrayType *array, char* value)
{
return array_iterator((Oid) 20, /* char16 */
(Oid) 700, /* char16regexeq */
1, /* logical and */
array, (Datum)value);
}
/*
* Iterators for type _int4
*/
int32
array_int4eq(ArrayType *array, int4 value)
{
return array_iterator((Oid) 23, /* int4 */
(Oid) 65, /* int4eq */
0, /* logical or */
array, (Datum)value);
}
int32
array_all_int4eq(ArrayType *array, int4 value)
{
return array_iterator((Oid) 23, /* int4 */
(Oid) 65, /* int4eq */
1, /* logical and */
array, (Datum)value);
}
int32
array_int4gt(ArrayType *array, int4 value)
{
return array_iterator((Oid) 23, /* int4 */
(Oid) 147, /* int4gt */
0, /* logical or */
array, (Datum)value);
}
int32
array_all_int4gt(ArrayType *array, int4 value)
{
return array_iterator((Oid) 23, /* int4 */
(Oid) 147, /* int4gt */
1, /* logical and */
array, (Datum)value);
}
From: Massimo Dal Zotto <dz@cs.unitn.it>
Date: Mon, 6 May 1996 01:03:37 +0200 (MET DST)
Subject: [PG95]: new operators for arrays
- -----BEGIN PGP SIGNED MESSAGE-----
Hi,
I have written an extension to Postgres95 which allows to use qualification
clauses based on the values of single elements of arrays.
For example I can now select rows having some or all element of an array
attribute equal to a given value or matching a regular expression:
select * from t where t.foo *= 'bar';
select * from t where t.foo **~ '^ba[rz]';
The scheme is quite general, each operator which operates on a base type can
be iterated over the elements of an array. It seem to work well but defining
each new operators requires writing a different C function. Furthermore in
each function there are two hardcoded OIDs which reference a base type and
a procedure. Not very portable. Can anyone suggest a better and more portable
way to do it ? Do you think this could be a useful feature for next release ?
Here is my code, it can be compiled and loaded as a dynamic module without
need to recompile the backend. I have defined only the few operators I needed,
the list can be extended. Feddback is welcome.
/*
* SQL code
- - -- load the new functions
- - --
load '/home/dz/lib/postgres/array_iterator.so';
- - -- define the array operators *=, **=, *~ and **~ for type _text
- - --
create function array_texteq(_text, text)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_all_texteq(_text, text)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_textregexeq(_text, text)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_all_textregexeq(_text, text)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create operator *= (
leftarg=_text,
rightarg=text,
procedure=array_texteq);
create operator **= (
leftarg=_text,
rightarg=text,
procedure=array_all_texteq);
create operator *~ (
leftarg=_text,
rightarg=text,
procedure=array_textregexeq);
create operator **~ (
leftarg=_text,
rightarg=text,
procedure=array_all_textregexeq);
- - -- define the array operators *=, **=, *~ and **~ for type _char16
- - --
create function array_char16eq(_char16, char16)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_all_char16eq(_char16, char16)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_char16regexeq(_char16, text)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_all_char16regexeq(_char16, text)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create operator *= (
leftarg=_char16,
rightarg=char16,
procedure=array_char16eq);
create operator **= (
leftarg=_char16,
rightarg=char16,
procedure=array_all_char16eq);
create operator *~ (
leftarg=_char16,
rightarg=text,
procedure=array_char16regexeq);
create operator **~ (
leftarg=_char16,
rightarg=text,
procedure=array_all_char16regexeq);
- - -- define the array operators *=, **=, *> and **> for type _int4
- - --
create function array_int4eq(_int4, int4)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_all_int4eq(_int4, int4)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_int4gt(_int4, int4)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create function array_all_int4gt(_int4, int4)
returns bool
as '/home/dz/lib/postgres/array_iterator.so'
language 'c';
create operator *= (
leftarg=_int4,
rightarg=int4,
procedure=array_int4eq);
create operator **= (
leftarg=_int4,
rightarg=int4,
procedure=array_all_int4eq);
create operator *> (
leftarg=_int4,
rightarg=int4,
procedure=array_int4gt);
create operator **> (
leftarg=_int4,
rightarg=int4,
procedure=array_all_int4gt);
*/
/* end of file */
/*
* datetime_functions.c --
*
* This file defines new functions for the time and date data types.
*
* Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it>
*/
#include <time.h>
#include "postgres.h"
#include "pg_type.h"
#include "utils/palloc.h"
typedef struct DateADT {
char day;
char month;
short year;
} DateADT;
typedef struct TimeADT {
short hr;
short min;
float sec;
} TimeADT;
TimeADT *
time_difference(TimeADT *time1, TimeADT *time2)
{
TimeADT *time = (TimeADT*)palloc(sizeof(TimeADT));
time->sec = time1->sec - time2->sec;
time->min = time1->min - time2->min;
time->hr = time1->hr - time2->hr;
if (time->sec < 0) {
time->sec += 60.0;
time->min--;
} else if (time->sec >= 60.0) {
time->sec -= 60.0;
time->min++;
}
if (time->min < 0) {
time->min += 60;
time->hr--;
} else if (time->min >= 60) {
time->min -= 60;
time->hr++;
}
if (time->hr < 0) {
time->hr += 24;
} else if (time->hr >= 24) {
time->hr -= 24;
}
return (time);
}
TimeADT *
currentTime()
{
time_t current_time;
struct tm *tm;
TimeADT *result = (TimeADT*)palloc(sizeof(TimeADT));
current_time = time(NULL);
tm = localtime(&current_time);
result->sec = tm->tm_sec;
result->min = tm->tm_min;
result->hr = tm->tm_hour;
return (result);
}
int4
currentDate()
{
time_t current_time;
struct tm *tm;
int4 result;
DateADT *date = (DateADT*)&result;
current_time = time(NULL);
tm = localtime(&current_time);
date->day = tm->tm_mday;
date->month = tm->tm_mon+1;
date->year = tm->tm_year+1900;
return (result);
}
int4
hours(TimeADT *time)
{
return (time->hr);
}
int4
minutes(TimeADT *time)
{
return (time->min);
}
int4
seconds(TimeADT *time)
{
int seconds = (int)time->sec;
return (seconds);
}
int4
day(int4 val)
{
DateADT *date = (DateADT*)&val;
return (date->day);
}
int4
month(int4 val)
{
DateADT *date = (DateADT*)&val;
return (date->month);
}
int4
year(int4 val)
{
DateADT *date = (DateADT*)&val;
return (date->year);
}
int4
asMinutes(TimeADT *time)
{
int seconds = (int)time->sec;
return (time->min + 60*time->hr);
}
int4
asSeconds(TimeADT *time)
{
int seconds = (int)time->sec;
return (seconds + 60*time->min + 3600*time->hr);
}
From: Massimo Dal Zotto <dz@cs.unitn.it>
Date: Tue, 14 May 1996 14:31:18 +0200 (MET DST)
Subject: [PG95]: new postgres functions
- -----BEGIN PGP SIGNED MESSAGE-----
Some time ago I read in the mailing list requests of people looking
for more time and date functions. I have now written some of them:
time_difference(time1, time2) ,also defined as operator '-'
hour(time)
minutes(time)
seconds(time)
asMinutes(time)
asSeconds(time)
currentTime()
currentDate()
The file can be compiled as shared library and loaded as dynamic module
without need to recompile the backend. This can also be taken as an example
of the extensibility of postgres (user-defined functions, operators, etc).
I would be nice to see more of these user contributed modules posted to this
list and hopefully accessible from the Postgres home page.
-- SQL code to load and define 'datetime' functions
-- load the new functions
load '/home/dz/lib/postgres/datetime_functions.so';
-- define the new functions in postgres
create function time_difference(time,time)
returns time
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function currentDate()
returns date
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function currentTime()
returns time
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function hours(time)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function minutes(time)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function seconds(time)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function day(date)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function month(date)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function year(date)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function asMinutes(time)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create function asSeconds(time)
returns int4
as '/home/dz/lib/postgres/datetime_functions.so'
language 'c';
create operator - (
leftarg=time,
rightarg=time,
procedure=time_difference);
#
# Makefile
#
#
TARGET = pginsert
CFLAGS = -g -Wall -I/u/postgres95/include
LIBS = -L/u/postgres95/lib -lpq
$(TARGET) : pginsert.o pginterface.o halt.o
$(CC) -o $(TARGET) $(XFLAGS) $(CFLAGS) \
pginsert.o pginterface.o halt.o $(LIBS)
clean:
rm -f *.o $(TARGET) log core
install:
make clean
make CFLAGS=-O
install -s -o bin -g bin $(TARGET) /usr/local/bin
Pginterface 1.0
Attached is a copy of the Postgres support routines I wrote to allow me
to more cleanly interface to the libpg library, more like a 4gl SQL
interface.
It has several features that may be useful for others:
I have simplified the C code that calls libpq by wrapping all the
functionality of libpq in calls to connectdb(), doquery(), fetch(), and
disconnectdb(). Each call returns a structure or value, so if you need
to do more work with the result, you can. Also, I have a global
variable that allows you to disable the error checking I have added to
the doquery() routine.
I have added a function called fetch(), which allows you to pass
pointers as parameters, and on return the variables are filled with the
data from the binary cursor you opened. These binary cursors are not
useful if you are running the query engine on a system with a different
architecture than the database server. If you pass a NULL pointer, the
column is skipped, and you can use libpq to handle it as you wish.
I have used sigprocmask() to block the reception of certain signals
while the program is executing SQL queries. This prevents a user
pressing Control-C from stopping all the back ends. It blocks SIGHUP,
SIGINT, and SIGTERM, but does not block SIGQUIT or obviously kill -9.
If your platform does not support sigprocmask(), you can remove those
function calls. ( Am I correct that abnormal termination can cause
shared memory resynchronization?)
There is a demo program called pginsert that demonstrates how the
library can be used.
You can create a library of pginterface.c and halt.c, and just include
pginterface.h in your source code.
I am willing to maintain this if people find problems or want additional
functionality.
Bruce Momjian (root@candle.pha.pa.us)
/*
**
** halt.c
**
** This is used to print out error messages and exit
*/
#include <varargs.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/*-------------------------------------------------------------------------
**
** halt - print error message, and call clean up routine or exit
**
**------------------------------------------------------------------------*/
/*VARARGS*/
void halt(va_alist)
va_dcl
{
va_list arg_ptr;
char *format, *pstr;
void (*sig_func)();
va_start(arg_ptr);
format = va_arg(arg_ptr,char *);
if (strncmp(format,"PERROR", 6) != 0)
vfprintf(stderr,format,arg_ptr);
else
{
for (pstr=format+6; *pstr == ' ' || *pstr == ':'; pstr++)
;
vfprintf(stderr,pstr,arg_ptr);
perror("");
}
va_end(arg_ptr);
fflush(stderr);
/* call one clean up function if defined */
if ( (sig_func = signal(SIGTERM, SIG_DFL)) != SIG_DFL &&
sig_func != SIG_IGN)
(*sig_func)(0);
else if ( (sig_func = signal(SIGHUP, SIG_DFL)) != SIG_DFL &&
sig_func != SIG_IGN)
(*sig_func)(0);
else if ( (sig_func = signal(SIGINT, SIG_DFL)) != SIG_DFL &&
sig_func != SIG_IGN)
(*sig_func)(0);
else if ( (sig_func = signal(SIGQUIT, SIG_DFL)) != SIG_DFL &&
sig_func != SIG_IGN)
(*sig_func)(0);
exit(1);
}
/*
** halt.h
**
*/
void halt();
/*
* insert.c
*
*/
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include "halt.h"
#include <libpq-fe.h>
#include "pginterface.h"
int main(int argc, char **argv)
{
char query[4000];
int row =1;
int aint;
float afloat;
double adouble;
char achar[11], achar16[17], abpchar[11], avarchar[51], atext[51];
time_t aabstime;
if (argc != 2)
halt("Usage: %s database\n",argv[0]);
connectdb(argv[1],NULL,NULL,NULL,NULL);
on_error_continue();
doquery("DROP TABLE testfetch");
on_error_stop();
doquery("\
CREATE TABLE testfetch( \
aint int4, \
afloat float4, \
adouble float8, \
achar char, \
achar16 char16, \
abpchar char(10), \
avarchar varchar(50), \
atext text, \
aabstime abstime) \
");
while(1)
{
sprintf(query,"INSERT INTO testfetch VALUES ( \
%d, \
2322.12, \
'923121.0323'::float8, \
'A', \
'Betty', \
'Charley', \
'Doug', \
'Ernie', \
'now' )", row);
doquery(query);
doquery("BEGIN WORK");
doquery("DECLARE c_testfetch BINARY CURSOR FOR \
SELECT * FROM testfetch");
doquery("FETCH ALL IN c_testfetch");
while (fetch(
&aint,
&afloat,
&adouble,
achar,
achar16,
abpchar,
avarchar,
atext,
&aabstime) != END_OF_TUPLES)
printf("int %d\nfloat %f\ndouble %f\nchar %s\nchar16 %s\n\
bpchar %s\nvarchar %s\ntext %s\nabstime %s",
aint,
afloat,
adouble,
achar,
achar16,
abpchar,
avarchar,
atext,
ctime(&aabstime));
doquery("CLOSE c_testfetch");
doquery("COMMIT WORK");
printf("--- %-d rows inserted so far\n",row);
row++;
}
disconnectdb();
return 0;
}
/*
* pginterface.c
*
*/
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdarg.h>
#include "halt.h"
#include <libpq-fe.h>
#include "pginterface.h"
static void sig_disconnect();
static void set_signals();
#define NUL '\0'
/* GLOBAL VARIABLES */
static PGconn* conn;
static PGresult* res = NULL;
#define ON_ERROR_STOP 0
#define ON_ERROR_CONTINUE 1
static int on_error_state = ON_ERROR_STOP;
/* LOCAL VARIABLES */
static sigset_t block_sigs, unblock_sigs;
static int tuple;
/*
**
** connectdb - returns PGconn structure
**
*/
PGconn *connectdb( char *dbName,
char *pghost,
char *pgport,
char *pgoptions,
char *pgtty)
{
/* make a connection to the database */
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
if (PQstatus(conn) == CONNECTION_BAD)
halt("Connection to database '%s' failed.\n%s\n", dbName,
PQerrorMessage(conn));
set_signals();
return conn;
}
/*
**
** disconnectdb
**
*/
void disconnectdb()
{
PQfinish(conn);
}
/*
**
** doquery - returns PGresult structure
**
*/
PGresult *doquery(char *query)
{
if (res != NULL)
PQclear(res);
sigprocmask(SIG_SETMASK,&block_sigs,NULL);
res = PQexec(conn, query);
sigprocmask(SIG_SETMASK,&unblock_sigs,NULL);
if (on_error_state == ON_ERROR_STOP &&
(res == NULL ||
PQresultStatus(res) == PGRES_BAD_RESPONSE ||
PQresultStatus(res) == PGRES_NONFATAL_ERROR ||
PQresultStatus(res) == PGRES_FATAL_ERROR))
{
if (res != NULL)
fprintf(stderr,"query error: %s\n",PQcmdStatus(res));
else fprintf(stderr,"connection error: %s\n",PQerrorMessage(conn));
PQfinish(conn);
halt("failed request: %s\n", query);
}
tuple = 0;
return res;
}
/*
**
** fetch - returns tuple number (starts at 0), or the value END_OF_TUPLES
** NULL pointers are skipped
**
*/
int fetch(void *param, ...)
{
va_list ap;
int arg, num_args;
num_args = PQnfields(res);
if (tuple >= PQntuples(res))
return END_OF_TUPLES;
va_start(ap, param);
for (arg = 0; arg < num_args; arg++)
{
if (param != NULL)
{
if (PQfsize(res, arg) == -1)
{
memcpy(param,PQgetvalue(res,tuple,arg),PQgetlength(res,tuple,arg));
((char *)param)[PQgetlength(res,tuple,arg)] = NUL;
}
else
memcpy(param,PQgetvalue(res,tuple,arg),PQfsize(res,arg));
}
param = va_arg(ap, char *);
}
va_end(ap);
return tuple++;
}
/*
**
** on_error_stop
**
*/
void on_error_stop()
{
on_error_state = ON_ERROR_STOP;
}
/*
**
** on_error_continue
**
*/
void on_error_continue()
{
on_error_state = ON_ERROR_CONTINUE;
}
/*
**
** sig_disconnect
**
*/
static void sig_disconnect()
{
fprintf(stderr,"exiting...\n");
PQfinish(conn);
exit(1);
}
/*
**
** set_signals
**
*/
static void set_signals()
{
sigemptyset(&block_sigs);
sigemptyset(&unblock_sigs);
sigaddset(&block_sigs,SIGTERM);
sigaddset(&block_sigs,SIGHUP);
sigaddset(&block_sigs,SIGINT);
/* sigaddset(&block_sigs,SIGQUIT); no block */
sigprocmask(SIG_SETMASK,&unblock_sigs,NULL);
signal(SIGTERM,sig_disconnect);
signal(SIGHUP,sig_disconnect);
signal(SIGINT,sig_disconnect);
signal(SIGQUIT,sig_disconnect);
}
/*
* pglib.h
*
*/
PGresult *doquery(char *query);
PGconn *connectdb();
void disconnectdb();
int fetch(void *param, ...);
void on_error_continue();
void on_error_stop();
#define END_OF_TUPLES (-1)
/*****************************************************************************/
/* soundex.c */
/*****************************************************************************/
#include <string.h>
#include <stdio.h>
#include "postgres.h" /* for char16, etc. */
#include "utils/palloc.h" /* for palloc */
#include "libpq-fe.h" /* for TUPLE */
#include <stdio.h>
#include <ctype.h>
/* prototype for soundex function */
char *soundex(char *instr, char *outstr);
text *text_soundex(text *t)
{
/* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
char *table = "01230120022455012623010202";
int count = 0;
text *new_t;
char outstr[6+1]; /* max length of soundex is 6 */
char *instr;
/* make a null-terminated string */
instr=palloc(VARSIZE(t)+1);
memcpy(instr,VARDATA(t),VARSIZE(t)-VARHDRSZ);
instr[VARSIZE(t)-VARHDRSZ] = (char)0;
/* load soundex into outstr */
soundex(instr, outstr);
/* Now the outstr contains the soundex of instr */
/* copy outstr to new_t */
new_t = (text *) palloc(strlen(outstr)+VARHDRSZ);
memset(new_t, 0, strlen(outstr)+1);
VARSIZE(new_t) = strlen(outstr)+VARHDRSZ;
memcpy((void *) VARDATA(new_t),
(void *) outstr,
strlen(outstr));
/* free instr */
pfree(instr);
return(new_t);
}
char *soundex(char *instr, char *outstr)
{ /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
char *table = "01230120022455012623010202";
int count = 0;
while(!isalpha(instr[0]) && instr[0])
++instr;
if(!instr[0]) { /* Hey! Where'd the string go? */
outstr[0]=(char)0;
return outstr;
}
if(toupper(instr[0]) == 'P' && toupper(instr[1]) == 'H') {
instr[0] = 'F';
instr[1] = 'A';
}
*outstr++ = (char)toupper(*instr++);
while(*instr && count < 5) {
if(isalpha(*instr) && *instr != *(instr-1)) {
*outstr = table[toupper(instr[0]) - 'A'];
if(*outstr != '0') {
++outstr;
++count;
}
}
++instr;
}
*outstr = '\0';
return(outstr);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment