PostgreSQL Training,
Consulting & Support
General Bits
By A. Elein Mustain

01-Dec-2003 Issue: 52

Archives | General Tidbits | Google General Bits | Docs | Castellano | PortuguÍs | Subscriptions | Notifications | | Prev

General Bits is a column loosely based on the PostgreSQL mailing list pgsql-general.
To find out more about the pgsql-general list and PostgreSQL, see

My Vacation, Shameless Hype, and Expanding General Bits
Call for Scripts and Articles 30-Nov-2003

Over my short hiatus from General Bits, I've been working on the infrastructure of my business, Varlena, LLC. I have always offered PostgreSQL consulting. Now we've begun offering technical support and I also hope soon to offer training very soon. For more information on Varlena, LLC and our offerings feel free to contact me directly at

As I begin the second year of publishing PostgreSQL General Bits, the information will expand. A wider and deeper script repository is under way which will support PostgreSQL information and Advocacy. I would like to make a call to all authors and technical people to invite you to submit more scripts and articles for inclusion in General Bits. A broader community voice is entirely appropriate and very welcome. If you are concerned about your writing or English skills, editing help is certainly available.

And as always, comments and questions are always welcome.

Editor: elein at
Domain Basics
[GENERAL] Domains (Was [PERFORM] Views With Unions) 01-Aug-2003

A domain is a way to name a default and a set of constraints on a a data type without changing the datatype. The primary purpose of a domain is to consolidate constraint logic for a set of fields which have the same constraints and/or formats. It is usually used to verify formats of well known types of column values.

For example, email addresses are text fields which must be non null and in name@domain format where name is alphanumeric and domain is alphanumeric with a valid trailing, e.g. .com, .org, .net, etc. To check this format, write a function which returns a boolean to determine if the address is in its proper format. (The function is best written in plperl and is left as an exercise to the reader--send in your best effort for future publication :-)

Usually, one would then define a table using email as follows.

	create table addressbook (
		email	text NOT NULL CHECK ( emailformatok( email ) ),
However if you use email routinely in a number of tables you can define the domain and then use that to ensure consistency among your tables. Note that when you define domains, use VALUE instead of the column name in the check clause.
	create domain email_d AS text DEFAULT 'none'
	   CONSTRAINT email_domain check( emailcheckok( VALUE) );
	create table addressbook (
	   email email_d,

Domains are not User Defined Types, however, in practice they are cousins. Domains inherit all of the casts and functions of the underlying data type. For example, if you define a domain based on an integer, you can still do comparisons and order by on the domain as if it were an integer. So a domain is an inherited data type as opposed to a newly created user defined type.

You can define functions on domains, but there is a bug/caveat. If you declare your function to return a domain type, the check is not executed on return. You are able to return values that do not meet the domain's constraints. (Question pending in pgsql-general.)

Another reason to use domains is that you can ALTER them. You can change the check constraint as necessary in one place. You cannot, however, alter the underlying data type of the domain.

In the Illustra and Informix ORDBMS, these domains were defined as CREATE TYPE bar UNDER TYPE foo; And Jim Melton warns that domains created in the PostgreSQL style may be deprecated in future SQL standards. I expect the standard will lean toward create types UNDER types.

Contributors: elein at Francisco J Reyes fran at, Christopher Browne cbbrowne at, Stephan Szabo sszabo at, Ron Johnson ron.l.johnson at, Jochem van Dieten jochemd at, Tom Lane tgl at
Empty Arrays
[GENERAL] Declaring empty, non-NULL array in plpgsql 23-Nov-2003

An empty array literal is quoted curly brackets: '{}' With an empty array declared correctly in SQL or plpgsql (for example) you can then append to the array as you like.

In this example, the varchar array is declared as empty and then is appended to with each number from 1 to the number passed into the routine. Notice this nice syntax of the FOR LOOP and that a simple concatenation function can be used to add array elements at the end of the array.

	regression=# create function foo(int) returns varchar[] as '
	regression'# declare
	regression'#   arr varchar[] := ''{}'';
	regression'# begin
	regression'#   for i in 1..$1 loop
	regression'#     arr = arr || i::varchar;
	regression'#   end loop;
	regression'# return arr;
	regression'# end' language plpgsql;
	regression=# select foo(10);
	(1 row)

With 7.4 available, there are many more things you can do with arrays easily. Some of these were previously covered in General Bits, and more examples will be available.

Contributors: CSN cool_screen_name90001 at, Joe Conway mail at, Tom Lane tgl at
Syntax for Indexing Array Elements
[GENERAL] Index on array element 24-Nov-2003

It is possible to index on a specific array element in both 7.3 and 7.4. In 7.3 one would use a simple functional index and pass to it the array. This is a little clunky. In 7.4 you can index on the element(s) directly or in an expression.

In 7.3, for example, create a function which returns the first element of the array:

	create function first(text[]) 
	returns text 
	as 'select $1 [1]'
	strict immutable language 'sql';
The index, then would look like this:
	create index foodex on foo (first(textarray));

In 7.4, the only tricky part is an extra set of parentheses. The extra parentheses are needed to isolate the expression from a possible operator class specification in the main parentheses. In 7.4, you can index an array element directly like this:

	create index foodex on foo ((textarray[3]));

Contributors: Steve Crawford scrawford at, Tom Lane tgl at, Randolf Richardson rr at, Greg Stark gsstark at
Jonathan Bartlett's Explanation of WAL
[GENERAL] What is WAL used for? 26-Nov-2003

In response to the question, "What is WAL [write ahead logging] used for?" Jonathan Bartlett wrote a very nice, understandable description of WAL. I'm including it here with very little editing.

WAL is write-ahead logging. Basically, before the database actually performs an operation, it writes in a log what it's about to do. Then, it goes and does it. This ensures data consistency. Let's say that the computer was powered off suddenly. There are several points that could happen:

1) Before a write - in this case the database would be fine with or without write-ahead logging.

2) During a write - without write-ahead logging, if the machine is powered off during a write, the database has no way of knowing what remained to be written, or what was being written. With PostgreSQL, this is further broken down into two possibilities:

  • The power-off occurred while it was writing to the log - in this case, the log is rolled back. The database is unaffected because the data was never written to the database proper.
  • The power-off occurred after writing to the log, while writing to disk - in this case, PostgreSQL can simply read from the log what was supposed to be written, and complete the write.

3) After a write - again, this does not affect PostgreSQL either with or without WAL.

In addition, WAL increases PostgreSQL's efficiency, because it can delay random-access writes to disk, and just do sequential writes to the log for a long time. This reduces the amount of head-seek the disk are doing. If you store your WAL files on a different disk, you get even more speed advantages.

Contributors: Relaxin noname at, Jonathan Bartlett johnnyb at, Thierry Missimilly THIERRY.MISSIMILLY at BULL.NET

Comments and Corrections are welcome. Suggestions and contributions of items are also welcome. Send them in!
Copyright A. Elein Mustain 2003, 2004, 2005, 2006, 2007, 2008, 2009

Search General Bits & Search WWW