From: Bruce Momjian Date: Mon, 19 Jun 2000 14:02:16 +0000 (+0000) Subject: Add missing /contrib files X-Git-Tag: REL9_0_0~23015 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=bad9ce7099c2d4154dbd787f34a3a3a3a405e4e1;p=pg-rex%2Fsyncrep.git Add missing /contrib files --- diff --git a/contrib/array/README.array_iterator b/contrib/array/README.array_iterator new file mode 100644 index 0000000000..b072ebe397 --- /dev/null +++ b/contrib/array/README.array_iterator @@ -0,0 +1,49 @@ +Array iterator functions, by Massimo Dal Zotto +Copyright (C) 1999, Massimo Dal Zotto + +This software is distributed under the GNU General Public License +either version 2, or (at your option) any later version. + + +This loadable module defines a new class of functions 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 iteration 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 x 2 array functions, each of them has a name like +"array_[all_]" 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. + +We can then define new operators based on these functions and use +them to write queries with qualification clauses based on the +values of some of the elements of an array. +For example to select rows having some or all element of an array +attribute equal to a given value or matching a regular expression: + + create table t(id int4[], txt text[]); + + -- select tuples with some id element equal to 123 + select * from t where t.id *= 123; + + -- select tuples with some txt element matching '[a-z]' + select * from t where t.txt *~ '[a-z]'; + + -- select tuples with all txt elements matching '^[A-Z]' + select * from t where t.txt[1:3] **~ '^[A-Z]'; + +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 ? + +See also array_iterator.sql for an example on how to use this module. diff --git a/contrib/earthdistance/README.earthdistance b/contrib/earthdistance/README.earthdistance new file mode 100644 index 0000000000..f4ecef80fe --- /dev/null +++ b/contrib/earthdistance/README.earthdistance @@ -0,0 +1,31 @@ +Date: Wed, 1 Apr 1998 15:19:32 -0600 (CST) +From: Hal Snyder +To: vmehr@ctp.com +Subject: [QUESTIONS] Re: Spatial data, R-Trees + +> From: Vivek Mehra +> Date: Wed, 1 Apr 1998 10:06:50 -0500 + +> Am just starting out with PostgreSQL and would like to learn more about +> the spatial data handling ablilities of postgreSQL - in terms of using +> R-tree indexes, user defined types, operators and functions. +> +> Would you be able to suggest where I could find some code and SQL to +> look at to create these? + +Here's the setup for adding an operator '<@>' to give distance in +statute miles between two points on the earth's surface. Coordinates +are in degrees. Points are taken as (longitude, latitude) and not vice +versa as longitude is closer to the intuitive idea of x-axis and +latitude to y-axis. + +There's C source, Makefile for FreeBSD, and SQL for installing and +testing the function. + +Let me know if anything looks fishy! + +A note on testing C extensions - it seems not enough to drop a function +and re-create it - if I change a function, I have to stop and restart +the backend for the new version to be seen. I guess it would be too +messy to track which functions are added from a .so and do a dlclose +when the last one is dropped. diff --git a/contrib/findoidjoins/README.findoidjoins b/contrib/findoidjoins/README.findoidjoins new file mode 100644 index 0000000000..44c150a43f --- /dev/null +++ b/contrib/findoidjoins/README.findoidjoins @@ -0,0 +1,90 @@ + + findoidjoins + +This program scans a database, and prints oid fields (also regproc fields) +and the tables they join to. CAUTION: it is ver-r-r-y slow on a large +database, or even a not-so-large one. We don't really recommend running +it on anything but an empty database, such as template1. + +Uses pgeasy library. + +Run on an empty database, it returns the system join relationships (shown +below for 7.0). Note that unexpected matches may indicate bogus entries +in system tables --- don't accept a peculiar match without question. +In particular, a field shown as joining to more than one target table is +probably messed up. In 7.0, the *only* field that should join to more +than one target is pg_description.objoid. (Running make_oidjoins_check +is an easy way to spot fields joining to more than one table, BTW.) + +The shell script make_oidjoins_check converts findoidjoins' output +into an SQL script that checks for dangling links (entries in an +OID or REGPROC column that don't match any row in the expected table). +Note that fields joining to more than one table are NOT processed. + +The result of make_oidjoins_check should be installed as the "oidjoins" +regression test. The oidjoins test should be updated after any +revision in the patterns of cross-links between system tables. +(Ideally we'd just regenerate the script as part of the regression +tests themselves, but that seems too slow...) + +--------------------------------------------------------------------------- + +Join pg_aggregate.aggtransfn1 => pg_proc.oid +Join pg_aggregate.aggtransfn2 => pg_proc.oid +Join pg_aggregate.aggfinalfn => pg_proc.oid +Join pg_aggregate.aggbasetype => pg_type.oid +Join pg_aggregate.aggtranstype1 => pg_type.oid +Join pg_aggregate.aggtranstype2 => pg_type.oid +Join pg_aggregate.aggfinaltype => pg_type.oid +Join pg_am.amgettuple => pg_proc.oid +Join pg_am.aminsert => pg_proc.oid +Join pg_am.amdelete => pg_proc.oid +Join pg_am.ambeginscan => pg_proc.oid +Join pg_am.amrescan => pg_proc.oid +Join pg_am.amendscan => pg_proc.oid +Join pg_am.ammarkpos => pg_proc.oid +Join pg_am.amrestrpos => pg_proc.oid +Join pg_am.ambuild => pg_proc.oid +Join pg_am.amcostestimate => pg_proc.oid +Join pg_amop.amopid => pg_am.oid +Join pg_amop.amopclaid => pg_opclass.oid +Join pg_amop.amopopr => pg_operator.oid +Join pg_amproc.amid => pg_am.oid +Join pg_amproc.amopclaid => pg_opclass.oid +Join pg_amproc.amproc => pg_proc.oid +Join pg_attribute.attrelid => pg_class.oid +Join pg_attribute.atttypid => pg_type.oid +Join pg_class.reltype => pg_type.oid +Join pg_class.relam => pg_am.oid +Join pg_description.objoid => pg_proc.oid +Join pg_description.objoid => pg_type.oid +Join pg_index.indexrelid => pg_class.oid +Join pg_index.indrelid => pg_class.oid +Join pg_opclass.opcdeftype => pg_type.oid +Join pg_operator.oprleft => pg_type.oid +Join pg_operator.oprright => pg_type.oid +Join pg_operator.oprresult => pg_type.oid +Join pg_operator.oprcom => pg_operator.oid +Join pg_operator.oprnegate => pg_operator.oid +Join pg_operator.oprlsortop => pg_operator.oid +Join pg_operator.oprrsortop => pg_operator.oid +Join pg_operator.oprcode => pg_proc.oid +Join pg_operator.oprrest => pg_proc.oid +Join pg_operator.oprjoin => pg_proc.oid +Join pg_proc.prolang => pg_language.oid +Join pg_proc.prorettype => pg_type.oid +Join pg_rewrite.ev_class => pg_class.oid +Join pg_statistic.starelid => pg_class.oid +Join pg_statistic.staop => pg_operator.oid +Join pg_trigger.tgrelid => pg_class.oid +Join pg_trigger.tgfoid => pg_proc.oid +Join pg_type.typrelid => pg_class.oid +Join pg_type.typelem => pg_type.oid +Join pg_type.typinput => pg_proc.oid +Join pg_type.typoutput => pg_proc.oid +Join pg_type.typreceive => pg_proc.oid +Join pg_type.typsend => pg_proc.oid + +--------------------------------------------------------------------------- + +Bruce Momjian (root@candle.pha.pa.us) diff --git a/contrib/fulltextindex/README.fti b/contrib/fulltextindex/README.fti new file mode 100644 index 0000000000..fdb6fcf3b1 --- /dev/null +++ b/contrib/fulltextindex/README.fti @@ -0,0 +1,197 @@ +An attempt at some sort of Full Text Indexing for PostgreSQL. + +The included software is an attempt to add some sort of Full Text Indexing +support to PostgreSQL. I mean by this that we can ask questions like: + + Give me all rows that have 'still' and 'nash' in the 'artist' field. + +Ofcourse we can write this as: + + select * from cds where artist ~* 'stills' and artist ~* 'nash'; + +But this does not use any indices, and therefore, if your database +gets very large, it will not have very high performance (the above query +requires at least one sequential scan, it probably takes 2 due to the +self-join). + +The approach used by this add-on is to define a trigger on the table and +column you want to do this queries on. On every insert in the table, it +takes the value in the specified column, breaks the text in this column +up into pieces, and stores all sub-strings into another table, together +with a reference to the row in the original table that contained this +sub-string (it uses the oid of that row). + +By now creating an index over the 'fti-table', we can search for +substrings that occur in the original table. By making a join between +the fti-table and the orig-table, we can get the actual rows we want +(this can also be done by using subselects, and maybe there're other +ways too). + +The trigger code also allows an array called StopWords, that prevents +certain words from being indexed. + +As an example we take the previous query, where we assume we have all +sub-strings in the table 'cds-fti': + + select c.* + from cds c, cds-fti f1, cds-fti f2 + where f1.string ~ '^stills' and + f2.string ~ '^nash' and + f1.id = c.oid and + f2.id = c.oid ; + +We can use the ~ (case-sensitive regular expression) here, because of +the way sub-strings are built: from right to left, ie. house -> 'se' + +'use' + 'ouse' + 'house'. If a ~ search starts with a ^ (match start of +string), btree indices can be used by PostgreSQL. + +Now, how do we create the trigger that maintains the fti-table? First: the +fti-table should have the following schema: + + create cds-fti ( string varchar(N), id oid ); + +Don't change the *names* of the columns, the varchar() can in fact also +be of text-type. If you do use varchar, make sure the largest possible +sub-string will fit. + +The create the function that contains the trigger:: + + create function fti() returns opaque as + '/path/to/fti.so' language 'newC'; + +And finally define the trigger on the 'cds' table: + + create trigger cds-fti-trigger after update or insert or delete on cds + for each row execute procedure fti(cds-fti, artist); + +Here, the trigger will be defined on table 'cds', it will create +sub-strings from the field 'artist', and it will place those sub-strings +in the table 'cds-fti'. + +Now populate the table 'cds'. This will also populate the table 'cds-fti'. +It's fastest to populate the table *before* you create the indices. + +Before you start using the system, you should at least have the following +indices: + + create index cds-fti-idx on cds-fti (string, id); + create index cds-oid-idx on cds (oid); + +To get the most performance out of this, you should have 'cds-fti' +clustered on disk, ie. all rows with the same sub-strings should be +close to each other. There are 3 ways of doing this: + +1. After you have created the indices, execute 'cluster cds-fti-idx on cds-fti'. +2. Do a 'select * into tmp-table from cds-fti order by string' *before* + you create the indices, then 'drop table cds-fti' and + 'alter table tmp-table rename to cds-fti' +3. *Before* creating indices, dump the contents of the cds-fti table using + 'pg_dump -a -t cds-fti dbase-name', remove the \connect + from the beginning and the \. from the end, and sort it using the + UNIX 'sort' program, and reload the data. + +Method 1 is very slow, 2 a lot faster, and for very large tables, 3 is +preferred. + + +BENCH: +~~~~~ + +Maarten Boekhold +The following data was generated by the 'timings.sh' script included +in this directory. It uses a very large table with music-related +articles as a source for the fti-table. The tables used are: + +product : contains product information : 540.429 rows +artist_fti : fti table for product : 4.501.321 rows +clustered : same as above, only clustered : 4.501.321 rows + +A sequential scan of the artist_fti table (and thus also the clustered table) +takes around 6:16 minutes.... + +Unfortunately I cannot probide anybody else with this test-date, since I +am not allowed to redistribute the data (it's a database being sold by +a couple of wholesale companies). Anyways, it's megabytes, so you probably +wouldn't want it in this distribution anyways. + +I haven't tested this with less data. + +The test-machine is a Pentium 133, 64 MB, Linux 2.0.32 with the database +on a 'QUANTUM BIGFOOT_CY4320A, 4134MB w/67kB Cache, CHS=8960/15/63'. This +is a very slow disk. + +The postmaster was running with: + + postmaster -i -b /usr/local/pgsql/bin/postgres -S 1024 -B 256 \ + -o -o /usr/local/pgsql/debug-output -F -d 1 + +('trashing' means a 'select count(*) from artist_fti' to completely trash +any disk-caches and buffers....) + +TESTING ON UNCLUSTERED FTI +trashing +1: ^lapton and ^ric : 0.050u 0.000s 5m37.484s 0.01% +2: ^lapton and ^ric : 0.050u 0.030s 5m32.447s 0.02% +3: ^lapton and ^ric : 0.030u 0.020s 5m28.822s 0.01% +trashing +1: ^lling and ^tones : 0.020u 0.030s 0m54.313s 0.09% +2: ^lling and ^tones : 0.040u 0.030s 0m5.057s 1.38% +3: ^lling and ^tones : 0.010u 0.050s 0m2.072s 2.89% +trashing +1: ^aughan and ^evie : 0.020u 0.030s 0m26.241s 0.19% +2: ^aughan and ^evie : 0.050u 0.010s 0m1.316s 4.55% +3: ^aughan and ^evie : 0.030u 0.020s 0m1.029s 4.85% +trashing +1: ^lling : 0.040u 0.010s 0m55.104s 0.09% +2: ^lling : 0.030u 0.030s 0m4.716s 1.27% +3: ^lling : 0.040u 0.010s 0m2.157s 2.31% +trashing +1: ^stev and ^ray and ^vaugh : 0.040u 0.000s 1m5.630s 0.06% +2: ^stev and ^ray and ^vaugh : 0.050u 0.020s 1m3.561s 0.11% +3: ^stev and ^ray and ^vaugh : 0.050u 0.010s 1m5.923s 0.09% +trashing +1: ^lling (no join) : 0.050u 0.020s 0m24.139s 0.28% +2: ^lling (no join) : 0.040u 0.040s 0m1.087s 7.35% +3: ^lling (no join) : 0.020u 0.030s 0m0.772s 6.48% +trashing +1: ^vaughan (no join) : 0.040u 0.030s 0m9.075s 0.77% +2: ^vaughan (no join) : 0.030u 0.010s 0m0.609s 6.56% +3: ^vaughan (no join) : 0.040u 0.010s 0m0.503s 9.94% +trashing +1: ^rol (no join) : 0.020u 0.030s 0m49.898s 0.10% +2: ^rol (no join) : 0.030u 0.020s 0m3.136s 1.59% +3: ^rol (no join) : 0.030u 0.020s 0m1.231s 4.06% + +TESTING ON CLUSTERED FTI +trashing +1: ^lapton and ^ric : 0.020u 0.020s 2m17.120s 0.02% +2: ^lapton and ^ric : 0.030u 0.020s 2m11.767s 0.03% +3: ^lapton and ^ric : 0.040u 0.010s 2m8.128s 0.03% +trashing +1: ^lling and ^tones : 0.020u 0.030s 0m18.179s 0.27% +2: ^lling and ^tones : 0.030u 0.010s 0m1.897s 2.10% +3: ^lling and ^tones : 0.040u 0.010s 0m1.619s 3.08% +trashing +1: ^aughan and ^evie : 0.070u 0.010s 0m11.765s 0.67% +2: ^aughan and ^evie : 0.040u 0.010s 0m1.198s 4.17% +3: ^aughan and ^evie : 0.030u 0.020s 0m0.872s 5.73% +trashing +1: ^lling : 0.040u 0.000s 0m28.623s 0.13% +2: ^lling : 0.030u 0.010s 0m2.339s 1.70% +3: ^lling : 0.030u 0.010s 0m1.975s 2.02% +trashing +1: ^stev and ^ray and ^vaugh : 0.020u 0.010s 0m17.667s 0.16% +2: ^stev and ^ray and ^vaugh : 0.030u 0.010s 0m3.745s 1.06% +3: ^stev and ^ray and ^vaugh : 0.030u 0.020s 0m3.439s 1.45% +trashing +1: ^lling (no join) : 0.020u 0.040s 0m2.218s 2.70% +2: ^lling (no join) : 0.020u 0.020s 0m0.506s 7.90% +3: ^lling (no join) : 0.030u 0.030s 0m0.510s 11.76% +trashing +1: ^vaughan (no join) : 0.040u 0.050s 0m2.048s 4.39% +2: ^vaughan (no join) : 0.030u 0.020s 0m0.332s 15.04% +3: ^vaughan (no join) : 0.040u 0.010s 0m0.318s 15.72% +trashing +1: ^rol (no join) : 0.020u 0.030s 0m2.384s 2.09% +2: ^rol (no join) : 0.020u 0.030s 0m0.676s 7.39% +3: ^rol (no join) : 0.020u 0.030s 0m0.697s 7.17% diff --git a/contrib/isbn_issn/README.isbn_issn b/contrib/isbn_issn/README.isbn_issn new file mode 100644 index 0000000000..6b734ce905 --- /dev/null +++ b/contrib/isbn_issn/README.isbn_issn @@ -0,0 +1,22 @@ + +ISBN (books) and ISSN (serials) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This directory contains definitions for a couple of PostgreSQL +external types, for a couple of international-standard namespaces: +ISBN (books) and ISSN (serials). Rather than just using a char() +member of the appropriate length, I wanted my database to include +the validity-checking that both these numbering systems were designed +to encompass. A little bit of research revealed the formulae +for computing the check digits, and I also included some validity +constraints on the number of hyphens. + +The internal representation of these types is intended to be +compatible with `char16', in the (perhaps vain) hope that +this will make it possible to create indices of these types +using char16_ops. + +These are based on Tom Ivar Helbekkmo's IP address type definition, +from which I have copied the entire form of the implementation. + +Garrett A. Wollman, August 1998 diff --git a/contrib/lo/README.lo b/contrib/lo/README.lo new file mode 100644 index 0000000000..aa06adf084 --- /dev/null +++ b/contrib/lo/README.lo @@ -0,0 +1,69 @@ +PostgreSQL type extension for managing Large Objects +---------------------------------------------------- + +Overview + +One of the problems with the JDBC driver (and this affects the ODBC driver +also), is that the specification assumes that references to BLOBS (Binary +Large OBjectS) are stored within a table, and if that entry is changed, the +associated BLOB is deleted from the database. + +As PostgreSQL stands, this doesn't occur. It allocates an OID for each object, +and it is up to the application to store, and ultimately delete the objects. + +Now this is fine for new postgresql specific applications, but existing ones +using JDBC or ODBC wont delete the objects, arising to orphaning - objects +that are not referenced by anything, and simply occupy disk space. + +The Fix + +I've fixed this by creating a new data type 'lo', some support functions, and +a Trigger which handles the orphaning problem. + +The 'lo' type was created because we needed to differenciate between normal +Oid's and Large Objects. Currently the JDBC driver handles this dilema easily, +but (after talking to Byron), the ODBC driver needed a unique type. They had created an 'lo' type, but not the solution to orphaning. + +Install + +Ok, first build the shared library, and install. Typing 'make install' in the +contrib/lo directory should do it. + +Then, as the postgres super user, run the lo.sql script. This will install the +type, and define the support functions. + +How to Use + +The easiest way is by an example: + +> create table image (title text,raster lo); +> create trigger t_image before update or delete on image for each row execute procedure lo_manage(raster); + +Here, a trigger is created for each column that contains a lo type. + +Issues + +* dropping a table will still orphan any objects it contains, as the trigger + is not actioned. + + For now, precede the 'drop table' with 'delete from {table}'. However, this + could be fixed by having 'drop table' perform an additional + + 'select lo_unlink({colname}::oid) from {tablename}' + + for each column, before actually dropping the table. + +* Some frontends may create their own tables, and will not create the + associated trigger(s). Also, users may not remember (or know) to create + the triggers. + + This can be solved, but would involve changes to the parser. + +As the ODBC driver needs a permanent lo type (& JDBC could be optimised to +use it if it's Oid is fixed), and as the above issues can only be fixed by +some internal changes, I feel it should become a permanent built-in type. + +I'm releasing this into contrib, just to get it out, and tested. + +Peter Mount June 13 1998 + diff --git a/contrib/mSQL-interface/README.mpgsql b/contrib/mSQL-interface/README.mpgsql new file mode 100644 index 0000000000..714ab29056 --- /dev/null +++ b/contrib/mSQL-interface/README.mpgsql @@ -0,0 +1,86 @@ + +Hello! :) + +(Sorry for my english. But if i wrote in portuguese, you wouldn't + understand nothing. :]) + + I found it's the right place to post this. I'm a newcomer in these +lists. I hope i did it right. :] + + + When i started using SQL, i started with mSQL. I developed a lot +of useful apps for me and my job with C, mainly because i loved it's +elegant, simple api. But for a large project i'm doing in these days, i +thought is was not enough, because it felt a lot of features i started to +need, like security and subselects. (and it's not free :)) + So after looking at the options, choose to start again with +postgres. It offered everything that i needed, and the documentation is +really good (remember me to thank the one who wrote'em). + But for my little apps, i needed to start porting them to libpq. +After looking at pq's syntax, i found it was better to write a bridge +between the mSQL api and libpq. I found that rewriting the libmsql.a +routines that calls libpq would made things much easier. I guess the +results are quite good right now. + + + Ok. Lets' summarize it: + + mpgsql.c is the bridge. Acting as a wrapper, it's really good, +since i could run mSQL. But it's not accurate. Some highlights: + + CONS: + * It's not well documented + (this post is it's first documentation attempt, in fact); + * It doesn't handle field types correctly. I plan to fix it, + if people start doing feedbacks; + * It's limited to 10 simultaneous connections. I plan to enhance + this, i'm just figuring out; + * I'd like to make it reentrant/thread safe, although i don't + think this could be done without changing the API structure; + * Error Management should be better. This is my first priority + now; + * Some calls are just empty implementations. + + PROS: + * the mSQL Monitor runs Okay. :] + * It's really cool. :) + * Make mSQL-made applications compatible with postgresql just by + changing link options. + * Uses postgreSQL. :] + * the mSQL API it's far easier to use and understand than libpq. + Consider this example: + +#include "msql.h" + +void main(int argc, char **argv, char **envp) { + int sid; + + sid = msqlConnect(NULL); /* Connects via unix socket */ + + if (sid >= 0) { + m_result *rlt; + m_row *row; + msqlSelectDB(sid, "hosts"); + if (msqlQuery(sid, "select host_id from hosts")) { + rlt = msqlStoreResult(); + while (row = (m_row*)msqlFetchRow(rlt)) + printf("hostid: %s\n", row[0]); + msqlFreeResult(rlt); + } + msqlClose(sid); + } +} + + I enclose mpgsql.c inside. I'd like to maintain it, and (maybe, am +i dreaming) make it as part of the pgsql distribution. I guess it doesn't +depends on me, but mainly on it's acceptance by its users. + + Hm... i forgot: you'll need a msql.h copy, since it's copyrighted +by Hughes Technologies Pty Ltd. If you haven't it yes, fetch one +from www.hughes.com.au. + + I would like to catch users ideas. My next goal is to add better +error handling, and to make it better documented, and try to let relshow +run through it. :) + + done. Aldrin Leal diff --git a/contrib/miscutil/README.misc_utils b/contrib/miscutil/README.misc_utils new file mode 100644 index 0000000000..903455513a --- /dev/null +++ b/contrib/miscutil/README.misc_utils @@ -0,0 +1,43 @@ +Miscellaneous utility functions for PostgreSQL. +Copyright (C) 1999, Massimo Dal Zotto + +This software is distributed under the GNU General Public License +either version 2, or (at your option) any later version. + +query_limit(n) + + sets a limit on the maximum numbers of query returned from + a backend. It can be used to limit the result size retrieved + by the application for poor input data or to avoid accidental + table product while playying with sql. + +backend_pid() + + return the pid of our corresponding backend. + +unlisten(relname) + + unlisten from a relation or from all relations if the argument + is null, empty or '*'. + It is now obsoleted by the new unlisten command but still useful + if you want unlisten a name computed by the query. + Note that a listen/notify relname can be any ascii string, not + just valid relation names. + +min(x,y) +max(x,y) + + return the min or max bteween two integers. + +assert_enable(bool) + + enable/disable assert checkings in the backend, if it has been + compiled with USE_ASSERT_CHECKING. + +assert_test(bool) + + test the assert enable/disable code, if the backend has been + compiled with ASSERT_CHECKING_TEST. + +-- +Massimo Dal Zotto diff --git a/contrib/noupdate/README.noup b/contrib/noupdate/README.noup new file mode 100644 index 0000000000..1c773dc778 --- /dev/null +++ b/contrib/noupdate/README.noup @@ -0,0 +1,20 @@ + + +noupdate +~~~~~~~~ + + - trigger to prevent updates on single columns. + + +Example: +~~~~~~~ + +CREATE TABLE TEST ( COL1 INT, COL2 INT, COL3 INT ); + +CREATE TRIGGER BT BEFORE UPDATE ON TEST FOR EACH ROW + EXECUTE PROCEDURE + noup ('COL1'); + +-- Now Try +INSERT INTO TEST VALUES (10,20,30); +UPDATE TEST SET COL1 = 5; diff --git a/contrib/odbc/README.odbc b/contrib/odbc/README.odbc new file mode 100644 index 0000000000..c36f183c05 --- /dev/null +++ b/contrib/odbc/README.odbc @@ -0,0 +1,38 @@ +This directory contains support functions for the ODBC driver +supplied with PostgreSQL-7.0. + +To enable additional ODBC functions with PostgreSQL-7.0, simply +execute the commands in odbc.sql: + +psql +Welcome to psql, the PostgreSQL interactive terminal. + +Type: \copyright for distribution terms + \h for help with SQL commands + \? for help on internal slash commands + \g or terminate with semicolon to execute query + \q to quit + +postgres=# \i odbc.sql +CREATE +... + + +To enable additional ODBC functions with versions of PostgreSQL +prior to PostgreSQL-7.0 (e.g. PostgreSQL-6.5.3), build the shared +library and SQL commands as follows: + +make pre7 +psql +Welcome to psql, the PostgreSQL interactive terminal. + +Type: \copyright for distribution terms + \h for help with SQL commands + \? for help on internal slash commands + \g or terminate with semicolon to execute query + \q to quit + +postgres=# \i odbc-pre7.sql +CREATE +... + diff --git a/contrib/pg_dumplo/README.pg_dumplo b/contrib/pg_dumplo/README.pg_dumplo new file mode 100644 index 0000000000..aef8f9f71d --- /dev/null +++ b/contrib/pg_dumplo/README.pg_dumplo @@ -0,0 +1,117 @@ + +How to use pg_dumplo? +===================== + +(c) 2000, Pavel Janík ml. + + +Q: How do you use pg_dumplo? +============================ + +A: This is a small demo of backing up the database table with Large Objects: + + +We will create a demo database and a small and useless table `lo' inside +it: + +SnowWhite:$ createdb test +CREATE DATABASE + +Ok, our database with the name 'test' is created. Now we should create demo +table which will contain only one column with the name 'id' which will hold +the oid number of Large Object: + +SnowWhite:$ psql test +Welcome to psql, the PostgreSQL interactive terminal. + +Type: \copyright for distribution terms + \h for help with SQL commands + \? for help on internal slash commands + \g or terminate with semicolon to execute query + \q to quit + +test=# CREATE TABLE lo (id oid); +CREATE +test=# \lo_import /etc/aliases +lo_import 19338 +test=# INSERT INTO lo VALUES (19338); +INSERT 19352 1 +test=# select * from lo; + id +------- + 19338 +(1 row) + +test=# \q + +In the above example you can see that we have also imported one "Large +Object" - the file /etc/aliases. It has an oid of 19338 so we have inserted +this oid number to the database table lo to the column id. The final SELECT +shows that we have one record in the table. + +Now we can demonstrate the work of pg_dumplo. We will create dump directory +which will contain the whole dump of large objects (/tmp/dump): + +mkdir -p /tmp/dump + +Now we can dump all large objects from the database `test' which has an oid +stored in the column `id' in the table `lo': + +SnowWhite:$ pg_dumplo -s /tmp/dump -d test -l lo.id +pg_dumplo: dump lo.id (1 large obj) + +Voila, we have the dump of all Large Objects in our directory: + +SnowWhite:$ tree /tmp/dump/ +/tmp/dump/ +`-- test + |-- lo + | `-- id + | `-- 19338 + `-- lo_dump.index + +3 directories, 2 files +SnowWhite:$ + +Isn't it nice :-) Yes, it is, but we are on the half of our way. We should +also be able to recreate the contents of the table lo and the Large Object +database when something went wrong. It is very easy, we will demonstrate +this via dropping the database and recreating it from scratch with +pg_dumplo: + +SnowwWite:$ dropdb test +DROP DATABASE + +SnowWhite:$ createdb test +CREATE DATABASE + +Ok, our database with the name `test' is created again. We should also +create the table `lo' again: + +SnowWhite:$ psql test +Welcome to psql, the PostgreSQL interactive terminal. + +Type: \copyright for distribution terms + \h for help with SQL commands + \? for help on internal slash commands + \g or terminate with semicolon to execute query + \q to quit + +test=# CREATE TABLE lo (id oid); +CREATE +test=# \q +SnowWhite:$ + +Now the database with the table `lo' is created again, but we do not have +any information stored in it. But have the dump of complete Large Object +database, so we can recreate the contents of the whole database from the +directory /tmp/dump: + +SnowWhite:$ pg_dumplo -s /tmp/dump -d test -i +19338 lo id test/lo/id/19338 +SnowWhite:$ + +And this is everything. + +Summary: In this small example we have shown that pg_dumplo can be used to +completely dump the database's Large Objects very easily. diff --git a/contrib/pgbench/README.pgbench b/contrib/pgbench/README.pgbench new file mode 100644 index 0000000000..093f2b9869 --- /dev/null +++ b/contrib/pgbench/README.pgbench @@ -0,0 +1,149 @@ +pgbench 1.2 README 2000/1/15 Tatsuo Ishii (t-ishii@sra.co.jp) + +o What is pgbench? + + pgbench is a simple program to run a benchmark test sort of + "TPC-B". pgbench is a client application of PostgreSQL and runs + with PostgreSQL only. It performs lots of small and simple + transactions including select/update/insert operations then + calculates number of transactions successfully completed within a + second (transactions per second, tps). Targeting data includes a + table with at least 100k tuples. + + Example outputs from pgbench look like: + + number of clients: 4 + number of transactions per client: 100 + number of processed transactions: 400/400 + tps = 19.875015(including connections establishing) + tps = 20.098827(excluding connections establishing) + + Similar program called "JDBCBench" already exists, but it requires + Java that may not be available on every platform. Moreover some + people concerned about the overhead of Java that might lead + inaccurate results. So I decided to write in pure C, and named + it "pgbench." + +o features of pgbench + + - pgbench is written in C using libpq only. So it is very portable + and easy to install. + + - pgbench can simulate concurrent connections using asynchronous + capability of libpq. No threading is required. + +o How to install pgbench + + (1) Edit the first line in Makefile + + POSTGRESHOME = /usr/local/pgsql + + so that it points to the directory where PostgreSQL installed. + + (2) Run configure + + (3) Run make. You will see an executable file "pgbench" there. + +o How to use pgbench? + + (1) Initialize database by: + + pgbench -i + + where is the name of database. pgbench uses four tables + accounts, branches, history and tellers. These tables will be + destroyed. Be very carefully if you have tables having same + names. Default test data contains: + + table # of tuples + ------------------------- + branches 1 + tellers 10 + accounts 100000 + history 0 + + You can increase the number of tuples by using -s option. See + below. + + (2) Run the benchmark test + + pgbench + + The default configuration is: + + number of clients: 1 + number of transactions per client: 10 + +o options + + pgbench has number of options. + + -h hostname + hostname where the backend is running. If this option + is omitted, pgbench will connect to the localhost via + Unix domain socket. + + -p port + the port number that the backend is accepting. default is + 5432. + + -c number_of_clients + Number of clients simulated. default is 1. + + -t number_of_transactions + Number of transactions each client runs. default is 10. + + -s scaling_factor + this should be used with -i (initialize) option. + number of tuples generated will be multiple of the + scaling factor. For example, -s 100 will imply 10M + (10,000,000) tuples in the accounts table. + default is 1. + + -n + No vacuuming and cleaning the history table prior the + test is performed. + + -v + Do vacuuming before testing. This will take some time. + Without both -n and -v pgbench will vacuum tellers and + branches tables only. + + -S + Perform select only transactions instead of TPC-B. + + -d + debug option. + + +o What is the "transaction" actually performed in pgbench? + + (1) begin; + + (2) update accounts set abalance = abalance + :delta where aid = :aid; + + (3) select abalance from accounts where aid = :aid; + + (4) update tellers set tbalance = tbalance + :delta where tid = :tid; + + (5) update branches set bbalance = bbalance + :delta where bid = :bid; + + (6) insert into history(tid,bid,aid,delta) values(:tid,:bid,:aid,:delta); + + (7) end; + +o License? + +Basically it is same as BSD license. See pgbench.c for more details. + +o History + +2000/1/15 pgbench-1.2 contributed to PostgreSQL + * Add -v option + +1999/09/29 pgbench-1.1 released + * Apply cygwin patches contributed by Yutaka Tanida + * More robust when backends die + * Add -S option (select only) + +1999/09/04 pgbench-1.0 released \ No newline at end of file diff --git a/contrib/pgbench/README.pgbench_jis b/contrib/pgbench/README.pgbench_jis new file mode 100644 index 0000000000..da33c31744 --- /dev/null +++ b/contrib/pgbench/README.pgbench_jis @@ -0,0 +1,166 @@ +pgbench 1.2 README 2000/1/15 Tatsuo Ishii (t-ishii@sra.co.jp) + +$B"#(Bpgbench $B$H$O!)(B + +pgbench $B$O(B TPC-B$B$K;w$?%Y%s%A%^!<%/%F%9%H$r9T$J$&%W%m%0%i%`$G$9!#:#$N$H(B +$B$3$m(B PostgreSQL $B@lMQ$G$9!#(B + +pgbench $B$O(B select/update/insert $B$r4^$`%H%i%s%6%/%7%g%s$r]$H$J$k%F!<%V%k$O%G%U%)(B +$B%k%H$G$O(B 10$BK|%?%W%k$N%G!<%?$r4^$_$^$9!#(B + +$Be$K$"$k(B + + POSTGRESHOME = /usr/local/pgsql + +$B$rI,MW$K1~$8$F=$@5$7!"(Bconfigure;make $B$9$k$@$1$G$9!#(B + +$B"#(Bpgbench $B$N;H$$J}(B + +$B4pK\E*$J;H$$J}$O!"(B + +$ pgbench [$B%G!<%?%Y!<%9L>(B] + +$B$G$9!#%G!<%?%Y!<%9L>$r>JN,$9$k$H!"%f!<%6L>$HF1$8%G!<%?%Y!<%9$r;XDj$7$?(B +$B$b$N$H$_$J$7$^$9!#%G!<%?%Y!<%9$O8e=R$N(B -i $B%*%W%7%g%s$r;H$C$F$"$i$+$8$a(B +$B=i4|2=$7$F$*$/I,MW$,$"$j$^$9!#(B + +pgbench $B$K$O$$$m$$$m$J%*%W%7%g%s$,$"$j$^$9!#(B + +-h $B%[%9%HL>(B PostgreSQL$B$N%G!<%?%Y!<%9%G!<%b%s(B postmaster $B$NF0(B + $B$$$F$$$k%[%9%HL>$r;XDj$7$^$9!#>JN,$9$k$H<+%[%9%H$K(B Unix domain + socket $B$G@\B3$7$^$9!#(B + +-p $B%]!<%HHV9f(B postmaster $B$N;HMQ$9$k%]!<%HHV9f$r;XDj$7$^$9!#>JN,$9$k$H(B 5432 + $B$,;XDj$5$l$?$b$N$H$_$J$7$^$9!#(B + +-c $B%/%i%$%"%s%H?t(B $BF1;~JN,;~$O(B + 1 $B$H$J$j$^$9!#(Bpgbench $B$OF1;~JN,;~$O(B 10 $B$H$J$j$^$9!#(B + +-s $B%9%1!<%j%s%0%U%!%/%?!<(B + + -i $B%*%W%7%g%s$H0l=o$K;HMQ$7$^$9!#(B + $B%9%1!<%j%s%0%U%!%/%?!<$O(B1$B0J>e$N@0?t!#%9%1!<%j%s%0%U%!(B + $B%/%?!<$rJQ$($k$3$H$K$h$j!"%F%9%H$NBP>]$H$J$k%F!<%V%k$N(B + $BBg$-$5$,(B 10$BK|(B x [$B%9%1!<%j%s%0%U%!%/%?!<(B]$B$K$J$j$^$9!#(B + $B%G%U%)%k%H$N%9%1!<%j%s%0%U%!%/%?!<$O(B 1 $B$G$9!#(B + +-v $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B + history $B$N%/%j%"$r9T$J$$$^$9!#(B-v $B$H(B -n $B$r>JN,$9$k$H!"(B + $B:G>.8B$N(B vacuum $B$J$I$r9T$$$^$9!#$9$J$o$A!"(Bhistory $B$N:o=|!"(B + $B$H(B history, branches, history $B$N(B vacuum $B$r9T$$$^$9!#(B + $B$3$l$O!"(Bvacuum $B$N;~4V$r:G>.8B$K$7$J$,$i!"%Q%U%)!<%^%s%9$K(B + $B1F6A$9$k%4%_A]=|$r8z2LE*$K9T$$$^$9!#DL>o$O(B -v $B$H(B -n $B$r(B + $B>JN,$9$k$3$H$r$*$9$9$a$7$^$9!#(B + +-n $B$3$N%*%W%7%g%s$r;XDj$9$k$H!"%Y%s%A%^!<%/3+;OA0$K(B vacuum $B$H(B + history $B$N%/%j%"$r9T$J$$$^$;$s!#(B + +-S TPC-B$B$N%H%i%s%6%/%7%g%s$G$O$J$/!"8!:w$N$_$N%H%i%s%6%/%7%g%s$r(B + $BpJs$,I=<($5$l$^$9!#(B + +$B"#%G!<%?%Y!<%9$N=i4|2=(B + +pgbench $B$G%Y%s%A%^!<%/%F%9%H$r(B] + +$B$3$l$K$h$j0J2<$N%F!<%V%k$,:n$i$l$^$9(B($B%9%1!<%j%s%0%U%!%/%?!<(B == 1 $B$N>l9g(B)$B!#(B + +$B!vCm0U!v(B +$BF1$8L>A0$N%F!<%V%k$,$"$k$H:o=|$5$l$F$7$^$&$N$G$4Cm0U2<$5$$!*!*(B + +$B%F!<%V%kL>(B $B%?%W%k?t(B +------------------------- +branches 1 +tellers 10 +accounts 100000 +history 0 + +$B%9%1!<%j%s%0%U%!%/%?!<$r(B 10,100,1000 $B$J$I$KJQ99$9$k$H!">e5-%?%W%k?t$O(B +$B$=$l$K1~$8$F(B10$BG\!"(B100$BG\!"(B1000$BG\$K$J$j$^$9!#$?$H$($P!"%9%1!<%j%s%0%U%!(B +$B%/%?!<$r(B 10 $B$H$9$k$H!"(B + +$B%F!<%V%kL>(B $B%?%W%k?t(B +------------------------- +branches 10 +tellers 100 +accounts 1000000 +history 0 + +$B$K$J$j$^$9!#(B + +$B"#!V%H%i%s%6%/%7%g%s!W$NDj5A(B + +pgbench $B$G$O!"0J2<$N%7!<%1%s%9$rA4It40N;$7$F(B1$B%H%i%s%6%/%7%g%s$H?t$($F(B +$B$$$^$9!#(B + +(1) begin; + +(2) update accounts set abalance = abalance + :delta where aid = :aid; + $B$3$3$G!"(B:delta$B$O(B1$B$+$i(B1000$B$^$G$NCM$r$l$3$N%H%i%s%6%/%7%g%s$N(B + $BCf$G$OF1$8CM$r;H$$$^$9!#(B + +(3) select abalance from accounts where aid = :aid; + $B$3$3$G$O(B1$B7o$@$18!:w$5$l$^$9!#(B + +(4) update tellers set tbalance = tbalance + :delta where tid = :tid; + $B$3$3$G(B :tid $B$O(B 1$B$+$i(B10$B$N4V$NCM$r$H$kMp?t$G$9!#(B + +(5) update branches set bbalance = bbalance + :delta where bid = :bid; + $B$3$3$G(B :bid $B$O(B 1 $B$+$i(B[$B%9%1%j%s%0%U%!%/%?!<(B]$B$N4V$NCM$rr7o(B + +pgbench $B$O@P0f(B $BC#IW$K$h$C$F=q$+$l$^$7$?!#%i%$%;%s%9>r7o$O(B pgbench.c $B$N(B +$BKAF,$K=q$$$F$"$j$^$9!#$3$N>r7o$r b.oid\g + +CREATE FUNCTION text_sx_eq(text, text) RETURNS bool AS +'select text_soundex($1) = text_soundex($2)' +LANGUAGE 'sql'\g + +CREATE FUNCTION text_sx_lt(text,text) RETURNS bool AS +'select text_soundex($1) < text_soundex($2)' +LANGUAGE 'sql'\g + +CREATE FUNCTION text_sx_gt(text,text) RETURNS bool AS +'select text_soundex($1) > text_soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_le(text,text) RETURNS bool AS +'select text_soundex($1) <= text_soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_ge(text,text) RETURNS bool AS +'select text_soundex($1) >= text_soundex($2)' +LANGUAGE 'sql'; + +CREATE FUNCTION text_sx_ne(text,text) RETURNS bool AS +'select text_soundex($1) <> text_soundex($2)' +LANGUAGE 'sql'; + +DROP OPERATOR #= (text,text)\g + +CREATE OPERATOR #= (leftarg=text, rightarg=text, procedure=text_sx_eq, +commutator=text_sx_eq)\g + +SELECT * +FROM s +WHERE text_sx_eq(nm,'john')\g + +SELECT * +from s +where s.nm #= 'john'; + diff --git a/contrib/spi/README.spi b/contrib/spi/README.spi new file mode 100644 index 0000000000..65868f0fc7 --- /dev/null +++ b/contrib/spi/README.spi @@ -0,0 +1,104 @@ + +Here are general trigger functions provided as workable examples +of using SPI and triggers. "General" means that functions may be +used for defining triggers for any tables but you have to specify +table/field names (as described below) while creating a trigger. + +1. refint.c - functions for implementing referential integrity. + +check_primary_key () is to used for foreign keys of a table. + + You are to create trigger (BEFORE INSERT OR UPDATE) using this +function on a table referencing another table. You are to specify +as function arguments: triggered table column names which correspond +to foreign key, referenced table name and column names in referenced +table which correspond to primary/unique key. + You may create as many triggers as you need - one trigger for +one reference. + +check_foreign_key () is to used for primary/unique keys of a table. + + You are to create trigger (BEFORE DELETE OR UPDATE) using this +function on a table referenced by another table(s). You are to specify +as function arguments: number of references for which function has to +performe checking, action if referencing key found ('cascade' - to delete +corresponding foreign key, 'restrict' - to abort transaction if foreign keys +exist, 'setnull' - to set foreign key referencing primary/unique key +being deleted to null), triggered table column names which correspond +to primary/unique key, referencing table name and column names corresponding +to foreign key (, ... - as many referencing tables/keys as specified +by first argument). + Note, that NOT NULL constraint and unique index have to be defined by +youself. + + There are examples in refint.example and regression tests +(sql/triggers.sql). + + To CREATE FUNCTIONs use refint.sql (will be made by gmake from +refint.source). + + +2. timetravel.c - functions for implementing time travel feature. + + Old internally supported time-travel (TT) used insert/delete +transaction commit times. To get the same feature using triggers +you are to add to a table two columns of abstime type to store +date when a tuple was inserted (start_date) and changed/deleted +(stop_date): + +CREATE TABLE XXX ( + ... ... + date_on abstime default currabstime(), + date_off abstime default 'infinity' + ... ... +); + +- so, tuples being inserted with NULLs in date_on/date_off will get +_current_date_ in date_on (name of start_date column in XXX) and INFINITY in +date_off (name of stop_date column in XXX). + + Tuples with stop_date equal INFINITY are "valid now": when trigger will +be fired for UPDATE/DELETE of a tuple with stop_date NOT equal INFINITY then +this tuple will not be changed/deleted! + + If stop_date equal INFINITY then on + +UPDATE: only stop_date in tuple being updated will be changed to current +date and new tuple with new data (coming from SET ... in UPDATE) will be +inserted. Start_date in this new tuple will be setted to current date and +stop_date - to INFINITY. + +DELETE: new tuple will be inserted with stop_date setted to current date +(and with the same data in other columns as in tuple being deleted). + + NOTE: +1. To get tuples "valid now" you are to add _stop_date_ = 'infinity' + to WHERE. Internally supported TT allowed to avoid this... + Fixed rewriting RULEs could help here... + As work arround you may use VIEWs... +2. You can't change start/stop date columns with UPDATE! + Use set_timetravel (below) if you need in this. + + FUNCTIONs: + +timetravel() is general trigger function. + + You are to create trigger BEFORE (!!!) UPDATE OR DELETE using this +function on a time-traveled table. You are to specify two arguments: name of +start_date column and name of stop_date column in triggered table. + +currabstime() may be used in DEFAULT for start_date column to get +current date. + +set_timetravel() allows you turn time-travel ON/OFF for a table: + + set_timetravel('XXX', 1) will turn TT ON for table XXX (and report +old status). + set_timetravel('XXX', 0) will turn TT OFF for table XXX (-"-). + +Turning TT OFF allows you do with a table ALL what you want. + + There is example in timetravel.example. + + To CREATE FUNCTIONs use timetravel.sql (will be made by gmake from +timetravel.source). diff --git a/contrib/spi/new_example.example b/contrib/spi/new_example.example new file mode 100644 index 0000000000..0204907894 --- /dev/null +++ b/contrib/spi/new_example.example @@ -0,0 +1,68 @@ +--Column ID of table A is primary key: + +CREATE TABLE A ( + ID int4 not null, + id1 int4 not null, +primary key (ID,ID1) +); + +--Columns REFB of table B and REFC of C are foreign keys referenting ID of A: + +CREATE TABLE B ( + REFB int4, + REFB1 INT4 +); +CREATE INDEX BI ON B (REFB); + +CREATE TABLE C ( + REFC int4, + REFC1 int4 +); +CREATE INDEX CI ON C (REFC); + +--Trigger for table A: + +CREATE TRIGGER AT BEFORE DELETE ON A FOR EACH ROW +EXECUTE PROCEDURE +check_foreign_key (2, 'cascade', 'ID','id1', 'B', 'REFB','REFB1', 'C', 'REFC','REFC1'); + + +CREATE TRIGGER AT1 AFTER UPDATE ON A FOR EACH ROW +EXECUTE PROCEDURE +check_foreign_key (2, 'cascade', 'ID','id1', 'B', 'REFB','REFB1', 'C', 'REFC','REFC1'); + + +CREATE TRIGGER BT BEFORE INSERT OR UPDATE ON B FOR EACH ROW +EXECUTE PROCEDURE +check_primary_key ('REFB','REFB1', 'A', 'ID','ID1'); + +CREATE TRIGGER CT BEFORE INSERT OR UPDATE ON C FOR EACH ROW +EXECUTE PROCEDURE +check_primary_key ('REFC','REFC1', 'A', 'ID','ID1'); + + + +-- Now try + +INSERT INTO A VALUES (10,10); +INSERT INTO A VALUES (20,20); +INSERT INTO A VALUES (30,30); +INSERT INTO A VALUES (40,41); +INSERT INTO A VALUES (50,50); + +INSERT INTO B VALUES (1); -- invalid reference +INSERT INTO B VALUES (10,10); +INSERT INTO B VALUES (30,30); +INSERT INTO B VALUES (30,30); + +INSERT INTO C VALUES (11); -- invalid reference +INSERT INTO C VALUES (20,20); +INSERT INTO C VALUES (20,21); +INSERT INTO C VALUES (30,30); + +-- now update work well +update A set ID = 100 , ID1 = 199 where ID=30 ; + +SELECT * FROM A; +SELECT * FROM B; +SELECT * FROM C; diff --git a/contrib/string/README.string_io b/contrib/string/README.string_io new file mode 100644 index 0000000000..4b4d10166f --- /dev/null +++ b/contrib/string/README.string_io @@ -0,0 +1,23 @@ +String io module for postgresql. +Copyright (C) 1999, Massimo Dal Zotto + +This software is distributed under the GNU General Public License +either version 2, or (at your option) any later version. + + +These output functions can be used as substitution of the standard text +output functions to get the value of text fields printed in the format +used for C strings. This allows the output of queries or the exported +files to be processed more easily using standard unix filter programs +like perl or awk. + +If you use the standard functions instead you could find a single tuple +splitted into many lines and the tabs embedded in the values could be +confused with those used as field delimters. + +My function translates all non-printing characters into corresponding +esacape sequences as defined by the C syntax. All you need to reconstruct +the exact value in your application is a corresponding unescape function +like the string_input defined in the source code. + +Massimo Dal Zotto diff --git a/contrib/userlock/README.user_locks b/contrib/userlock/README.user_locks new file mode 100644 index 0000000000..4c923a4657 --- /dev/null +++ b/contrib/userlock/README.user_locks @@ -0,0 +1,55 @@ +User locks, by Massimo Dal Zotto +Copyright (C) 1999, Massimo Dal Zotto + +This software is distributed under the GNU General Public License +either version 2, or (at your option) any later version. + + +This loadable module, together with my user-lock.patch applied to the +backend, provides support for user-level long-term cooperative locks. +For example one can write: + + select some_fields, user_write_lock_oid(oid) from table where id='key'; + +Now if the returned user_write_lock_oid field is 1 you have acquired an +user lock on the oid of the selected tuple and can now do some long operation +on it, like let the data being edited by the user. +If it is 0 it means that the lock has been already acquired by some other +process and you should not use that item until the other has finished. +Note that in this case the query returns 0 immediately without waiting on +the lock. This is good if the lock is held for long time. +After you have finished your work on that item you can do: + + update table set some_fields where id='key'; + select user_write_unlock_oid(oid) from table where id='key'; + +You can also ignore the failure and go ahead but this could produce conflicts +or inconsistent data in your application. User locks require a cooperative +behavior between users. User locks don't interfere with the normal locks +used by postgres for transaction processing. + +This could also be done by setting a flag in the record itself but in +this case you have the overhead of the updates to the records and there +could be some locks not released if the backend or the application crashes +before resetting the lock flag. +It could also be done with a begin/end block but in this case the entire +table would be locked by postgres and it is not acceptable to do this for +a long period because other transactions would block completely. + +The generic user locks use two values, group and id, to identify a lock, +which correspond to ip_posid and ip_blkid of an ItemPointerData. +Group is a 16 bit value while id is a 32 bit integer which could also be +an oid. The oid user lock functions, which take only an oid as argument, +use a group equal to 0. + +The meaning of group and id is defined by the application. The user +lock code just takes two numbers and tells you if the corresponding +entity has been succesfully locked. What this mean is up to you. + +My succestion is that you use the group to identify an area of your +application and the id to identify an object in this area. +Or you can just lock the oid of the tuples which are by definition unique. + +Note also that a process can acquire more than one lock on the same entity +and it must release the lock the corresponding number of times. This can +be done calling the unlock funtion until it returns 0. diff --git a/contrib/vacuumlo/README.vacuumlo b/contrib/vacuumlo/README.vacuumlo new file mode 100644 index 0000000000..2eeaa3988c --- /dev/null +++ b/contrib/vacuumlo/README.vacuumlo @@ -0,0 +1,38 @@ +$Header: /cvsroot/pgsql/contrib/vacuumlo/Attic/README.vacuumlo,v 1.1 2000/06/19 14:02:16 momjian Exp $ + +This is a simple utility that will remove any orphaned large objects out of a +PostgreSQL database. + +Compiling +-------- + +Simply run make. A single executable "vacuumlo" is created. + +Useage +------ + +vacuumlo [-v] database [db2 ... dbn] + +The -v flag outputs some progress messages to stdout. + +Method +------ + +First, it builds a temporary table which contains all of the oid's of the +large objects in that database. + +It then scans through any columns in the database that are of type 'oid', and +removes any entries from the temporary table. + +Finally, it runs through the first table, and removes from the second table, any +oid's it finds. What is left are the orphans, and these are removed. + +I decided to place this in contrib as it needs further testing, but hopefully, +this (or a variant of it) would make it into the backed as a "vacuum lo" command +in a later release. + +Peter Mount +http://www.retep.org.uk +March 21 1999 + +Committed April 10 1999 Peter