+++ /dev/null
-
-
-
The POSTGRES95 User Manual - ADMINISTERING POSTGRES
-
-
-
-
-
-
-
-
15. ADMINISTERING POSTGRES
-
- In this section, we will discuss aspects of POSTGRES
- that are of interest to those who make extensive use of
- POSTGRES, or who are the site administrator for a group
- of POSTGRES users.
-
-
15.1. Frequent Tasks
- Here we will briefly discuss some procedures that you
- should be familiar with in managing any POSTGRES
- installation.
-
-
15.1.1. Starting the Postmaster
- If you did not install POSTGRES exactly as described in
- the installation instructions, you may have to perform
- some additional steps before starting the postmaster
- process.
-
Even if you were not the person who installed POSTGRES,
- you should understand the installation
- instructions. The installation instructions explain
- some important issues with respect to where POSTGRES
- places some important files, proper settings for
- environment variables, etc. that may vary from one
- version of POSTGRES to another.
-
You must start the postmaster process with the userid
- that owns the installed database files. In most
- cases, if you have followed the installation
- instructions, this will be the user "postgres". If
- you do not start the postmaster with the right userid,
- the backend servers that are started by the
- postmaster will not be able to read the data.
-
Make sure that /usr/local/postgres95/bin
is in your
- shell command path, because the postmaster will use
- your
PATH to locate POSTGRES commands.
-
Remember to set the environment variable PGDATA to
- the directory where the POSTGRES databases are
- installed. (This variable is more fully explained
- in the POSTGRES installation instructions.)
-
If you do start the postmaster using non-standard
- options, such as a different TCP port number, remember
- to tell all users so that they can set their
-
PGPORT environment variable correctly.
-
-
-
15.1.2. Shutting Down the Postmaster
- If you need to halt the postmaster process, you can use
- the UNIX kill(1) command. Some people habitually use
- the -9 or -KILL option; this should never be necessary
- and we do not recommend that you do this, as the postmaster
- will be unable to free its various shared
- resources, its child processes will be unable to exit
- gracefully, etc.
-
-
15.1.3. Adding and Removing Users
- The createuser and destroyuser commands enable and disable
- access to POSTGRES by specific users on the host
- system.
-
-
15.1.4. Periodic Upkeep
- The vacuum command should be run on each database periodically.
- This command processes deleted instances
[9]
- and, more importantly, updates the system statistics
- concerning the size of each class. If these statistics
- are permitted to become out-of-date and inaccurate, the
- POSTGRES query optimizer may make extremely poor decisions
- with respect to query evaluation strategies.
- Therefore, we recommend running vacuum every night or
- so (perhaps in a script that is executed by the UNIX
- cron(1) or at(1) commands).
- Do frequent backups. That is, you should either back
- up your database directories using the POSTGRES copy
- command and/or the UNIX dump(1) or tar(1) commands.
- You may think, "Why am I backing up my database? What
- about crash recovery?" One side effect of the POSTGRES
- "no overwrite" storage manager is that it is also a "no
- log" storage manager. That is, the database log stores
- only abort/commit data, and this is not enough information
- to recover the database if the storage medium
- (disk) or the database files are corrupted! In other
- words, if a disk block goes bad or POSTGRES happens to
- corrupt a database file, you cannot recover that file.
- This can be disastrous if the file is one of the shared
- catalogs, such as pg_database.
-
-
15.1.5. Tuning
- Once your users start to load a significant amount of
- data, you will typically run into performance problems.
- POSTGRES is not the fastest DBMS in the world, but many
- of the worst problems encountered by users are due to
- their lack of experience with any DBMS. Some general
- tips include:
-
Define indices over attributes that are commonly
- used for qualifications. For example, if you
- often execute queries of the form
-
-
SELECT * from EMP where salary < 5000
-
- then a B-tree index on the salary attribute will
- probably be useful. If scans involving equality
- are more common, as in
-
-
SELECT * from EMP where salary = 5000
-
- then you should consider defining a hash index
- on salary. You can define both, though it will
- use more disk space and may slow down updates a
- bit. Scans using indices are much faster than
- sequential scans of the entire class.
-
Run the vacuum command a lot. This command
- updates the statistics that the query optimizer
- uses to make intelligent decisions; if the
- statistics are inaccurate, the system will make
- inordinately stupid decisions with respect to
- the way it joins and scans classes.
-
When specifying query qualfications (i.e., the
- where part of the query), try to ensure that a
- clause involving a constant can be turned into
- one of the form range_variable operator constant, e.g.,
-
-
- The POSTGRES query optimizer will only use an
- index with a constant qualification of this
- form. It doesn't hurt to write the clause as
-
-
- if the operator (in this case, =) has a commutator
- operator defined so that POSTGRES can
- rewrite the query into the desired form. However,
- if such an operator does not exist, POSTGRES
- will never consider the use of an index.
-
When joining several classes together in one
- query, try to write the join clauses in a
- "chained" form, e.g.,
-
-
where A.a = B.b and B.b = C.c and ...
-
- Notice that relatively few clauses refer to a
- given class and attribute; the clauses form a
- linear sequence connecting the attributes, like
- links in a chain. This is preferable to a query
- written in a "star" form, such as
-
-
where A.a = B.b and A.a = C.c and ...
-
- Here, many clauses refer to the same class and
- attribute (in this case, A.a). When presented
- with a query of this form, the POSTGRES query
- optimizer will tend to consider far more choices
- than it should and may run out of memory.
-
If you are really desperate to see what query
- plans look like, you can run the postmaster with
- the -d option and then run monitor with the -t
- option. The format in which query plans will be
- printed is hard to read but you should be able
- to tell whether any index scans are being performed.
-
-
-
15.2. Infrequent Tasks
-
- At some time or another, every POSTGRES site
- administrator has to perform all of the following actions.
-
-15.2.1. Cleaning Up After Crashes
- The postgres server and the postmaster run as two
- different processes. They may crash separately or
- together. The housekeeping procedures required to fix
- one kind of crash are different from those required to
- fix the other.
- The message you will usually see when the backend
- server crashes is:
-
-
FATAL: no response from backend: detected in ...
-
- This generally means one of two things: there is a bug
- in the POSTGRES server, or there is a bug in some user
- code that has been dynamically loaded into POSTGRES.
- You should be able to restart your application and
- resume processing, but there are some considerations:
-
POSTGRES usually dumps a core file (a snapshot
- of process memory used for debugging) in the
- database directory
-
/usr/local/postgres95/data/base/<database>/core
-
- on the server machine. If you don't want to try
- to debug the problem or produce a stack trace to
- report the bug to someone else, you can delete
- this file (which is probably around 10MB).
-
When one backend crashes in an uncontrolled way
- (i.e., without calling its built-in cleanup
- routines), the postmaster will detect this situation,
- kill all running servers and reinitialize
- the state shared among all backends (e.g., the
- shared buffer pool and locks). If your server
- crashed, you will get the "no response" message
- shown above. If your server was killed because
- someone else's server crashed, you will see the
- following message:
-
-
I have been signalled by the postmaster.
- Some backend process has died unexpectedly and possibly
- corrupted shared memory. The current transaction was
- aborted, and I am going to exit. Please resend the
- last query. -- The postgres backend
-
-
Sometimes shared state is not completely cleaned
- up. Frontend applications may see errors of the
- form:
-
-
WARN: cannot write block 34 of myclass [mydb] blind
-
- In this case, you should kill the postmaster and
-
When the system crashes while updating the system
- catalogs (e.g., when you are creating a
- class, defining an index, retrieving into a
- class, etc.) the B-tree indices defined on the
- catalogs are sometimes corrupted. The general
- (and non-unique) symptom is that all queries
- stop working. If you have tried all of the
- above steps and nothing else seems to work, try
- using the reindexdb command. If reindexdb succeeds
- but things still don't work, you have
- another problem; if it fails, the system catalogs
- themselves were almost certainly corrupted
- and you will have to go back to your backups.
-
- The postmaster does not usually crash (it doesn't do
- very much except start servers) but it does happen on
- occasion. In addition, there are a few cases where it
- encounters problems during the reinitialization of
- shared resources. Specifically, there are race conditions
- where the operating system lets the postmaster
- free shared resources but then will not permit it to
- reallocate the same amount of shared resources (even
- when there is no contention).
- You will typically have to run the ipcclean command if
- system errors cause the postmaster to crash. If this
- happens, you may find (using the UNIX ipcs(1) command)
- that the "postgres" user has shared memory and/or
- semaphores allocated even though no postmaster process
- is running. In this case, you should run ipcclean as
- the "postgres" user in order to deallocate these
- resources. Be warned that all such resources owned by
- the "postgres" user will be deallocated. If you have
- multiple postmaster processes running on the same
- machine, you should kill all of them before running
- ipcclean (otherwise, they will crash on their own when
- their shared resources are suddenly deallocated).
-
-
15.2.2. Moving Database Directories
- By default, all POSTGRES databases are stored in
- separate subdirectories under
-
/usr/local/postgres95/data/base
.
[10] At some point, you
- may find that you wish to move one or more databases to
- another location (e.g., to a filesystem with more free
- space).
- If you wish to move all of your databases to the new
- location, you can simply:
-
Copy the entire data directory to the new location
- (making sure that the new files are owned by user
- "postgres").
-
-
% cp -rp /usr/local/postgres95/data /new/place/data
-
Reset your PGDATA environment variable (as described
- earlier in this manual and in the installation
- instructions).
-
- % setenv PGDATA /new/place/data
-
- # using sh, ksh or bash...
- % PGDATA=/new/place/data; export PGDATA
-
-
Restart the postmaster.
-
-
After you run some queries and are sure that the
- newly-moved database works, you can remove the old
- data directory.
-
% rm -rf /usr/local/postgres95/data
-
- To install a single database in an alternate directory
- while leaving all other databases in place, do the following:
-
Create the database (if it doesn't already exist)
- using the createdb command. In the following steps
- we will assume the database is named foo.
-
Copy the directory
- /usr/local/postgres95/data/base/foo
and its contents
- to its ultimate destination. It should still be
- owned by the "postgres" user.
-
-
% cp -rp /usr/local/postgres95/data/base/foo /new/place/foo
-
-
Remove the directory
- /usr/local/postgres95/data/base/foo
:
-
-
% rm -rf /usr/local/postgres95/data/base/foo
-
-
Make a symbolic link from
- /usr/local/postgres95/data/base
to the new directory:
-
-
% ln -s /new/place/foo /usr/local/postgres95/data/base/foo
-
-
Restart the postmaster.
-
-
15.2.3. Updating Databases
- POSTGRES is a research system. In general, POSTGRES
- may not retain the same binary format for the storage
- of databases from release to release. Therefore, when
- you update your POSTGRES software, you will probably
- have to modify your databases as well. This is a common
- occurrence with commercial database systems as
- well; unfortunately, unlike commercial systems, POSTGRES
- does not come with user-friendly utilities to make
- your life easier when these updates occur.
- In general, you must do the following to update your
- databases to a new software release:
-
Extensions (such as user-defined types, functions,
- aggregates, etc.) must be reloaded by re-executing
- the SQL CREATE commands. See Appendix A for more
- details.
-
Data must be dumped from the old classes into ASCII
- files (using the COPY command), the new classes created
- in the new database (using the CREATE TABLE
- command), and the data reloaded from the ASCII files.
-
Rules and views must also be reloaded by
- reexecuting the various CREATE commands.
-
- You should give any new release a "trial period"; in
- particular, do not delete the old database until you
- are satisfied that there are no compatibility problems
- with the new software. For example, you do not want to
- discover that a bug in a type's "input" (conversion
- from ASCII) and "output" (conversion to ASCII) routines
- prevents you from reloading your data after you have
- destroyed your old databases! (This should be standard
- procedure when updating any software package, but some
- people try to economize on disk space without applying
- enough foresight.)
-
-
15.3. Database Security
-
- Most sites that use POSTGRES are educational or
- research institutions and do not pay much attention to
- security in their POSTGRES installations. If desired,
- one can install POSTGRES with additional security
- features. Naturally, such features come with additional
- administrative overhead that must be dealt with.
-
-
15.3.1. Kerberos
- POSTGRES can be configured to use the MIT Kerberos network
- authentication system. This prevents outside
- users from connecting to your databases over the network
- without the correct authentication information.
-
15.4. Querying the System Catalogs
- As an administrator (or sometimes as a plain user), you
- want to find out what extensions have been added to a
- given database. The queries listed below are "canned"
- queries that you can run on any database to get simple
- answers. Before executing any of the queries below, be
- sure to execute the POSTGRES vacuum command. (The
- queries will run much more quickly that way.) Also,
- note that these queries are also listed in
-
/usr/local/postgres95/tutorial/syscat.sql
-
- so use cut-and-paste (or the \i command) instead of
- doing a lot of typing.
- This query prints the names of all database adminstrators
- and the name of their database(s).
-
SELECT usename, datname
- FROM pg_user, pg_database
- WHERE usesysid = int2in(int4out(datdba))
- ORDER BY usename, datname;
-
- This query lists all user-defined classes in the
- database.
- FROM pg_class
- WHERE relkind = 'r' -- not indices
- and relname !~ '^pg_' -- not catalogs
- and relname !~ '^Inv' -- not large objects
- ORDER BY relname;
-
- This query lists all simple indices (i.e., those that
- are not defined over a function of several attributes).
-
SELECT bc.relname AS class_name,
- ic.relname AS index_name,
- a.attname
- FROM pg_class bc, -- base class
- pg_class ic, -- index class
- pg_index i,
- pg_attribute a -- att in base
- WHERE i.indrelid = bc.oid
- and i.indexrelid = ic.oid
- and i.indkey[0] = a.attnum
- and a.attrelid = bc.oid
- and i.indproc = '0'::oid -- no functional indices
- ORDER BY class_name, index_name, attname;
-
- This query prints a report of the user-defined
- attributes and their types for all user-defined classes
- in the database.
-
SELECT c.relname, a.attname, t.typname
- FROM pg_class c, pg_attribute a, pg_type t
- WHERE c.relkind = 'r' -- no indices
- and c.relname !~ '^pg_' -- no catalogs
- and c.relname !~ '^Inv' -- no large objects
- and a.attnum > 0 -- no system att's
- and a.attrelid = c.oid
- and a.atttypid = t.oid
- ORDER BY relname, attname;
-
- This query lists all user-defined base types (not
- including array types).
-
SELECT u.usename, t.typname
- FROM pg_type t, pg_user u
- WHERE u.usesysid = int2in(int4out(t.typowner))
- and t.typrelid = '0'::oid -- no complex types
- and t.typelem = '0'::oid -- no arrays
- and u.usename <> 'postgres'
- ORDER BY usename, typname;
-
- This query lists all left-unary (post-fix) operators.
-
SELECT o.oprname AS left_unary,
- right.typname AS operand,
- result.typname AS return_type
- FROM pg_operator o, pg_type right, pg_type result
- WHERE o.oprkind = 'l' -- left unary
- and o.oprright = right.oid
- and o.oprresult = result.oid
- ORDER BY operand;
-
- This query lists all right-unary (pre-fix) operators.
-
SELECT o.oprname AS right_unary,
- left.typname AS operand,
- result.typname AS return_type
- FROM pg_operator o, pg_type left, pg_type result
- WHERE o.oprkind = 'r' -- right unary
- and o.oprleft = left.oid
- and o.oprresult = result.oid
- ORDER BY operand;
-
- This query lists all binary operators.
-
SELECT o.oprname AS binary_op,
- left.typname AS left_opr,
- right.typname AS right_opr,
- result.typname AS return_type
- FROM pg_operator o, pg_type left, pg_type right, pg_type result
- WHERE o.oprkind = 'b' -- binary
- and o.oprleft = left.oid
- and o.oprright = right.oid
- and o.oprresult = result.oid
- ORDER BY left_opr, right_opr;
-
- This query returns the name, number of arguments
- (parameters) and return type of all user-defined C
- functions. The same query can be used to find all
- built-in C functions if you change the "C" to "internal",
- or all SQL functions if you change the "C" to
- "sql".
-
SELECT p.proname, p.pronargs, t.typname
- FROM pg_proc p, pg_language l, pg_type t
- WHERE p.prolang = l.oid
- and p.prorettype = t.oid
- and l.lanname = 'c'
- ORDER BY proname;
-
- This query lists all of the aggregate functions that
- have been installed and the types to which they can be
- applied. count is not included because it can take any
- type as its argument.
-
SELECT a.aggname, t.typname
- FROM pg_aggregate a, pg_type t
- WHERE a.aggbasetype = t.oid
- ORDER BY aggname, typname;
-
- This query lists all of the operator classes that can
- be used with each access method as well as the operators
- that can be used with the respective operator
- classes.
-
SELECT am.amname, opc.opcname, opr.oprname
- FROM pg_am am, pg_amop amop, pg_opclass opc, pg_operator opr
- WHERE amop.amopid = am.oid
- and amop.amopclaid = opc.oid
- and amop.amopopr = opr.oid
- ORDER BY amname, opcname, oprname;
-
-
-
-This may mean different things depending on the archive
-mode with which each class has been created. However, the
-current implementation of the vacuum command does not perform any compaction or clustering of data. Therefore, the
-UNIX files which store each POSTGRES class never shrink and
-the space "reclaimed" by vacuum is never actually reused.
-
-
-Data for certain classes may stored elsewhere if a
-non-standard storage manager was specified when they were
-created. Use of non-standard storage managers is an experimental feature that is not supported outside of Berkeley.
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - EXTENDING SQL: AN OVERVIEW
-
-
-
-
-
-
-
-
-
6. EXTENDING SQL: AN OVERVIEW
-
- In the sections that follow, we will discuss how you
- can extend the POSTGRES SQL query language by adding:
-
functions
-
types
-
operators
-
aggregates
-
- POSTGRES is extensible because its operation is
- catalog-driven. If you are familiar with standard
- relational systems, you know that they store information
- about databases, tables, columns, etc., in what are
- commonly known as system catalogs. (Some systems call
- this the data dictionary). The catalogs appear to the
- user as classes, like any other, but the DBMS stores
- its internal bookkeeping in them. One key difference
- between POSTGRES and standard relational systems is
- that POSTGRES stores much more information in its
- catalogs -- not only information about tables and columns,
- but also information about its types, functions, access
- methods, and so on. These classes can be modified by
- the user, and since POSTGRES bases its internal operation
- on these classes, this means that POSTGRES can be
- extended by users. By comparison, conventional
- database systems can only be extended by changing hardcoded
- procedures within the DBMS or by loading modules
- specially-written by the DBMS vendor.
- POSTGRES is also unlike most other data managers in
- that the server can incorporate user-written code into
- itself through dynamic loading. That is, the user can
- specify an object code file (e.g., a compiled .o file
- or shared library) that implements a new type or function
- and POSTGRES will load it as required. Code written
- in SQL are even more trivial to add to the server.
- This ability to modify its operation "on the fly" makes
- POSTGRES uniquely suited for rapid prototyping of new
- applications and storage structures.
-
- The POSTGRES type system can be broken down in several
- ways.
- Types are divided into base types and composite types.
- Base types are those, like int4
, that are implemented
- in a language such as C. They generally correspond to
- what are often known as "abstract data types"; POSTGRES
- can only operate on such types through methods provided
- by the user and only understands the behavior of such
- types to the extent that the user describes them.
- Composite types are created whenever the user creates a
- class. EMP is an example of a composite type.
- POSTGRES stores these types in only one way (within the
- file that stores all instances of the class) but the
- user can "look inside" at the attributes of these types
- from the query language and optimize their retrieval by
- (for example) defining indices on the attributes.
- POSTGRES base types are further divided into built-in
- types and user-defined types. Built-in types (like
- int4
) are those that are compiled into the system.
- User-defined types are those created by the user in the
- manner to be described below.
-
- Having introduced the basic extensibility concepts, we
- can now take a look at how the catalogs are actually
- laid out. You can skip this section for now, but some
- later sections will be incomprehensible without the
- information given here, so mark this page for later
- reference.
- All system catalogs have names that begin with pg_
.
- The following classes contain information that may be
- useful to the end user. (There are many other system
- catalogs, but there should rarely be a reason to query
- them directly.)
-
-
-
-
catalog name | description |
-
-
-
pg_database | databases |
-
-
-
pg_attribute | class attributes |
-
-
-
pg_index | secondary indices |
-
-
-
pg_proc | procedures (both C and SQL) |
-
-
-
pg_type | types (both base and complex) |
-
-
-
pg_operator | operators |
-
-
-
pg_aggregate | aggregates and aggregate functions |
-
-
-
pg_am | access methods |
-
-
-
pg_amop | access method operators |
-
-
-
pg_amproc | access method support functions |
-
-
-
pg_opclass | access method operator classes |
-
-
-
-
-
- ALT="Figure 3. The major POSTGRES system catalogs">
- The Reference Manual gives a more detailed explanation
- of these catalogs and their attributes. However, Figure 3
- shows the major entities and their relationships
- in the system catalogs. (Attributes that do not refer
- to other entities are not shown unless they are part of
- a primary key.)
- This diagram is more or less incomprehensible until you
- actually start looking at the contents of the catalogs
- and see how they relate to each other. For now, the
- main things to take away from this diagram are as follows:
-
-
In several of the sections that follow, we will
- present various join queries on the system
- catalogs that display information we need to extend
- the system. Looking at this diagram should make
- some of these join queries (which are often
- three- or four-way joins) more understandable,
- because you will be able to see that the
- attributes used in the queries form foreign keys
- in other classes.
-
Many different features (classes, attributes,
- functions, types, access methods, etc.) are
- tightly integrated in this schema. A simple
- create command may modify many of these catalogs.
-
Types and procedures [6]
- are central to the schema.
- Nearly every catalog contains some reference to
- instances in one or both of these classes. For
- example, POSTGRES frequently uses type
- signatures (e.g., of functions and operators) to
- identify unique instances of other catalogs.
-
There are many attributes and relationships that
- have obvious meanings, but there are many
- (particularly those that have to do with access
- methods) that do not. The relationships between
- pg_am, pg_amop, pg_amproc, pg_operator
and
- pg_opclass
are particularly hard to understand
- and will be described in depth (in the section
- on interfacing types and operators to indices)
- after we have discussed basic extensions.
-
-
-
6. We use the words
procedure and
function more or less
-interchangably.
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - Introduction
-
-
-
-
-[ Previous ]
-
-
-
1. INTRODUCTION
-
- This document is the user manual for the
- database management system developed at the University
- of California at Berkeley. POSTGRES95 is based on
- POSTGRES release 4.2. The POSTGRES project,
- led by Professor Michael Stonebraker, has been sponsored by the
- Defense Advanced Research Projects Agency (DARPA), the
- Army Research Office (ARO), the National Science
- Foundation (NSF), and ESL, Inc.
-
1.1. What is POSTGRES?
- Traditional relational database management systems
- (DBMSs) support a data model consisting of a collection
- of named relations, containing attributes of a specific
- type. In current commercial systems, possible types
- include floating point numbers, integers, character
- strings, money, and dates. It is commonly recognized
- that this model is inadequate for future data
- processing applications.
- The relational model successfully replaced previous
- models in part because of its "Spartan simplicity".
- However, as mentioned, this simplicity often makes the
- implementation of certain applications very difficult
- to implement. POSTGRES offers substantial additional
- power by incorporating the following four additional
- basic constructs in such a way that users can easily
- extend the system:
- inheritance
- types
- functions
- In addition, POSTGRES supports a powerful production
- rule system.
-
- Implementation of the POSTGRES DBMS began in 1986. The
- initial concepts for the system were presented in
-
[STON86] and the definition of the initial data model
- appeared in
[ROWE87]. The design of the rule system at
- that time was described in
[STON87a]. The rationale
- and architecture of the storage manager were detailed
- POSTGRES has undergone several major releases since
- then. The first "demoware" system became operational
- in 1987 and was shown at the 1988 ACM-SIGMOD
- Conference. We released Version 1, described in
[STON90a],
- to a few external users in June 1989. In response to a
- critique of the first rule system
[STON89], the rule
- system was redesigned
[STON90b] and Version 2 was
- released in June 1990 with the new rule system.
- Version 3 appeared in 1991 and added support for multiple
- storage managers, an improved query executor, and a
- rewritten rewrite rule system. For the most part,
- releases since then have focused on portability and
- reliability.
- POSTGRES has been used to implement many different
- research and production applications. These include: a
- financial data analysis system, a jet engine
- performance monitoring package, an asteroid tracking
- database, a medical information database, and several
- geographic information systems. POSTGRES has also been
- used as an educational tool at several universities.
- the code and commercialized it.
- POSTGRES became the primary data manager for the
- Furthermore, the size of the external user community
- nearly doubled during 1993. It became increasingly
- obvious that maintenance of the prototype code and
- support was taking up large amounts of time that should
- have been devoted to database research. In an effort
- to reduce this support burden, the project officially
- ended with Version 4.2.
-
- POSTGRES95 is a derivative of the last official release
- of POSTGRES (version 4.2). The code is now completely
- ANSI C and the code size has been trimmed by 25%. There
- are a lot of internal changes that improve performance
- and code maintainability. POSTGRES95 runs about 30-50%
- faster on the Wisconsin Benchmark compared to v4.2.
- Apart from bug fixes, these are the major enhancements:
-
The query language POSTQUEL has been replaced with
- SQL (implemented in the server). We do not support
- subqueries (which can be imitated with user defined
- SQL functions) at the moment. Aggregates have been
- re-implemented. We also added support for GROUP BY.
- The libpq interface is still available for C
- programs.
-
In addition to the monitor program, we provide a new
- program (psql) which supports GNU readline.
-
We added a new front-end library, libpgtcl, that
- supports Tcl-based clients. A sample shell,
- pgtclsh, provides new Tcl commands to interface tcl
- programs with the POSTGRES95 backend.
-
The large object interface has been overhauled. We
- kept Inversion large objects as the only mechanism
- for storing large objects. (This is not to be
- confused with the Inversion file system which has been
- removed.)
-
The instance-level rule system has been removed.
-
Rules are still available as rewrite rules.
-
A short tutorial introducing regular SQL features as
- well as those of ours is distributed with the source
- code.
-
GNU make (instead of BSD make) is used for the
- build. Also, POSTGRES95 can be compiled with an
- unpatched gcc (data alignment of doubles has been
- fixed).
-
- POSTGRES95 is available free of charge. This manual
- describes version 1.0 of POSTGRES95. The authors have
- compiled and tested POSTGRES95 on the following
- platforms:
-
-
-
-
Architecture |
-
Processor |
-
Operating System |
-
-
-
DECstation 3000 |
-
Alpha AXP |
-
OSF/1 2.1, 3.0, 3.2 |
-
-
-
DECstation 5000 |
-
MIPS |
-
ULTRIX 4.4 |
-
-
-
Sun4 |
-
SPARC |
-
SunOS 4.1.3, 4.1.3_U1; Solaris 2.4 |
-
-
-
H-P 9000/700 and 800 |
-
PA-RISC |
-
HP-UX 9.00, 9.01, 9.03 |
-
-
-
Intel |
-
X86 |
-
Linux 1.2.8, ELF |
-
-
- From now on, We will use POSTGRES to mean POSTGRES95.
- The first part of this manual goes over some basic sys-
- tem concepts and procedures for starting the POSTGRES
- system. We then turn to a tutorial overview of the
- POSTGRES data model and SQL query language, introducing
- a few of its advanced features. Next, we explain the
- POSTGRES approach to extensibility and describe how
- users can extend POSTGRES by adding user-defined types,
- operators, aggregates, and both query language and pro-
- gramming language functions. After an extremely brief
- overview of the POSTGRES rule system, the manual
- concludes with a detailed appendix that discusses some of
- the more involved and operating system-specific
- procedures involved in extending the system.
-
-UNIX is a trademark of X/Open, Ltd. Sun4, SPARC, SunOS
-and Solaris are trademarks of Sun Microsystems, Inc. DEC,
-DECstation, Alpha AXP and ULTRIX are trademarks of Digital
-Equipment Corp. PA-RISC and HP-UX are trademarks of
-Hewlett-Packard Co. OSF/1 is a trademark of the Open
-
- We assume proficiency with UNIX and C programming.
-
-
-
-[ Previous ]
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - LIBPQ
-
-
-
-
-
-
-
-
12. LIBPQ
-
- LIBPQ is the application programming interface to POSTGRES.
- LIBPQ is a set of library routines which allows
- client programs to pass queries to the POSTGRES backend
- server and to receive the results of these queries.
- This version of the documentation describes the C
- interface library. Three short programs are included
- at the end of this section to show how to write programs that use LIBPQ.
- There are several examples of LIBPQ applications in the
- following directories:
-
- ../src/test/examples
- ../src/bin/psql
-
- Frontend programs which use LIBPQ must include the
- header file libpq-fe.h
and must link with the libpq
- library.
-
- The following environment variables can be used to set
- up default environment values to avoid hard-coding
- database names into an application program:
-
-
PGHOST sets the default server name.
-
PGOPTIONS sets additional runtime options for the POSTGRES backend.
-
PGPORT sets the default port for communicating with the POSTGRES backend.
-
PGTTY sets the file or tty on which debugging messages from the backend server are displayed.
-
PGDATABASE sets the default POSTGRES database name.
-
PGREALM sets the Kerberos realm to use with POSTGRES, if it is different from the local realm. If
-
PGREALM is set, POSTGRES applications will attempt
- authentication with servers for this realm and use
- separate ticket files to avoid conflicts with local
- ticket files. This environment variable is only
- used if Kerberos authentication is enabled.
-
-
- The following routines deal with making a connection to
- a backend from a C program.
-
-
PQsetdb
-
Makes a new connection to a backend.
-
PGconn *PQsetdb(char *pghost,
- char *pgport,
- char *pgoptions,
- char *pgtty,
- char *dbName);
-
-
If any argument is NULL, then the corresponding
- environment variable is checked. If the environment variable is also not set, then hardwired
- defaults are used.
-
PQsetdb always returns a valid PGconn pointer.
-
The PQstatus (see below) command should be called
- to ensure that a connection was properly made
- before queries are sent via the connection. LIBPQ
- programmers should be careful to maintain the
-
PGconn abstraction. Use the accessor functions
- below to get at the contents of PGconn. Avoid
- directly referencing the fields of the PGconn
- structure as they are subject to change in the
- future.
-
PQdb
-
Returns the database name of the connection.
-
char *PQdb(PGconn *conn)
-
-
PQhost
-
Returns the host name of the connection.
-
char *PQhost(PGconn *conn)
-
-
PQoptions
-
Returns the pgoptions used in the connection.
-
char *PQoptions(PGconn *conn)
-
-
PQport
-
Returns the pgport of the connection.
-
char *PQport(PGconn *conn)
-
-
PQtty
-
Returns the pgtty of the connection.
-
char *PQtty(PGconn *conn)
-
-
PQstatus
-
Returns the status of the connection.
-
The status can be CONNECTION_OK or CONNECTION_BAD.
-
ConnStatusType *PQstatus(PGconn *conn)
-
-
PQerrorMessage
-
Returns the error message associated with the connection
-
char *PQerrorMessage(PGconn* conn);
-
-
-
PQfinish
-
Close the connection to the backend. Also frees
- memory used by the PGconn structure. The PGconn
- pointer should not be used after PQfinish has been
- called.
-
void PQfinish(PGconn *conn)
-
-
PQreset
-
Reset the communication port with the backend.
- This function will close the IPC socket connection
- to the backend and attempt to reestablish a new
- connection to the same backend.
-
void PQreset(PGconn *conn)
-
-
PQtrace
-
Enables tracing of messages passed between the
- frontend and the backend. The messages are echoed
- to the debug_port file stream.
-
void PQtrace(PGconn *conn,
- FILE* debug_port);
-
-
PQuntrace
-
Disables tracing of messages passed between the
- frontend and the backend.
-
void PQuntrace(PGconn *conn);
-
-
-
PQexec
-
Submit a query to POSTGRES. Returns a PGresult
- pointer if the query was successful or a NULL otherwise. If a NULL is returned, PQerrorMessage can
- be used to get more information about the error.
-
PGresult *PQexec(PGconn *conn,
- char *query);
-
-
The PGresult structure encapsulates the query
- result returned by the backend. LIBPQ programmers
- should be careful to maintain the PGresult
- abstraction. Use the accessor functions described
- below to retrieve the results of the query. Avoid
- directly referencing the fields of the PGresult
- structure as they are subject to change in the
- future.
-
PQresultStatus
-
Returns the result status of the query. PQresultStatus can return one of the following values:
- PGRES_COMMAND_OK, /* the query was a command */
- PGRES_TUPLES_OK, /* the query successfully returned tuples */
- PGRES_COPY_OUT,
- PGRES_COPY_IN,
- PGRES_BAD_RESPONSE, /* an unexpected response was received */
- PGRES_NONFATAL_ERROR,
- PGRES_FATAL_ERROR
-
-
If the result status is PGRES_TUPLES_OK, then the
- following routines can be used to retrieve the
- tuples returned by the query.
-
PQntuples returns the number of tuples (instances)
- in the query result.
-
-
int PQntuples(PGresult *res);
-
-
PQnfields
-
Returns the number of fields
- (attributes) in the query result.
-
-
int PQnfields(PGresult *res);
-
-
PQfname
-
Returns the field (attribute) name associated with the given field index. Field indices
- start at 0.
-
-
char *PQfname(PGresult *res,
- int field_index);
-
-
PQfnumber
-
Returns the field (attribute) index
- associated with the given field name.
-
-
int PQfnumber(PGresult *res,
- char* field_name);
-
-
PQftype
-
Returns the field type associated with the
- given field index. The integer returned is an
- internal coding of the type. Field indices start
- at 0.
-
-
Oid PQftype(PGresult *res,
- int field_num);
-
-
PQfsize
-
Returns the size in bytes of the field
- associated with the given field index. If the size
- returned is -1, the field is a variable length
- field. Field indices start at 0.
-
-
int2 PQfsize(PGresult *res,
- int field_index);
-
-
PQgetvalue
-
Returns the field (attribute) value.
- For most queries, the value returned by PQgetvalue
- is a null-terminated ASCII string representation
- of the attribute value. If the query was a result
- of a BINARY cursor, then the value returned by
- PQgetvalue is the binary representation of the
- type in the internal format of the backend server.
- It is the programmer's responsibility to cast and
- convert the data to the correct C type. The value
- returned by PQgetvalue points to storage that is
- part of the PGresult structure. One must explicitly
- copy the value into other storage if it is to
- be used past the lifetime of the PGresult structure itself.
-
-
char* PQgetvalue(PGresult *res,
- int tup_num,
- int field_num);
-
-
PQgetlength
-
Returns the length of a field
- (attribute) in bytes. If the field is a struct
- varlena, the length returned here does not include
- the size field of the varlena, i.e., it is 4 bytes
- less.
-
int PQgetlength(PGresult *res,
- int tup_num,
- int field_num);
-
-
PQcmdStatus
- Returns the command status associated with the
- last query command.
- char *PQcmdStatus(PGresult *res);
-
-
PQoidStatus
- Returns a string with the object id of the tuple
- inserted if the last query is an INSERT command.
- Otherwise, returns an empty string.
-
char* PQoidStatus(PGresult *res);
-
-
PQprintTuples
- Prints out all the tuples and, optionally, the
- attribute names to the specified output stream.
- The programs psql and monitor both use PQprintTuples for output.
-
- PGresult* res,
- FILE* fout, /* output stream */
- int printAttName,/* print attribute names or not*/
- int terseOutput, /* delimiter bars or not?*/
- int width /* width of column, variable width if 0*/
- );
-
-
-
PQclear
- Frees the storage associated with the PGresult.
- Every query result should be properly freed when
- it is no longer used. Failure to do this will
- result in memory leaks in the frontend application.
-
void PQclear(PQresult *res);
-
-
- POSTGRES provides a fast path interface to send function calls to the backend. This is a trapdoor into
- system internals and can be a potential security hole.
- Most users will not need this feature.
-
-
PGresult* PQfn(PGconn* conn,
- int fnid,
- int *result_buf,
- int *result_len,
- int result_is_int,
- PQArgBlock *args,
- int nargs);
-
-
- The fnid argument is the object identifier of the function to be executed. result_buf is the buffer in which
- to load the return value. The caller must have allocated sufficient space to store the return value. The
- result length will be returned in the storage pointed
- to by result_len. If the result is to be an integer
- value, than result_is_int should be set to 1; otherwise
- it should be set to 0. args and nargs specify the
- arguments to the function.
- int len;
- int isint;
- union {
- int *ptr;
- int integer;
- } u;
- } PQArgBlock;
-
- PQfn always returns a valid PGresult*. The resultStatus should be checked before the result is used. The
- caller is responsible for freeing the PGresult with
- PQclear when it is not longer needed.
- POSTGRES supports asynchronous notification via the
- LISTEN and NOTIFY commands. A backend registers its
- interest in a particular relation with the LISTEN command. All backends listening on a particular relation
- will be notified asynchronously when a NOTIFY of that
- relation name is executed by another backend. No
- additional information is passed from the notifier to
- the listener. Thus, typically, any actual data that
- needs to be communicated is transferred through the
- relation.
- LIBPQ applications are notified whenever a connected
- backend has received an asynchronous notification.
- However, the communication from the backend to the
- frontend is not asynchronous. Notification comes
- piggy-backed on other query results. Thus, an application must submit queries, even empty ones, in order to
- receive notice of backend notification. In effect, the
- LIBPQ application must poll the backend to see if there
- is any pending notification information. After the
- execution of a query, a frontend may call PQNotifies to
- see if any notification data is available from the
- backend.
-
PQNotifies
-
returns the notification from a list of unhandled
- notifications from the backend. Returns NULL if
- there are no pending notifications from the backend. PQNotifies behaves like the popping of a
- stack. Once a notification is returned from PQnotifies, it is considered handled and will be
- removed from the list of notifications.
-
PGnotify* PQNotifies(PGconn *conn);
-
-
- The second sample program gives an example of the use
- of asynchronous notification.
- The copy command in POSTGRES has options to read from
- or write to the network connection used by LIBPQ.
- Therefore, functions are necessary to access this network connection directly so applications may take full
- advantage of this capability.
-
PQgetline
-
Reads a newline-terminated line of characters
- (transmitted by the backend server) into a buffer
- string of size length. Like fgets(3), this routine copies up to length-1 characters into string.
- It is like gets(3), however, in that it converts
- the terminating newline into a null character.
- PQgetline returns EOF at EOF, 0 if the entire line
- has been read, and 1 if the buffer is full but the
- terminating newline has not yet been read.
- Notice that the application must check to see if a
- new line consists of the single character ".",
- which indicates that the backend server has finished sending the results of the copy command.
- Therefore, if the application ever expects to
- receive lines that are more than length-1 characters long, the application must be sure to check
- the return value of PQgetline very carefully.
- The code in
-
-
- contains routines that correctly handle the copy
- protocol.
-
int PQgetline(PGconn *conn,
- char *string,
- int length)
-
-
PQputline
-
Sends a null-terminated string to the backend
- server.
- The application must explicitly send the single
- character "." to indicate to the backend that it
- has finished sending its data.
-
-
void PQputline(PGconn *conn,
- char *string);
-
-
PQendcopy
-
Syncs with the backend. This function waits until
- the backend has finished the copy. It should
- either be issued when the last string has been
- sent to the backend using PQputline or when the
- last string has been received from the backend
- using PGgetline. It must be issued or the backend
- may get "out of sync" with the frontend. Upon
- return from this function, the backend is ready to
- receive the next query.
- The return value is 0 on successful completion,
- nonzero otherwise.
-
int PQendcopy(PGconn *conn);
-
- As an example:
-
PQexec(conn, "create table foo (a int4, b char16, d float8)");
- PQexec(conn, "copy foo from stdin");
- PQputline(conn, "3<TAB>hello world<TAB>4.5\n");
- PQputline(conn,"4<TAB>goodbye world<TAB>7.11\n");
- ...
- PQputline(conn,".\n");
- PQendcopy(conn);
-
-
-
PQtrace
-
Enable tracing of the frontend/backend communication to a debugging file stream.
-
void PQtrace(PGconn *conn
- FILE *debug_port)
-
-
-
PQuntrace
-
Disable tracing started by PQtrace
-
void PQuntrace(PGconn *conn)
-
-
- If the user has generated the appropriate authentication credentials (e.g., obtaining Kerberos tickets),
- the frontend/backend authentication process is handled
- by PQexec without any further intervention. The following routines may be called by LIBPQ programs to tailor the behavior of the authentication process.
-
fe_getauthname
-
Returns a pointer to static space containing whatever name the user has authenticated. Use of this
- routine in place of calls to getenv(3) or getpwuid(3) by applications is highly recommended, as
- it is entirely possible that the authenticated
- user name is not the same as value of the USER
- environment variable or the user's entry in
- /etc/passwd
.
-
-
char *fe_getauthname(char* errorMessage)
-
-
fe_setauthsvc
-
Specifies that LIBPQ should use authentication
- service name rather than its compiled-in default.
-
This value is typically taken from a command-line
- switch.
-
void fe_setauthsvc(char *name,
- char* errorMessage)
-
-
Any error messages from the authentication
- attempts are returned in the errorMessage argument.
-
-
- The query buffer is 8192 bytes long, and queries over
- that length will be silently truncated.
- /*
- * testlibpq.c
- * Test the C version of LIBPQ, the POSTGRES frontend library.
- *
- *
- */
- #include <stdio.h>
- #include "libpq-fe.h"
- void
- exit_nicely(PGconn* conn)
- {
- PQfinish(conn);
- exit(1);
- }
- main()
- {
- char *pghost, *pgport, *pgoptions, *pgtty;
- char* dbName;
- int nFields;
- int i,j;
- /* FILE *debug; */
- PGconn* conn;
- PGresult* res;
- /* begin, by setting the parameters for a backend connection
- if the parameters are null, then the system will try to use
- reasonable defaults by looking up environment variables
- or, failing that, using hardwired constants */
- pghost = NULL; /* host name of the backend server */
- pgport = NULL; /* port of the backend server */
- pgoptions = NULL; /* special options to start up the backend server */
- pgtty = NULL; /* debugging tty for the backend server */
- dbName = "template1";
- /* make a connection to the database */
- conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
- /* check to see that the backend connection was successfully made */
- if (PQstatus(conn) == CONNECTION_BAD) {
- fprintf(stderr,"Connection to database '%s' failed.0, dbName);
- fprintf(stderr,"%s",PQerrorMessage(conn));
- exit_nicely(conn);
- }
- /* debug = fopen("/tmp/trace.out","w"); */
- /* PQtrace(conn, debug); */
- /* start a transaction block */
-
- res = PQexec(conn,"BEGIN");
- if (PQresultStatus(res) != PGRES_COMMAND_OK) {
- fprintf(stderr,"BEGIN command failed0);
- PQclear(res);
- exit_nicely(conn);
- }
- /* should PQclear PGresult whenever it is no longer needed to avoid
- memory leaks */
- PQclear(res);
- /* fetch instances from the pg_database, the system catalog of databases*/
- res = PQexec(conn,"DECLARE myportal CURSOR FOR select * from pg_database");
- if (PQresultStatus(res) != PGRES_COMMAND_OK) {
- fprintf(stderr,"DECLARE CURSOR command failed0);
- PQclear(res);
- exit_nicely(conn);
- }
- PQclear(res);
- res = PQexec(conn,"FETCH ALL in myportal");
- if (PQresultStatus(res) != PGRES_TUPLES_OK) {
- fprintf(stderr,"FETCH ALL command didn't return tuples properly0);
- PQclear(res);
- exit_nicely(conn);
- }
- /* first, print out the attribute names */
- nFields = PQnfields(res);
- for (i=0; i < nFields; i++) {
- printf("%-15s",PQfname(res,i));
- }
- printf("0);
- /* next, print out the instances */
- for (i=0; i < PQntuples(res); i++) {
- for (j=0 ; j < nFields; j++) {
- printf("%-15s", PQgetvalue(res,i,j));
- }
- printf("0);
- }
- PQclear(res);
- /* close the portal */
- res = PQexec(conn, "CLOSE myportal");
- PQclear(res);
- /* end the transaction */
- res = PQexec(conn, "END");
- PQclear(res);
- /* close the connection to the database and cleanup */
- PQfinish(conn);
-
- /* fclose(debug); */
- }
-
- /*
- * testlibpq2.c
- * Test of the asynchronous notification interface
- *
- populate a database with the following:
- CREATE TABLE TBL1 (i int4);
- CREATE TABLE TBL2 (i int4);
- CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
- * Then start up this program
- * After the program has begun, do
- INSERT INTO TBL1 values (10);
- *
- *
- */
- #include <stdio.h>
- #include "libpq-fe.h"
- void exit_nicely(PGconn* conn)
- {
- PQfinish(conn);
- exit(1);
- }
- main()
- {
- char *pghost, *pgport, *pgoptions, *pgtty;
- char* dbName;
- int nFields;
- int i,j;
- PGconn* conn;
- PGresult* res;
- PGnotify* notify;
- /* begin, by setting the parameters for a backend connection
- if the parameters are null, then the system will try to use
- reasonable defaults by looking up environment variables
- or, failing that, using hardwired constants */
- pghost = NULL; /* host name of the backend server */
- pgport = NULL; /* port of the backend server */
- pgoptions = NULL; /* special options to start up the backend server */
- pgtty = NULL; /* debugging tty for the backend server */
- dbName = getenv("USER"); /* change this to the name of your test database*/
- /* make a connection to the database */
- conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
-
- /* check to see that the backend connection was successfully made */
- if (PQstatus(conn) == CONNECTION_BAD) {
- fprintf(stderr,"Connection to database '%s' failed.0, dbName);
- fprintf(stderr,"%s",PQerrorMessage(conn));
- exit_nicely(conn);
- }
- res = PQexec(conn, "LISTEN TBL2");
- if (PQresultStatus(res) != PGRES_COMMAND_OK) {
- fprintf(stderr,"LISTEN command failed0);
- PQclear(res);
- exit_nicely(conn);
- }
- /* should PQclear PGresult whenever it is no longer needed to avoid
- memory leaks */
- PQclear(res);
- while (1) {
- /* async notification only come back as a result of a query*/
- /* we can send empty queries */
- res = PQexec(conn, " ");
- /* printf("res->status = %s0, pgresStatus[PQresultStatus(res)]); */
- /* check for asynchronous returns */
- notify = PQnotifies(conn);
- if (notify) {
- fprintf(stderr,
- "ASYNC NOTIFY of '%s' from backend pid '%d' received0,
- notify->relname, notify->be_pid);
- free(notify);
- break;
- }
- PQclear(res);
- }
- /* close the connection to the database and cleanup */
- PQfinish(conn);
- }
-
- /*
- * testlibpq3.c
- * Test the C version of LIBPQ, the POSTGRES frontend library.
- * tests the binary cursor interface
- *
- *
- *
- populate a database by doing the following:
- CREATE TABLE test1 (i int4, d float4, p polygon);
- INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
- INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
- the expected output is:
- tuple 0: got
- i = (4 bytes) 1,
- d = (4 bytes) 3.567000,
- p = (4 bytes) 2 points boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000)
- tuple 1: got
- i = (4 bytes) 2,
- d = (4 bytes) 89.050003,
- p = (4 bytes) 2 points boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000)
- *
- */
- #include <stdio.h>
- #include "libpq-fe.h"
- #include "utils/geo-decls.h" /* for the POLYGON type */
- void exit_nicely(PGconn* conn)
- {
- PQfinish(conn);
- exit(1);
- }
- main()
- {
- char *pghost, *pgport, *pgoptions, *pgtty;
- char* dbName;
- int nFields;
- int i,j;
- int i_fnum, d_fnum, p_fnum;
- PGconn* conn;
- PGresult* res;
- /* begin, by setting the parameters for a backend connection
- if the parameters are null, then the system will try to use
- reasonable defaults by looking up environment variables
- or, failing that, using hardwired constants */
- pghost = NULL; /* host name of the backend server */
- pgport = NULL; /* port of the backend server */
- pgoptions = NULL; /* special options to start up the backend server */
- pgtty = NULL; /* debugging tty for the backend server */
- dbName = getenv("USER"); /* change this to the name of your test database*/
- /* make a connection to the database */
- conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
- /* check to see that the backend connection was successfully made */
- if (PQstatus(conn) == CONNECTION_BAD) {
- fprintf(stderr,"Connection to database '%s' failed.0, dbName);
- fprintf(stderr,"%s",PQerrorMessage(conn));
- exit_nicely(conn);
- }
- /* start a transaction block */
- res = PQexec(conn,"BEGIN");
- if (PQresultStatus(res) != PGRES_COMMAND_OK) {
- fprintf(stderr,"BEGIN command failed0);
- PQclear(res);
- exit_nicely(conn);
- }
- /* should PQclear PGresult whenever it is no longer needed to avoid
- memory leaks */
- PQclear(res);
- /* fetch instances from the pg_database, the system catalog of databases*/
- res = PQexec(conn,"DECLARE mycursor BINARY CURSOR FOR select * from test1");
- if (PQresultStatus(res) != PGRES_COMMAND_OK) {
- fprintf(stderr,"DECLARE CURSOR command failed0);
- PQclear(res);
- exit_nicely(conn);
- }
- PQclear(res);
- res = PQexec(conn,"FETCH ALL in mycursor");
- if (PQresultStatus(res) != PGRES_TUPLES_OK) {
- fprintf(stderr,"FETCH ALL command didn't return tuples properly0);
- PQclear(res);
- exit_nicely(conn);
- }
- i_fnum = PQfnumber(res,"i");
- d_fnum = PQfnumber(res,"d");
- p_fnum = PQfnumber(res,"p");
- for (i=0;i<3;i++) {
- printf("type[%d] = %d, size[%d] = %d0,
- i, PQftype(res,i),
- i, PQfsize(res,i));
- }
- for (i=0; i < PQntuples(res); i++) {
- int *ival;
- float *dval;
- int plen;
- POLYGON* pval;
- /* we hard-wire this to the 3 fields we know about */
- ival = (int*)PQgetvalue(res,i,i_fnum);
- dval = (float*)PQgetvalue(res,i,d_fnum);
- plen = PQgetlength(res,i,p_fnum);
- /* plen doesn't include the length field so need to increment by VARHDSZ*/
- pval = (POLYGON*) malloc(plen + VARHDRSZ);
- pval->size = plen;
- memmove((char*)&pval->npts, PQgetvalue(res,i,p_fnum), plen);
- printf("tuple %d: got0, i);
- printf(" i = (%d bytes) %d,0,
- PQgetlength(res,i,i_fnum), *ival);
- printf(" d = (%d bytes) %f,0,
- PQgetlength(res,i,d_fnum), *dval);
- printf(" p = (%d bytes) %d points boundbox = (hi=%f/%f, lo = %f,%f)0,
- PQgetlength(res,i,d_fnum),
- pval->npts,
- pval->boundbox.xh,
- pval->boundbox.yh,
- pval->boundbox.xl,
- pval->boundbox.yl);
- }
- PQclear(res);
- /* close the portal */
- res = PQexec(conn, "CLOSE mycursor");
- PQclear(res);
- /* end the transaction */
- res = PQexec(conn, "END");
- PQclear(res);
- /* close the connection to the database and cleanup */
- PQfinish(conn);
- }
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - LARGE OBJECTS
-
-
-
-
-
-
-
-
13. LARGE OBJECTS
-
- In POSTGRES, data values are stored in tuples and
- individual tuples cannot span data pages. Since the size of
- a data page is 8192 bytes, the upper limit on the size
- of a data value is relatively low. To support the storage
- of larger atomic values, POSTGRES provides a large
- object interface. This interface provides file
- oriented access to user data that has been declared to
- be a large type.
- This section describes the implementation and the
- programmatic and query language interfaces to POSTGRES
- large object data.
-
- Originally, POSTGRES 4.2 supports three standard
- implementations of large objects: as files external
- to POSTGRES, as UNIX files managed by POSTGRES, and as data
- stored within the POSTGRES database. It causes
- considerable confusion among users. As a result, we only
- support large objects as data stored within the POSTGRES
- database in POSTGRES95. Even though is is slower to
- access, it provides stricter data integrity and time
- travel. For historical reasons, they are called
- Inversion large objects. (We will use Inversion and large
- objects interchangeably to mean the same thing in this
- section.)
-
- The Inversion large object implementation breaks large
- objects up into "chunks" and stores the chunks in
- tuples in the database. A B-tree index guarantees fast
- searches for the correct chunk number when doing random
- access reads and writes.
-
- The facilities POSTGRES provides to access large
- objects, both in the backend as part of user-defined
- functions or the front end as part of an application
- using the interface, are described below. (For users
- familiar with POSTGRES 4.2, POSTGRES95 has a new set of
- functions providing a more coherent interface. The
- interface is the same for dynamically-loaded C
- functions as well as for .
- The POSTGRES large object interface is modeled after
- the UNIX file system interface, with analogues of
- open(2), read(2), write(2), lseek(2), etc. User
- functions call these routines to retrieve only the data of
- interest from a large object. For example, if a large
- object type called mugshot existed that stored
- photographs of faces, then a function called beard could
- be declared on mugshot data. Beard could look at the
- lower third of a photograph, and determine the color of
- the beard that appeared there, if any. The entire
- large object value need not be buffered, or even
- examined, by the beard function.
- Large objects may be accessed from dynamically-loaded C
- functions or database client programs that link the
- library. POSTGRES provides a set of routines that
- support opening, reading, writing, closing, and seeking on
- large objects.
- The routine
-
Oid lo_creat(PGconn *conn, int mode)
-
- creates a new large object. The mode is a bitmask
- describing several different attributes of the new
- object. The symbolic constants listed here are defined
- in
-
/usr/local/postgres95/src/backend/libpq/libpq-fs.h
-
- The access type (read, write, or both) is controlled by
- OR ing together the bits INV_READ and INV_WRITE. If
- the large object should be archived -- that is, if
- historical versions of it should be moved periodically to
- a special archive relation -- then the INV_ARCHIVE bit
- should be set. The low-order sixteen bits of mask are
- the storage manager number on which the large object
- should reside. For sites other than Berkeley, these
- bits should always be zero.
- The commands below create an (Inversion) large object:
-
inv_oid = lo_creat(INV_READ|INV_WRITE|INV_ARCHIVE);
-
-
-To import a UNIX file as
- a large object, call
- lo_import(PGconn *conn, text *filename)
-
- The filename argument specifies the UNIX pathname of
- the file to be imported as a large object.
-To export a large object
- into UNIX file, call
- lo_export(PGconn *conn, Oid lobjId, text *filename)
-
- The lobjId argument specifies the Oid of the large
- object to export and the filename argument specifies
- the UNIX pathname of the file.
- To open an existing large object, call
- lo_open(PGconn *conn, Oid lobjId, int mode, ...)
-
- The lobjId argument specifies the Oid of the large
- object to open. The mode bits control whether the
- object is opened for reading INV_READ), writing or
- both.
- A large object cannot be opened before it is created.
- lo_open returns a large object descriptor for later use
- in lo_read, lo_write, lo_lseek, lo_tell, and lo_close.
- The routine
- lo_write(PGconn *conn, int fd, char *buf, int len)
-
- writes len bytes from buf to large object fd. The fd
- argument must have been returned by a previous lo_open.
- The number of bytes actually written is returned. In
- the event of an error, the return value is negative.
- To change the current read or write location on a large
- object, call
- lo_lseek(PGconn *conn, int fd, int offset, int whence)
-
- This routine moves the current location pointer for the
- large object described by fd to the new location specified
- by offset. The valid values for .i whence are
- SEEK_SET SEEK_CUR and SEEK_END.
- A large object may be closed by calling
- lo_close(PGconn *conn, int fd)
-
- where fd is a large object descriptor returned by
- lo_open. On success, lo_close returns zero. On error,
- the return value is negative.
-
- There are two built-in registered functions, lo_import
- and lo_export which are convenient for use in SQL
- queries.
- Here is an example of there use
- name text,
- raster oid
- );
-
- INSERT INTO image (name, raster)
- VALUES ('beautiful image', lo_import('/etc/motd'));
-
- SELECT lo_export(image.raster, "/tmp/motd") from image
- WHERE name = 'beautiful image';
-
- Below is a sample program which shows how the large object
- interface
- in LIBPQ can be used. Parts of the program are
- commented out but are left in the source for the readers
- benefit. This program can be found in
-
- Frontend applications which use the large object interface
- in LIBPQ should include the header file
- libpq/libpq-fs.h and link with the libpq library.
-
-
/*--------------------------------------------------------------
- *
- * testlo.c--
- * test using large objects with libpq
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * /usr/local/devel/pglite/cvs/src/doc/manual.me,v 1.16 1995/09/01 23:55:00 jolly Exp
- *
- *--------------------------------------------------------------
- */
- #include <stdio.h>
- #include "libpq-fe.h"
- #include "libpq/libpq-fs.h"
- #define BUFSIZE 1024
- /*
- * importFile * import file "in_filename" into database as large object "lobjOid"
- *
- */
- Oid importFile(PGconn *conn, char *filename)
- {
- Oid lobjId;
- int lobj_fd;
- char buf[BUFSIZE];
- int nbytes, tmp;
- int fd;
- /*
- * open the file to be read in
- */
- fd = open(filename, O_RDONLY, 0666);
- if (fd < 0) { /* error */
- fprintf(stderr, "can't open unix file
- }
- /*
- * create the large object
- */
- lobjId = lo_creat(conn, INV_READ|INV_WRITE);
- if (lobjId == 0) {
- fprintf(stderr, "can't create large object");
- }
- lobj_fd = lo_open(conn, lobjId, INV_WRITE);
- /*
- * read in from the Unix file and write to the inversion file
- */
- while ((nbytes = read(fd, buf, BUFSIZE)) > 0) {
- tmp = lo_write(conn, lobj_fd, buf, nbytes);
- if (tmp < nbytes) {
- fprintf(stderr, "error while reading
- }
- }
- (void) close(fd);
- (void) lo_close(conn, lobj_fd);
- return lobjId;
- }
- void pickout(PGconn *conn, Oid lobjId, int start, int len)
- {
- int lobj_fd;
- char* buf;
- int nbytes;
- int nread;
- lobj_fd = lo_open(conn, lobjId, INV_READ);
- if (lobj_fd < 0) {
- fprintf(stderr,"can't open large object %d",
- lobjId);
- }
- lo_lseek(conn, lobj_fd, start, SEEK_SET);
- buf = malloc(len+1);
- nread = 0;
- while (len - nread > 0) {
- nbytes = lo_read(conn, lobj_fd, buf, len - nread);
- buf[nbytes] = ' ';
- fprintf(stderr,">>> %s", buf);
- nread += nbytes;
- }
- fprintf(stderr,"0);
- lo_close(conn, lobj_fd);
- }
- void overwrite(PGconn *conn, Oid lobjId, int start, int len)
- {
- int lobj_fd;
- char* buf;
- int nbytes;
- int nwritten;
- int i;
- lobj_fd = lo_open(conn, lobjId, INV_READ);
- if (lobj_fd < 0) {
- fprintf(stderr,"can't open large object %d",
- lobjId);
- }
- lo_lseek(conn, lobj_fd, start, SEEK_SET);
- buf = malloc(len+1);
- for (i=0;i<len;i++)
- buf[i] = 'X';
- buf[i] = ' ';
- nwritten = 0;
- while (len - nwritten > 0) {
- nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
- nwritten += nbytes;
- }
- fprintf(stderr,"0);
- lo_close(conn, lobj_fd);
- }
-
- /*
- * exportFile * export large object "lobjOid" to file "out_filename"
- *
- */
- void exportFile(PGconn *conn, Oid lobjId, char *filename)
- {
- int lobj_fd;
- char buf[BUFSIZE];
- int nbytes, tmp;
- int fd;
- /*
- * create an inversion "object"
- */
- lobj_fd = lo_open(conn, lobjId, INV_READ);
- if (lobj_fd < 0) {
- fprintf(stderr,"can't open large object %d",
- lobjId);
- }
- /*
- * open the file to be written to
- */
- fd = open(filename, O_CREAT|O_WRONLY, 0666);
- if (fd < 0) { /* error */
- fprintf(stderr, "can't open unix file
- filename);
- }
- /*
- * read in from the Unix file and write to the inversion file
- */
- while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0) {
- tmp = write(fd, buf, nbytes);
- if (tmp < nbytes) {
- fprintf(stderr,"error while writing
- filename);
- }
- }
- (void) lo_close(conn, lobj_fd);
- (void) close(fd);
- return;
- }
- void
- exit_nicely(PGconn* conn)
- {
- PQfinish(conn);
- exit(1);
- }
- int
- main(int argc, char **argv)
- {
- char *in_filename, *out_filename;
- char *database;
- Oid lobjOid;
- PGconn *conn;
- PGresult *res;
- if (argc != 4) {
- fprintf(stderr, "Usage: %s database_name in_filename out_filename0,
- argv[0]);
- exit(1);
- }
- database = argv[1];
- in_filename = argv[2];
- out_filename = argv[3];
- /*
- * set up the connection
- */
- conn = PQsetdb(NULL, NULL, NULL, NULL, database);
- /* check to see that the backend connection was successfully made */
- if (PQstatus(conn) == CONNECTION_BAD) {
- fprintf(stderr,"Connection to database '%s' failed.0, database);
- fprintf(stderr,"%s",PQerrorMessage(conn));
- exit_nicely(conn);
- }
- res = PQexec(conn, "begin");
- PQclear(res);
-
- printf("importing file
- /* lobjOid = importFile(conn, in_filename); */
- lobjOid = lo_import(conn, in_filename);
- /*
- printf("as large object %d.0, lobjOid);
- printf("picking out bytes 1000-2000 of the large object0);
- pickout(conn, lobjOid, 1000, 1000);
- printf("overwriting bytes 1000-2000 of the large object with X's0);
- overwrite(conn, lobjOid, 1000, 1000);
- */
- printf("exporting large object to file
- /* exportFile(conn, lobjOid, out_filename); */
- lo_export(conn, lobjOid,out_filename);
- res = PQexec(conn, "end");
- PQclear(res);
- PQfinish(conn);
- exit(0);
- }
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual
-
-
-
-
-The
-POSTGRES95 User Manual
-
-
- Version 1.0 (September 5, 1995)
-
- and
- (with the POSTGRES Group)
- Computer Science Div., Dept. of EECS
- University of California at Berkeley
-
-
-
Table of Contents
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
POSTGRES95 is copyright © 1994-5 by the Regents of the
-University of California.
-The file
-pg95user.tgz contains the complete manual for download.
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - THE QUERY LANGUAGE
-
-
-
-
-
-
-
-
4. THE QUERY LANGUAGE
-
- The POSTGRES query language is a variant of SQL-3. It
- has many extensions such as an extensible type system,
- inheritance, functions and production rules. Those are
- features carried over from the original POSTGRES query
- language, POSTQUEL. This section provides an overview
- of how to use POSTGRES SQL to perform simple operations.
- This manual is only intended to give you an idea of our
- flavor of SQL and is in no way a complete tutorial on
- SQL. Numerous books have been written on SQL. For
- be aware that some features are not part of the ANSI
- standard.
- In the examples that follow, we assume that you have
- created the mydb database as described in the previous
- subsection and have started psql.
- Examples in this manual can also be found in
- /usr/local/postgres95/src/tutorial
. Refer to the
- README
file in that directory for how to use them. To
- start the tutorial, do the following:
-
% cd /usr/local/postgres95/src/tutorial
- % psql -s mydb
- Welcome to the POSTGRES95 interactive sql monitor:
-
- 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: jolly
-
-
- mydb=> \i basics.sql
-
- The \i command read in queries from the specified
- files. The -s option puts you in single step mode which
- pauses before sending a query to the backend. Queries
- in this section are in the file basics.sql
.
-
- The fundamental notion in POSTGRES is that of a class,
- which is a named collection of object instances. Each
- instance has the same collection of named attributes,
- and each attribute is of a specific type. Furthermore,
- each instance has a permanent object identifier (OID)
- that is unique throughout the installation. Because
- SQL syntax refers to tables, we will use the terms
- table< and class interchangeably. Likewise, a row is an
- instance and columns are attributes.
- As previously discussed, classes are grouped into
- databases, and a collection of databases managed by a
- single postmaster process constitutes an installation
- or site.
-
- You can create a new class by specifying the class
- name, along with all attribute names and their types:
- city varchar(80),
- temp_lo int, -- low temperature
- temp_hi int, -- high temperature
- prcp real, -- precipitation
- date date
- );
-
- Note that keywords are case-insensitive but identifiers
- are case-sensitive. POSTGRES SQL supports the usual
- SQL types int, float, real, smallint, char(N),
- varchar(N), date, and time. As we will
- see later, POSTGRES can be customized with an
- arbitrary number of
- user-defined data types. Consequently, type names are
- not keywords.
- So far, the POSTGRES create command looks exactly like
- the command used to create a table in a traditional
- relational system. However, we will presently see that
- classes have properties that are extensions of the
- relational model.
-
- The insert statement is used to populate a class with
- instances:
- VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')
-
- You can also use the copy command to perform load large
- amounts of data from flat (ASCII) files.
-
- The weather class can be queried with normal relational
- selection and projection queries. A SQL select
- statement is used to do this. The statement is divided into
- a target list (the part that lists the attributes to be
- returned) and a qualification (the part that specifies
- any restrictions). For example, to retrieve all the
- rows of weather, type:
-
-
- and the output should be:
- +--------------+---------+---------+------+------------+
- |city | temp_lo | temp_hi | prcp | date |
- +--------------+---------+---------+------+------------+
- |San Francisco | 46 | 50 | 0.25 | 11-27-1994 |
- +--------------+---------+---------+------+------------+
- |San Francisco | 43 | 57 | 0 | 11-29-1994 |
- +--------------+---------+---------+------+------------+
- |Hayward | 37 | 54 | | 11-29-1994 |
- +--------------+---------+---------+------+------------+
-
- You may specify any aribitrary expressions in the target list. For example, you can do:
-
* SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
-
- Arbitrary Boolean operators ( and, or and not) are
- allowed in the qualification of any query. For example,
- FROM weather
- WHERE city = 'San Francisco'
- and prcp > 0.0;
-
- +--------------+---------+---------+------+------------+
- |city | temp_lo | temp_hi | prcp | date |
- +--------------+---------+---------+------+------------+
- |San Francisco | 46 | 50 | 0.25 | 11-27-1994 |
- +--------------+---------+---------+------+------------+
-
-
- As a final note, you can specify that the results of a
- select can be returned in a sorted order or with duplicate instances removed.
- FROM weather
- ORDER BY city;
-
-
- Any select query can be redirected to a new class
-
SELECT * INTO temp from weather;
-
- This creates an implicit create command, creating a new
- class temp with the attribute names and types specified
- in the target list of the SELECT INTO command. We can
- then, of course, perform any operations on the resulting
- class that we can perform on other classes.
-
- Thus far, our queries have only accessed one class at a
- time. Queries can access multiple classes at once, or
- access the same class in such a way that multiple
- instances of the class are being processed at the same
- time. A query that accesses multiple instances of the
- same or different classes at one time is called a join
- query.
- As an example, say we wish to find all the records that
- are in the temperature range of other records. In
- effect, we need to compare the temp_lo and temp_hi
- attributes of each EMP instance to the temp_lo and
- temp_hi attributes of all other EMP instances.
2 We can
- do this with the following query:
-
SELECT W1.city, W1.temp_lo, W1.temp_hi,
- W2.city, W2.temp_lo, W2.temp_hi
- FROM weather W1, weather W2
- WHERE W1.temp_lo < W2.temp_lo
- and W1.temp_hi > W2.temp_hi;
-
- +--------------+---------+---------+---------------+---------+---------+
- |city | temp_lo | temp_hi | city | temp_lo | temp_hi |
- +--------------+---------+---------+---------------+---------+---------+
- |San Francisco | 43 | 57 | San Francisco | 46 | 50 |
- +--------------+---------+---------+---------------+---------+---------+
- |San Francisco | 37 | 54 | San Francisco | 46 | 50 |
- +--------------+---------+---------+---------------+---------+---------+
-
- In this case, both W1 and W2 are surrogates for an
- instance of the class weather, and both range over all
- instances of the class. (In the terminology of most
- database systems, W1 and W2 are known as "range variables.")
- A query can contain an arbitrary number of
- class names and surrogates.
3
-
- You can update existing instances using the update command.
- Suppose you discover the temperature readings are
- all off by 2 degrees as of Nov 28, you may update the
- data as follow:
- SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2
- WHERE date > '11/28/1994;
-
-
- Deletions are performed using the delete command:
-
* DELETE FROM weather WHERE city = 'Hayward';
-
- All weather recording belongs to Hayward is removed.
- One should be wary of queries of the form
-
- Without a qualification, the delete command will simply
- delete all instances of the given class, leaving it
- empty. The system will not request confirmation before
- doing this.
-
- Like most other query languages, POSTGRES supports
- aggregate functions. However, the current
- implementation of POSTGRES aggregate functions is very limited.
- Specifically, while there are aggregates to compute
- such functions as the count, sum, average, maximum and
- minimum over a set of instances, aggregates can only
- appear in the target list of a query and not in the
- qualification ( where clause) As an example,
- FROM weather;
-
- Aggregates may also have GROUP BY clauses:
- SELECT city, max(temp_lo)
- FROM weather
- GROUP BY city;
-
-
-
2. This is only a conceptual model. The actual join may
- be performed in a more efficient manner, but this is invisible to the user.
-
-
3. The semantics of such a join are
- that the qualification
- is a truth expression defined for the Cartesian product of
- the classes indicated in the query. For those instances in
- the Cartesian product for which the qualification is true,
- POSTGRES computes and returns the values specified in the
- target list. POSTGRES SQL does not assign any meaning to
- duplicate values in such expressions. This means that POSTGRES
- sometimes recomputes the same target list several times
- this frequently happens when Boolean expressions are connected
- with an or. To remove such duplicates, you must use
- the select distinct statement.
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - REFERENCES
-
-
-
-
-
-
-
-
16. REFERENCES
-
-
[DATE93]Date, C. J. and Darwen, Hugh, A Guide to The
- SQL Standard, 3rd Edition, Reading, MA, June
- 1993.
-
[MELT93]Melton, J. Understanding the New SQL, 1994.
-
[ONG90]Ong, L. and Goh, J., ``A Unified Framework
- for Version Modeling Using Production Rules
- in a Database System," Electronics Research
- Laboratory, University of California, ERL
- Technical Memorandum M90/33, Berkeley, CA,
- April 1990.
-
[ROWE87]Rowe, L. and Stonebraker, M., ``The POSTGRES
- Data Model,'' Proc. 1987 VLDB Conference,
- Brighton, England, Sept. 1987.
-
[STON86]Stonebraker, M. and Rowe, L., ``The Design
- of POSTGRES,'' Proc. 1986 ACM-SIGMOD Conference on Management of Data, Washington, DC,
- May 1986.
-
[STON87a]Stonebraker, M., Hanson, E. and Hong, C.-H.,
- ``The Design of the POSTGRES Rules System,''
- Proc. 1987 IEEE Conference on Data Engineering, Los Angeles, CA, Feb. 1987.
-
[STON87b]Stonebraker, M., ``The POSTGRES Storage System,'' Proc. 1987 VLDB Conference, Brighton,
- England, Sept. 1987.
-
[STON89]Stonebraker, M., Hearst, M., and Potamianos,
- S., ``A Commentary on the POSTGRES Rules
- System,'' SIGMOD Record 18(3), Sept. 1989.
-
[STON90a]Stonebraker, M., Rowe, L. A., and Hirohama,
- M., ``The Implementation of POSTGRES,'' IEEE
- Transactions on Knowledge and Data Engineering 2(1), March 1990.
-
[STON90b]Stonebraker, M. et al., ``On Rules, Procedures, Caching and Views in Database Systems,'' Proc. 1990 ACM-SIGMOD Conference on
- Management of Data, Atlantic City, N.J.,
- June 1990.
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - THE POSTGRES RULE SYSTEM
-
-
-
-
-
-
-
-
14. THE POSTGRES RULE SYSTEM
-
- Production rule systems are conceptually simple, but
- there are many subtle points involved in actually using
- them. Consequently, we will not attempt to explain the
- actual syntax and operation of the POSTGRES rule system
- here. Instead, you should read
[STON90b] to understand
- some of these points and the theoretical foundations of
- the POSTGRES rule system before trying to use rules.
- The discussion in this section is intended to provide
- an overview of the POSTGRES rule system and point the
- user at helpful references and examples.
- The "query rewrite" rule system modifies queries to
- take rules into consideration, and then passes the modified
- query to the query optimizer for execution. It
- is very powerful, and can be used for many things such
- as query language procedures, views, and versions. The
- power of this rule system is discussed in
-
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - GETTING STARTED
-
-
-
-
-
-
-
-
3. GETTING STARTED WITH POSTGRES
-
- This section discusses how to start POSTGRES and set up
- your own environment so that you can use frontend
- applications. We assume POSTGRES has already been
- successfully installed. (Refer to the installation notes
- for how to install POSTGRES.)
- Some of the steps listed in this section will apply to
- all POSTGRES users, and some will apply primarily to
- the site database administrator. This site administrator
- is the person who installed the software, created
- the database directories and started the postmaster
- process. This person does not have to be the UNIX
- superuser, "root," or the computer system administrator.
- In this section, items for end users are labelled
- "User" and items intended for the site administrator
- are labelled "Admin."
- Throughout this manual, any examples that begin with
- the character ``%'' are commands that should be typed
- at the UNIX shell prompt. Examples that begin with the
- character ``*'' are commands in the POSTGRES query
- language, POSTGRES SQL.
-
-
![]()
- Figure 2. shows how the POSTGRES distribution is laid
- out when installed in the default way. For simplicity,
- we will assume that POSTGRES has been installed in the
- directory /usr/local/postgres95. Therefore, wherever
- you see the directory /usr/local/postgres95 you should
- substitute the name of the directory where POSTGRES is
- actually installed.
- All POSTGRES commands are installed in the directory
- /usr/local/postgres95/bin. Therefore, you should add
- this directory to your shell command path. If you use
- a variant of the Berkeley C shell, such as csh or tcsh,
- you would add
-
% set path = ( /usr/local/postgres95/bin $path )
-
- in the .login file in your home directory. If you use
- a variant of the Bourne shell, such as sh, ksh, or
- bash, then you would add
- % PATH=/usr/local/postgres95/bin:$PATH
- % export PATH
-
- to the .profile file in your home directory.
- From now on, we will assume that you have added the
- POSTGRES bin directory to your path. In addition, we
- will make frequent reference to "setting a shell
- variable" or "setting an environment variable" throughout
- this document. If you did not fully understand the
- last paragraph on modifying your search path, you
- should consult the UNIX manual pages that describe your
- shell before going any further.
-
- It should be clear from the preceding discussion that
- nothing can happen to a database unless the postmaster
- process is running. As the site administrator, there
- are a number of things you should remember before
- starting the postmaster. These are discussed in the
- section of this manual titled, "Administering POSTGRES."
- However, if POSTGRES has been installed by following
- the installation instructions exactly as written, the
- following simple command is all you should
- need to start the postmaster:
-
- The postmaster occasionally prints out messages which
- are often helpful during troubleshooting. If you wish
- to view debugging messages from the postmaster, you can
- start it with the -d option and redirect the output to
- the log file:
-
% postmaster -d >& pm.log &
-
- If you do not wish to see these messages, you can type
-
- and the postmaster will be "S"ilent. Notice that there
- is no ampersand ("&") at the end of the last example.
-
- The createuser command enables specific users to access
- POSTGRES. The destroyuser command removes users and
- prevents them from accessing POSTGRES. Note that these
- commands only affect users with respect to POSTGRES;
- they have no effect administration of users that the
- operating system manages.
-
- Assuming that your site administrator has properly
- started the postmaster process and authorized you to
- use the database, you (as a user) may begin to start up
- applications. As previously mentioned, you should add
- /usr/local/postgres95/bin to your shell search path.
- In most cases, this is all you should have to do in
- If you get the following error message from a POSTGRES
- command (such as psql or createdb):
-
connectDB() failed: Is the postmaster running at 'localhost' on port '4322'?
-
- it is usually because (1) the postmaster is not running, or (2) you are attempting to connect to the wrong
- server host.
- If you get the following error message:
-
FATAL 1:Feb 17 23:19:55:process userid (2360) !=
- database owner (268)
-
- it means that the site administrator started the postmaster as the wrong user. Tell him to restart it as
- the POSTGRES superuser.
-
- Now that POSTGRES is up and running we can create some
- databases to experiment with. Here, we describe the
- basic commands for managing a database.
-
- Let's say you want to create a database named mydb.
- You can do this with the following command:
-
-
- POSTGRES allows you to create any number of databases
- at a given site and you automatically become the
- database administrator of the database you just created. Database names must have an alphabetic first
- character and are limited to 16 characters in length.
- Not every user has authorization to become a database
- administrator. If POSTGRES refuses to create databases
- for you, then the site administrator needs to grant you
- permission to create databases. Consult your site
- administrator if this occurs.
-
- Once you have constructed a database, you can access it
- by:
-
running the POSTGRES terminal monitor programs (
- monitor or psql) which allows you to interactively
- enter, edit, and execute SQL commands.
-
writing a C program using the LIBPQ subroutine
- library. This allows you to submit SQL commands
- from C and get answers and status messages back to
- your program. This interface is discussed further
- in section ??.
-
- You might want to start up psql, to try out the examples in this manual. It can be activated for the mydb
- database by typing the command:
-
- You will be greeted with the following message:
-
Welcome to the POSTGRES95 interactive sql monitor:
-
- 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: mydb
-
- mydb=>
- This prompt indicates that the terminal monitor is listening to you and that you can type SQL queries into a
- workspace maintained by the terminal monitor.
- The psql program responds to escape codes that begin
- with the backslash character, "\". For example, you
- can get help on the syntax of various POSTGRES SQL commands by typing:
-
- Once you have finished entering your queries into the
- workspace, you can pass the contents of the workspace
- to the POSTGRES server by typing:
-
- This tells the server to process the query. If you
- terminate your query with a semicolon, the \g is not
- necessary. psql will automatically process semicolon terminated queries.
- To read queries from a file, say myFile, instead of
- entering them interactively, type:
-
- To get out of psql and return to UNIX, type
-
- and psql will quit and return you to your command
- shell. (For more escape codes, type \h at the monitor
- prompt.)
- White space (i.e., spaces, tabs and newlines) may be
- used freely in SQL queries. Comments are denoted by
- --. Everything after the dashes up to the end of the
- line is ignored.
-
- If you are the database administrator for the database
- mydb, you can destroy it using the following UNIX command:
-
- This action physically removes all of the UNIX files
- associated with the database and cannot be undone, so
- this should only be done with a great deal of fore-thought.
-
-
-
-
1. If your site administrator has not set things up in the
-default way, you may have some more work to do. For example, if the database server machine is a remote machine, you
-will need to set the PGHOST environment variable to the name
-of the database server machine. The environment variable
-PGPORT may also have to be set. The bottom line is this: if
-you try to start an application program and it complains
-that it cannot connect to the postmaster, you should immediately consult your site administrator to make sure that your
-environment is properly set up.
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - EXTENDING SQL: AGGREGATES
-
-
-
-
-
-
-
-
10. EXTENDING SQL: AGGREGATES
-
- Aggregates in POSTGRES are expressed in terms of state
- transition functions. That is, an aggregate can be
- defined in terms of state that is modified whenever an
- instance is processed. Some state functions look at a
- particular value in the instance when computing the new
- state (sfunc1 in the create aggregate syntax) while
- others only keep track of their own internal state
- (sfunc2).
- If we define an aggregate that uses only sfunc1, we
- define an aggregate that computes a running function of
- the attribute values from each instance. "Sum" is an
- example of this kind of aggregate. "Sum" starts at
- zero and always adds the current instance's value to
- its running total. We will use the int4pl that is
- built into POSTGRES to perform this addition.
-
-
CREATE AGGREGATE complex_sum (
- sfunc1 = complex_add,
- basetype = complex,
- stype1 = complex,
- initcond1 = '(0,0)'
- );
-
-
- SELECT complex_sum(a) FROM test_complex;
-
-
- +------------+
- |complex_sum |
- +------------+
- |(34,53.9) |
- +------------+
-
-
- If we define only sfunc2, we are specifying an aggregate
- that computes a running function that is independent of
- the attribute values from each instance.
- "Count" is the most common example of this kind of
- aggregate. "Count" starts at zero and adds one to its
- running total for each instance, ignoring the instance
- value. Here, we use the built-in int4inc routine to do
- the work for us. This routine increments (adds one to)
- its argument.
-
-
CREATE AGGREGATE my_count (sfunc2 = int4inc, -- add one
- basetype = int4, stype2 = int4,
- initcond2 = '0')
-
- SELECT my_count(*) as emp_count from EMP;
-
-
- +----------+
- |emp_count |
- +----------+
- |5 |
- +----------+
-
-
- "Average" is an example of an aggregate that requires
- both a function to compute the running sum and a function
- to compute the running count. When all of the
- instances have been processed, the final answer for the
- aggregate is the running sum divided by the running
- count. We use the int4pl and int4inc routines we used
- before as well as the POSTGRES integer division
- routine, int4div, to compute the division of the sum by
- the count.
-
-
CREATE AGGREGATE my_average (sfunc1 = int4pl, -- sum
- basetype = int4,
- stype1 = int4,
- sfunc2 = int4inc, -- count
- stype2 = int4,
- finalfunc = int4div, -- division
- initcond1 = '0',
- initcond2 = '0')
-
- SELECT my_average(salary) as emp_average FROM EMP;
-
-
- +------------+
- |emp_average |
- +------------+
- |1640 |
- +------------+
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - EXTENDING SQL: FUNCTIONS
-
-
-
-
-
-
-
-
7. EXTENDING SQL: FUNCTIONS
-
- As it turns out, part of defining a new type is the
- definition of functions that describe its behavior.
- Consequently, while it is possible to define a new
- function without defining a new type, the reverse is
- not true. We therefore describe how to add new functions
- to POSTGRES before describing how to add new
- types.
- POSTGRES SQL provides two types of functions: query
- language functions (functions written in SQL and
- programming language functions (functions written in a
- compiled programming language such as C.) Either kind
- of function can take a base type, a composite type or
- some combination as arguments (parameters). In addition,
- both kinds of functions can return a base type or
- a composite type. It's easier to define SQL functions,
- so we'll start with those.
- Examples in this section can also be found in funcs.sql
- and C-code/funcs.c
.
-
- The simplest possible SQL function has no arguments and
- simply returns a base type, such as int4:
-
-
CREATE FUNCTION one() RETURNS int4
- AS 'SELECT 1 as RESULT' LANGUAGE 'sql';
-
-
- SELECT one() AS answer;
-
- +-------+
- |answer |
- +-------+
- |1 |
- +-------+
-
- Notice that we defined a target list for the function
- (with the name RESULT), but the target list of the
- query that invoked the function overrode the function's
- target list. Hence, the result is labelled answer
- instead of one.
- It's almost as easy to define SQL functions that take
- base types as arguments. In the example below, notice
- how we refer to the arguments within the function as $1
- and $2.
-
-
CREATE FUNCTION add_em(int4, int4) RETURNS int4
- AS 'SELECT $1 + $2;' LANGUAGE 'sql';
-
-
- SELECT add_em(1, 2) AS answer;
-
-
- +-------+
- |answer |
- +-------+
- |3 |
- +-------+
-
-
-
7.1.2. SQL Functions on Composite Types
- When specifying functions with arguments of composite
- types (such as EMP), we must not only specify which
- argument we want (as we did above with $1 and $2) but
- also the attributes of that argument. For example,
- take the function double_salary that computes what your
- salary would be if it were doubled.
-
-
CREATE FUNCTION double_salary(EMP) RETURNS int4
- AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql';
-
- SELECT name, double_salary(EMP) AS dream
- FROM EMP
- WHERE EMP.dept = 'toy';
-
-
- +-----+-------+
- |name | dream |
- +-----+-------+
- |Sam | 2400 |
- +-----+-------+
-
- Notice the use of the syntax $1.salary.
- Before launching into the subject of functions that
- return composite types, we must first introduce the
- function notation for projecting attributes. The simple way
- to explain this is that we can usually use the
- notation attribute(class) and class.attribute interchangably.
-
- -- this is the same as:
- -- SELECT EMP.name AS youngster FROM EMP WHERE EMP.age < 30
- --
- SELECT name(EMP) AS youngster
- FROM EMP
- WHERE age(EMP) < 30;
-
-
- +----------+
- |youngster |
- +----------+
- |Sam |
- +----------+
-
- As we shall see, however, this is not always the case.
- This function notation is important when we want to use
- a function that returns a single instance. We do this
- by assembling the entire instance within the function,
- attribute by attribute. This is an example of a function
- that returns a single EMP instance:
-
-
CREATE FUNCTION new_emp() RETURNS EMP
- AS 'SELECT \'None\'::text AS name,
- 1000 AS salary,
- 25 AS age,
- \'none\'::char16 AS dept;'
- LANGUAGE 'sql';
-
-
- In this case we have specified each of the attributes
- with a constant value, but any computation or expression
- could have been substituted for these constants.
- Defining a function like this can be tricky. Some of
- the more important caveats are as follows:
-
-
-
The target list order must be exactly the same as
- that in which the attributes appear in the CREATE
- TABLE statement (or when you execute a .* query).
-
You must be careful to typecast the expressions
- (using ::) very carefully or you will see the following error:
-
-
WARN::function declared to return type EMP does not retrieve (EMP.*)
-
-
When calling a function that returns an instance, we
- cannot retrieve the entire instance. We must either
- project an attribute out of the instance or pass the
- entire instance into another function.
-
SELECT name(new_emp()) AS nobody;
-
-
- +-------+
- |nobody |
- +-------+
- |None |
- +-------+
-
-
The reason why, in general, we must use the function
- syntax for projecting attributes of function return
- values is that the parser just doesn't understand
- the other (dot) syntax for projection when combined
- with function calls.
-
-
SELECT new_emp().name AS nobody;
- WARN:parser: syntax error at or near "."
-
-
-
- Any collection of commands in the SQL query language
- can be packaged together and defined as a function.
- The commands can include updates (i.e., insert, update
- and delete) as well as select queries. However, the
- final command must be a select that returns whatever is
- specified as the function's returntype.
-
- CREATE FUNCTION clean_EMP () RETURNS int4
- AS 'DELETE FROM EMP WHERE EMP.salary <= 0;
- SELECT 1 AS ignore_this'
- LANGUAGE 'sql';
-
- SELECT clean_EMP();
-
-
- +--+
- |x |
- +--+
- |1 |
- +--+
-
-
- Internally, POSTGRES regards a base type as a "blob of
- memory." The user-defined functions that you define
- over a type in turn define the way that POSTGRES can
- operate on it. That is, POSTGRES will only store and
- retrieve the data from disk and use your user-defined
- functions to input, process, and output the data.
- Base types can have one of three internal formats:
-
pass by value, fixed-length
-
pass by reference, fixed-length
-
pass by reference, variable-length
-
- By-value types can only be 1, 2 or 4 bytes in length
- (even if your computer supports by-value types of other
- sizes). POSTGRES itself only passes integer types by
- value. You should be careful to define your types such
- that they will be the same size (in bytes) on all
- architectures. For example, the long type is dangerous
- because it is 4 bytes on some machines and 8 bytes on
- others, whereas int type is 4 bytes on most UNIX
- machines (though not on most personal computers). A
- reasonable implementation of the int4 type on UNIX
- machines might be:
-
-
/* 4-byte integer, passed by value */
- typedef int int4;
-
-
- On the other hand, fixed-length types of any size may
- be passed by-reference. For example, here is a sample
- implementation of the POSTGRES char16 type:
-
-
/* 16-byte structure, passed by reference */
- typedef struct {
- char data[16];
- } char16;
-
-
- Only pointers to such types can be used when passing
- them in and out of POSTGRES functions.
- Finally, all variable-length types must also be passed
- by reference. All variable-length types must begin
- with a length field of exactly 4 bytes, and all data to
- be stored within that type must be located in the memory
- immediately following that length field. The
- length field is the total length of the structure
- (i.e., it includes the size of the length field
- itself). We can define the text type as follows:
-
- int4 length;
- char data[1];
- } text;
-
-
- Obviously, the data field is not long enough to hold
- all possible strings -- it's impossible to declare such
- a structure in C. When manipulating variable-length
- types, we must be careful to allocate the correct
- amount of memory and initialize the length field. For
- example, if we wanted to store 40 bytes in a text
- structure, we might use a code fragment like this:
-
- #include "utils/palloc.h"
-
- ...
-
- char buffer[40]; /* our source data */
-
- ...
-
- text *destination = (text *) palloc(VARHDRSZ + 40);
- destination->length = VARHDRSZ + 40;
- memmove(destination->data, buffer, 40);
-
- ...
-
-
- Now that we've gone over all of the possible structures
- for base types, we can show some examples of real functions.
- Suppose funcs.c
look like:
-
- #include "postgres.h" /* for char16, etc. */
- #include "utils/palloc.h" /* for palloc */
-
- int
- add_one(int arg)
- {
- return(arg + 1);
- }
-
- char16 *
- concat16(char16 *arg1, char16 *arg2)
- {
- char16 *new_c16 = (char16 *) palloc(sizeof(char16));
-
- memset((void *) new_c16, 0, sizeof(char16));
- (void) strncpy(new_c16, arg1, 16);
- return (char16 *)(strncat(new_c16, arg2, 16));
- }
- text *
- copytext(text *t)
- {
- /*
- * VARSIZE is the total size of the struct in bytes.
- */
- text *new_t = (text *) palloc(VARSIZE(t));
- memset(new_t, 0, VARSIZE(t));
- VARSIZE(new_t) = VARSIZE(t);
- /*
- * VARDATA is a pointer to the data region of the struct.
- */
- memcpy((void *) VARDATA(new_t), /* destination */
- (void *) VARDATA(t), /* source */
- VARSIZE(t)-VARHDRSZ); /* how many bytes */
- return(new_t);
- }
-
- On OSF/1 we would type:
-
-
CREATE FUNCTION add_one(int4) RETURNS int4
- AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';
-
- CREATE FUNCTION concat16(char16, char16) RETURNS char16
- AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';
-
- CREATE FUNCTION copytext(text) RETURNS text
- AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';
-
-
- On other systems, we might have to make the filename
- end in .sl (to indicate that it's a shared library).
- Composite types do not have a fixed layout like C
- structures. Instances of a composite type may contain
- null fields. In addition, composite types that are
- part of an inheritance hierarchy may have different
- fields than other members of the same inheritance hierarchy.
- Therefore, POSTGRES provides a procedural
- interface for accessing fields of composite types from
- C.
- As POSTGRES processes a set of instances, each instance
- will be passed into your function as an opaque structure of type TUPLE.
- Suppose we want to write a function to answer the query
-
-
* SELECT name, c_overpaid(EMP, 1500) AS overpaid
- FROM EMP
- WHERE name = 'Bill' or name = 'Sam';
-
- In the query above, we can define c_overpaid as:
-
-
#include "postgres.h" /* for char16, etc. */
- #include "libpq-fe.h" /* for TUPLE */
- bool
- c_overpaid(TUPLE t,/* the current instance of EMP */
- int4 limit)
- {
- bool isnull = false;
- int4 salary;
- salary = (int4) GetAttributeByName(t, "salary", &isnull);
- if (isnull)
- return (false);
- return(salary > limit);
- }
-
-
- GetAttributeByName is the POSTGRES system function that
- returns attributes out of the current instance. It has
- three arguments: the argument of type TUPLE passed into
- the function, the name of the desired attribute, and a
- return parameter that describes whether the attribute
- is null. GetAttributeByName will align data properly
- so you can cast its return value to the desired type.
- For example, if you have an attribute name which is of
- the type char16, the GetAttributeByName call would look
- like:
-
- ...
- str = (char *) GetAttributeByName(t, "name", &isnull)
-
-
- The following query lets POSTGRES know about the
- c_overpaid function:
-
-
* CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool
- AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';
-
- While there are ways to construct new instances or modify
- existing instances from within a C function, these
- are far too complex to discuss in this manual.
- We now turn to the more difficult task of writing
- programming language functions. Be warned: this section
- of the manual will not make you a programmer. You must
- have a good understanding of C (including the use of
- pointers and the malloc memory manager) before trying
- to write C functions for use with POSTGRES.
- While it may be possible to load functions written in
- languages other than C into POSTGRES, this is often
- difficult (when it is possible at all) because other
- languages, such as FORTRAN and Pascal often do not follow
- the same "calling convention" as C. That is, other
- languages do not pass argument and return values
- between functions in the same way. For this reason, we
- will assume that your programming language functions
- are written in C.
- The basic rules for building C functions are as follows:
-
Most of the header (include) files for POSTGRES
- should already be installed in
- /usr/local/postgres95/include (see Figure 2).
- You should always include
-
-
-I/usr/local/postgres95/include
-
- on your cc command lines. Sometimes, you may
- find that you require header files that are in
- the server source itself (i.e., you need a file
- we neglected to install in include). In those
- cases you may need to add one or more of
- -I/usr/local/postgres95/src/backend
- -I/usr/local/postgres95/src/backend/include
- -I/usr/local/postgres95/src/backend/port/<PORTNAME>
- -I/usr/local/postgres95/src/backend/obj
-
-
- (where <PORTNAME> is the name of the port, e.g.,
- alpha or sparc).
-
When allocating memory, use the POSTGRES
- routines palloc and pfree instead of the
- corresponding C library routines malloc and free.
- The memory allocated by palloc will be freed
- automatically at the end of each transaction,
- preventing memory leaks.
-
Always zero the bytes of your structures using
- memset or bzero. Several routines (such as the
- hash access method, hash join and the sort algorithm)
- compute functions of the raw bits contained in
- your structure. Even if you initialize all fields
- of your structure, there may be
- several bytes of alignment padding (holes in the
- structure) that may contain garbage values.
-
Most of the internal POSTGRES types are declared
- in postgres.h, so it's usually a good idea to
- include that file as well.
-
Compiling and loading your object code so that
- it can be dynamically loaded into POSTGRES
- always requires special flags. See Appendix A
- for a detailed explanation of how to do it for
- your particular operating system.
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - THE QUERY LANGUAGE
-
-
-
-
-
-
-
-
11. INTERFACING EXTENSIONS TO INDICES
-
- The procedures described thus far let you define a new
- type, new functions and new operators. However, we
- cannot yet define a secondary index (such as a B-tree,
- R-tree or hash access method) over a new type or its
-
- The right half shows the catalogs
- that we must modify in order to tell POSTGRES how
- to use a user-defined type and/or user-defined operators
- with an index (i.e., pg_am, pg_amop, pg_amproc
and
- pg_opclass
). Unfortunately, there is no simple command
- to do this. We will demonstrate how to modify these
- catalogs through a running example: a new operator
- class for the B-tree access method that sorts integers
- in ascending absolute value order.
-
- The pg_am
class contains one instance for every user
- defined access method. Support for the heap access
- method is built into POSTGRES, but every other access
- method is described here. The schema is
-
-
-
-
amname | name of the access method |
-
-
amowner | object id of the owner's instance in pg_user |
-
-
-
amkind | not used at present, but set to 'o' as a place holder |
-
-
-
amstrategies | number of strategies for this access method (see below) |
-
-
-
amsupport | number of support routines for this access method (see below) |
-
-
-
amgettuple
- aminsert
- ... |
-
procedure identifiers for interface routines to the access
- method. For example, regproc ids for opening, closing, and
- getting instances from the access method appear here. |
-
-
-
-
-
- The object ID of the instance in pg_am
is used as a
- foreign key in lots of other classes. You don't need
- to add a new instance to this class; all you're interested in
- is the object ID of the access method instance
- you want to extend:
-
-
SELECT oid FROM pg_am WHERE amname = 'btree'
-
- +----+
- |oid |
- +----+
- |403 |
- +----+
-
-
- The amstrategies
attribute exists to standardize
- comparisons across data types. For example, B-trees
- impose a strict ordering on keys, lesser to greater.
- Since POSTGRES allows the user to define operators,
- POSTGRES cannot look at the name of an operator (eg, >
- or <) and tell what kind of comparison it is. In fact,
- some access methods don't impose any ordering at all.
- For example, R-trees express a rectangle-containment
- relationship, whereas a hashed data structure expresses
- only bitwise similarity based on the value of a hash
- function. POSTGRES needs some consistent way of taking
- a qualification in your query, looking at the operator
- and then deciding if a usable index exists. This
- implies that POSTGRES needs to know, for example, that
- the <= and > operators partition a B-tree. POSTGRES
- uses strategies to express these relationships between
- operators and the way they can be used to scan indices.
-
- Defining a new set of strategies is beyond the scope of
- this discussion, but we'll explain how B-tree strategies
- work because you'll need to know that to add a new
- operator class. In the pg_am
class, the amstrategies
- attribute is the number of strategies defined for this
- access method. For B-trees, this number is 5. These
- strategies correspond to
-
-
-
-
-
less than or equal | 2 |
-
-
-
greater than or equal | 4 |
-
-
-
-
- The idea is that you'll need to add procedures corresponding
- to the comparisons above to the pg_amop
relation
- (see below). The access method code can use these
- strategy numbers, regardless of data type, to figure
- out how to partition the B-tree, compute selectivity,
- and so on. Don't worry about the details of adding
- procedures yet; just understand that there must be a
- set of these procedures for int2, int4, oid,
and every
- other data type on which a B-tree can operate.
- Sometimes, strategies aren't enough information for the
- system to figure out how to use an index. Some access
- methods require other support routines in order to
- work. For example, the B-tree access method must be
- able to compare two keys and determine whether one is
- greater than, equal to, or less than the other.
- Similarly, the R-tree access method must be able to compute
- intersections, unions, and sizes of rectangles. These
- operations do not correspond to user qualifications in
- SQL queries; they are administrative routines used by
- the access methods, internally.
-
- In order to manage diverse support routines
- consistently across all POSTGRES access methods, pg_am
- includes an attribute called amsupport
. This attribute
- records the number of support routines used by an
- access method. For B-trees, this number is one -- the
- routine to take two keys and return -1, 0, or +1,
- depending on whether the first key is less than, equal
- to, or greater than the second.
[8]
-
- The amstrategies
entry in pg_am is just the number of
- strategies defined for the access method in question.
- The procedures for less than, less equal, and so on
- don't appear in pg_am
. Similarly, amsupport
is just
- the number of support routines required by the access
- method. The actual routines are listed elsewhere.
-
- The next class of interest is pg_opclass. This class
- exists only to associate a name with an oid. In
- pg_amop, every B-tree operator class has a set of
- procedures, one through five, above. Some existing
- opclasses are int2_ops, int4_ops, and oid_ops
. You
- need to add an instance with your opclass name (for
- example, complex_abs_ops
) to pg_opclass
. The oid
of
- this instance is a foreign key in other classes.
-
-
INSERT INTO pg_opclass (opcname) VALUES ('complex_abs_ops');
-
- SELECT oid, opcname
- FROM pg_opclass
- WHERE opcname = 'complex_abs_ops';
-
- +------+--------------+
- |oid | opcname |
- +------+--------------+
- |17314 | int4_abs_ops |
- +------+--------------+
-
-
- Note that the oid for your pg_opclass
instance will be
- different! You should substitute your value for 17314
- wherever it appears in this discussion.
-
- So now we have an access method and an operator class.
- We still need a set of operators; the procedure for
- defining operators was discussed earlier in this manual.
- For the complex_abs_ops operator class on Btrees,
- the operators we require are:
-
-
absolute value less-than
- absolute value less-than-or-equal
- absolute value equal
- absolute value greater-than-or-equal
- absolute value greater-than
-
-
- Suppose the code that implements the functions defined
- is stored in the file
-
- /usr/local/postgres95/src/tutorial/complex.c
-
-
- Part of the code look like this: (note that we will
- only show the equality operator for the rest of the
- examples. The other four operators are very similar.
- Refer to complex.c
or complex.sql
for the details.)
-
-
#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
-
- bool
- complex_abs_eq(Complex *a, Complex *b)
- {
- double amag = Mag(a), bmag = Mag(b);
- return (amag==bmag);
- }
-
-
- There are a couple of important things that are happening below.
-
- First, note that operators for less-than, less-than-or
- equal, equal, greater-than-or-equal, and greater-than
- for int4
are being defined. All of these operators are
- already defined for int4
under the names <, <=, =, >=,
- and >. The new operators behave differently, of
- course. In order to guarantee that POSTGRES uses these
- new operators rather than the old ones, they need to be
- named differently from the old ones. This is a key
- point: you can overload operators in POSTGRES, but only
- if the operator isn't already defined for the argument
- types. That is, if you have < defined for (int4,
- int4), you can't define it again. POSTGRES does not
- check this when you define your operator, so be careful.
- To avoid this problem, odd names will be used for
- the operators. If you get this wrong, the access methods
- are likely to crash when you try to do scans.
-
- The other important point is that all the operator
- functions return Boolean values. The access methods
- rely on this fact. (On the other hand, the support
- function returns whatever the particular access method
- expects -- in this case, a signed integer.)
- The final routine in the file is the "support routine"
- mentioned when we discussed the amsupport attribute of
- the pg_am
class. We will use this later on. For now,
- ignore it.
-
-
CREATE FUNCTION complex_abs_eq(complex, complex)
- RETURNS bool
- AS '/usr/local/postgres95/tutorial/obj/complex.so'
- LANGUAGE 'c';
-
-
- Now define the operators that use them. As noted, the
- operator names must be unique among all operators that
- take two int4
operands. In order to see if the
- operator names listed below are taken, we can do a query on
- pg_operator
:
-
- * this query uses the regular expression operator (~)
- * to find three-character operator names that end in
- * the character &
- */
- SELECT *
- FROM pg_operator
- WHERE oprname ~ '^..&$'::text;
-
-
- to see if your name is taken for the types you want.
- The important things here are the procedure (which are
- the C functions defined above) and the restriction and
- join selectivity functions. You should just use the
- ones used below--note that there are different such
- functions for the less-than, equal, and greater-than
- cases. These must be supplied, or the access method
- will crash when it tries to use the operator. You
- should copy the names for restrict and join, but use
- the procedure names you defined in the last step.
-
- leftarg = complex, rightarg = complex, procedure = complex_abs_eq,
- restrict = eqsel, join = eqjoinsel
- )
-
-
- Notice that five operators corresponding to less, less
- equal, equal, greater, and greater equal are defined.
-
- We're just about finished. the last thing we need to do
- is to update the pg_amop
relation. To do this, we need
- the following attributes:
-
-
-
-
amopid | the oid of the pg_am instance for B-tree
- (== 403, see above) |
-
amopclaid | the oid of the
- pg_opclass instance for int4_abs_ops (==
- whatever you got instead of 17314 , see above) |
-
amopopr | the oid s of the operators for the opclass (which we'll
- get in just a minute) |
-
amopselect, amopnpages | cost functions. |
-
-
-
- The cost functions are used by the query optimizer to
- decide whether or not to use a given index in a scan.
- Fortunately, these already exist. The two functions
- we'll use are btreesel
, which estimates the selectivity
- of the B-tree, and btreenpage
, which estimates the
- number of pages a search will touch in the tree.
-
- So we need the oid
s of the operators we just defined.
- We'll look up the names of all the operators that take
- two int4
s, and pick ours out:
-
-
SELECT o.oid AS opoid, o.oprname
- INTO TABLE complex_ops_tmp
- FROM pg_operator o, pg_type t
- WHERE o.oprleft = t.oid and o.oprright = t.oid
- and t.typname = 'complex';
-
- which returns:
-
- +------+---------+
- |oid | oprname |
- +------+---------+
- |17321 | < |
- +------+---------+
- |17322 | <= |
- +------+---------+
- |17323 | = |
- +------+---------+
- |17324 | >= |
- +------+---------+
- |17325 | > |
- +------+---------+
-
-
- (Again, some of your oid
numbers will almost certainly
- be different.) The operators we are interested in are
- those with oid
s 17321 through 17325. The values you
- get will probably be different, and you should
- substitute them for the values below. We can look at the
- operator names and pick out the ones we just added.
-
- Now we're ready to update pg_amop
with our new operator
- class. The most important thing in this entire
- discussion is that the operators are ordered, from less equal
- through greater equal, in pg_amop
. We add the
- instances we need:
-
-
INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy,
- amopselect, amopnpages)
- SELECT am.oid, opcl.oid, c.opoid, 3,
- 'btreesel'::regproc, 'btreenpage'::regproc
- FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
- WHERE amname = 'btree' and opcname = 'complex_abs_ops'
- and c.oprname = '=';
-
-
- Note the order: "less than" is 1, "less than or equal"
- is 2, "equal" is 3, "greater than or equal" is 4, and
-
- The last step (finally!) is registration of the
- "support routine" previously described in our discussion of
- pg_am
. The oid
of this support routine is stored in
- the pg_amproc
class, keyed by the access method oid
and
- the operator class oid
. First, we need to register the
- function in POSTGRES (recall that we put the C code
- that implements this routine in the bottom of the file
- in which we implemented the operator routines):
-
-
CREATE FUNCTION int4_abs_cmp(int4, int4)
- RETURNS int4
- AS '/usr/local/postgres95/tutorial/obj/complex.so'
- LANGUAGE 'c';
-
- SELECT oid, proname FROM pg_proc WHERE prname = 'int4_abs_cmp';
-
- +------+--------------+
- |oid | proname |
- +------+--------------+
- |17328 | int4_abs_cmp |
- +------+--------------+
-
- (Again, your oid
number will probably be different and
- you should substitute the value you see for the value
- below.) Recalling that the B-tree instance's oid is
- 403 and that of int4_abs_ops
is 17314, we can add the
- new instance as follows:
-
-
INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
- VALUES ('403'::oid, -- btree oid
- '17314'::oid, -- pg_opclass tuple
- '17328'::oid, -- new pg_proc oid
- '1'::int2);
-
-
-
[8] Strictly speaking, this routine can return a negative
-number (< 0), 0, or a non-zero positive number (> 0).
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - THE QUERY LANGUAGE
-
-
-
-
-
-
-
-
9. EXTENDING SQL: OPERATORS
-
- POSTGRES supports left unary, right unary and binary
- operators. Operators can be overloaded, or re-used
- with different numbers and types of arguments. If
- there is an ambiguous situation and the system cannot
- determine the correct operator to use, it will return
- an error and you may have to typecast the left and/or
- right operands to help it understand which operator you
- meant to use.
- To create an operator for adding two complex numbers
- can be done as follows. First we need to create a
- function to add the new types. Then, we can create the
- operator with the function.
-
- CREATE FUNCTION complex_add(complex, complex)
- RETURNS complex
- AS '$PWD/obj/complex.so'
- LANGUAGE 'c';
-
-
- CREATE OPERATOR + (
- leftarg = complex,
- rightarg = complex,
- procedure = complex_add,
- commutator = +
- );
-
-
- We've shown how to create a binary operator here. To
- create unary operators, just omit one of leftarg (for
- left unary) or rightarg (for right unary).
- If we give the system enough type information, it can
- automatically figure out which operators to use.
-
- SELECT (a + b) AS c FROM test_complex;
-
-
- +----------------+
- |c |
- +----------------+
- |(5.2,6.05) |
- +----------------+
- |(133.42,144.95) |
- +----------------+
-
-
-
-
-
-
-
+++ /dev/null
-
-
-
The POSTGRES95 User Manual - EXTENDING SQL: TYPES
-
-
-
-
-
-
-
-
8. EXTENDING SQL: TYPES
-
- As previously mentioned, there are two kinds of types
- in POSTGRES: base types (defined in a programming language)
- and composite types (instances).
- Examples in this section up to interfacing indices can
- be found in complex.sql
and complex.c
. Composite examples
- are in funcs.sql
.
- A user-defined type must always have input and output
- functions. These functions determine how the type
- appears in strings (for input by the user and output to
- the user) and how the type is organized in memory. The
- input function takes a null-delimited character string
- as its input and returns the internal (in memory)
- representation of the type. The output function takes the
- internal representation of the type and returns a null
- delimited character string.
- Suppose we want to define a complex type which represents
- complex numbers. Naturally, we choose to represent a
- complex in memory as the following C structure:
-
-
typedef struct Complex {
- double x;
- double y;
- } Complex;
-
- and a string of the form (x,y) as the external string
- representation.
- These functions are usually not hard to write, especially
- the output function. However, there are a number of points
- to remember.
-
-
When defining your external (string) representation,
- remember that you must eventually write a
- complete and robust parser for that representation
- as your input function!
-
- complex_in(char *str)
- {
- double x, y;
- Complex *result;
-
- if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) {
- elog(WARN, "complex_in: error in parsing
- return NULL;
- }
- result = (Complex *)palloc(sizeof(Complex));
- result->x = x;
- result->y = y;
- return (result);
- }
-
-
- The output function can simply be:
-
- complex_out(Complex *complex)
- {
- char *result;
- if (complex == NULL)
- return(NULL);
- result = (char *) palloc(60);
- sprintf(result, "(%g,%g)", complex->x, complex->y);
- return(result);
- }
-
-
You should try to make the input and output
- functions inverses of each other. If you do
- not, you will have severe problems when you need
- to dump your data into a file and then read it
- back in (say, into someone else's database on
- another computer). This is a particularly common
- problem when floating-point numbers are
- involved.
-
- To define the complex type, we need to create the two
- user-defined functions complex_in and complex_out
- before creating the type:
-
-
CREATE FUNCTION complex_in(opaque)
- RETURNS complex
- AS '/usr/local/postgres95/tutorial/obj/complex.so'
- LANGUAGE 'c';
-
- CREATE FUNCTION complex_out(opaque)
- RETURNS opaque
- AS '/usr/local/postgres95/tutorial/obj/complex.so'
- LANGUAGE 'c';
-
- CREATE TYPE complex (
- internallength = 16,
- input = complex_in,
- output = complex_out
- );
-
-
- As discussed earlier, POSTGRES fully supports arrays of
- base types. Additionally, POSTGRES supports arrays of
- user-defined types as well. When you define a type,
- POSTGRES automatically provides support for arrays of
- that type. For historical reasons, the array type has
- the same name as the user-defined type with the
- underscore character _ prepended.
- Composite types do not need any function defined on
- them, since the system already understands what they
- look like inside.
- The types discussed to this point are all "small"
- objects -- that is, they are smaller than 8KB
[7] in size.
- If you require a larger type for something like a document
- retrieval system or for storing bitmaps, you will
- need to use the POSTGRES large object interface.
-
-
[7] 8 * 1024 == 8192 bytes. In fact, the type must be considerably smaller than 8192 bytes, since the POSTGRES tuple
-and page overhead must also fit into this 8KB limitation.
-The actual value that fits depends on the machine architecture.
-
-
-
-
-
-