Postgresql information
A small collection of useful postgresql items
The money
datatype is deprecated but there is no way to convert a money value into a numeric which
makes it hard to convert an old database. Here is one way to do it:
CREATE FUNCTION money2numeric(money) RETURNS numeric AS '
SELECT (((get_byte(cash_send($1), 0) & 255) << 24)
|((get_byte(cash_send($1), 1) & 255) << 16)
|((get_byte(cash_send($1), 2) & 255) << 8)
|((get_byte(cash_send($1), 3) & 255)))::numeric * 0.01;
' LANGUAGE sql IMMUTABLE STRICT;
CREATE CAST (money AS numeric) WITH FUNCTION money2numeric(money);
CREATE FUNCTION comma_aggregate(text,text) RETURNS text AS '
SELECT CASE WHEN $1 <> '''' THEN $1 || '', '' || $2
ELSE $2
END;
' LANGUAGE sql IMMUTABLE STRICT;
CREATE AGGREGATE comma (basetype=text, sfunc=comma_aggregate, stype=text, initcond='' );
Here is a faster way to do it (that work in recent versions of postgresql).
CREATE AGGREGATE array_accum (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
which can be used like this:
array_to_string(array_accum(column),',')
This is an example of how one can use a procedure in PostgreSQL 8.0 (and
later) to either insert a new row or update an old row if there already
is one with that key.
CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
CREATE FUNCTION merge_db (key INT, data TEXT) RETURNS VOID AS
$$
BEGIN
LOOP
UPDATE db SET b = data WHERE a = key;
IF found THEN
RETURN;
END IF;
BEGIN
INSERT INTO db(a,b) VALUES (key, data);
RETURN;
EXCEPTION WHEN unique_violation THEN
-- do nothing
END;
END LOOP;
END;
$$
LANGUAGE plpgsql;
SELECT merge_db (1, 'david');
SELECT merge_db (1, 'dennis');
Sometimes if you don't VACUUM often enough the tables use up more disc
space then they need to. The tables are filled with dead tuples that
normal VACUUM can't clean up anymore (VACUUM FULL can. but it lock
tables). This query can help to identify tables with bloat by
comparing the number of live rows with the number of pages
needed to store them.
SELECT oid::regclass, reltuples::numeric, relpages
FROM pg_class
ORDER BY 3 DESC;
A good setup for postgresql is to put the WAL on a ext2 file system
and the rest in a ext3 file system with the options
data=writeback, noatime.
WAL files are preallocated so it should survive a crash even on ext2, at least that's
what's been stated by people that should know. I would still put the WAL on a ext3
as well, with only meta data journaling just to be sure that the file system survive
a crash and no files go missing due to a meta data problem.
Copyright © 2005 Dennis Björklund