This document summarizes new features in PostgreSQL 9, including common table expressions that allow defining in-place data structures using queries, improvements to hot standby and streaming replication for database synchronization, deferrable unique constraints, exclusion constraints for more complex uniqueness checks, and enhancements to PL/PgSQL like unnamed functions and named parameter calls.
2. PostgreSQL 9
About PostgreSQL
• This presentation was inspired by the sessions I‘ve attended at
Fosdem 2010
• PostgreSQL means:
– Standards followed closely
– A true relational database
– Complex, advanced features that puts it far ahead of its competition
– The best tool to use for advanced database-based applications!
• This comes at a cost: it can‘t compete with simpler database
systems on poor hardware and writing „simple things“ tends to get
harder
2
3. PostgreSQL 9
Common Table Expressions
• Available since version 8.4
• They are about defining an in-place data structure by the result of a
query or a query combination
• This data structure can then be queried further
• Recursive join over this data structure is also possible
• Some of this functionality was available before by using:
• Views (named data structures stored into the database backend)
• Subselects
• The join recursion is a brand new feature
3
4. PostgreSQL 9
Common Table Expressions
• Basic usage
WITH [RECURSIVE] name AS
(
SELECT field1 FROM table WHERE field2=“abc”
)
SELECT * FROM name ORDER BY field;
4
5. PostgreSQL 9
Common Table Expressions
• Join recursion
– Assume we have the following corporate structure:
-- department structure represented here is as follows:
--
-- ROOT-+->A-+->B-+->C
-- | |
-- | +->D-+->F
-- +->E-+->G
– We want all the departments under A (or under any department, actually)
5
6. PostgreSQL 9
Common Table Expressions
• Join recursion
CREATE TABLE department (
id INTEGER PRIMARY KEY,
parent_department INTEGER REFERENCES department,
name TEXT
);
INSERT INTO department (id, parent_department, "name")
VALUES
(0, NULL, 'ROOT'),
(1, 0, 'A'),
(2, 1, 'B'),
(3, 2, 'C'),
(4, 2, 'D'),
(5, 0, 'E'),
(6, 4, 'F'),
(7, 5, 'G');
6
7. PostgreSQL 9
Common Table Expressions
• Join recursion
WITH RECURSIVE subdepartment AS
(
-- non-recursive term
SELECT * FROM department WHERE name = 'A'
UNION ALL
-- recursive term
SELECT d.*
FROM
department AS d
JOIN
subdepartment AS sd
ON (d.parent_department = sd.id)
)
SELECT *
FROM subdepartment
ORDER BY name;
7
8. PostgreSQL 9
Common Table Expressions
• Join recursion
– The non-recursive term is optional
– There are some restrictions when it comes to defining the
recursive term:
– No subquery using the recursive term (no double recursion)
– No aggregate functions such as COUNT(*)
– No HAVING, GROUP BY
– No ORDER BY, no LIMIT
– No FULL JOIN
– The recursive term must be on the left hand side:
» JOIN reference ON (recursiveterm.field = reference.field)
• The database engine performs a brute-force, all-terms comparison
so performance can sometimes be an issue
8
9. PostgreSQL 9
Hot Standby and Streaming Replication
• They are both about database synchronization
• Hot Standby is a „push“
• Streaming Replication is a „pull“
• The issue at hand is duplicating the contents of a Master Database
into one or more Slaves
• Hot Standby means that every query ran on Master is also ran on
the Slave; this also works for table locks!
• Streaming replication means that every database transaction is
requested by the Slave and then applied on it
9
10. PostgreSQL 9
Deferrable Unique Constraints
• This query sequence always fails:
# CREATE TABLE test (a INT PRIMARY KEY);
# INSERT INTO test values (1), (2);
# UPDATE test SET a = a + 1;
ERROR: duplicate key value violates unique constraint "test_pkey"
DETAIL: Key (a)=(2) already exists.
• What 9.0 version provides is that the uniqueness constraint may be
checked after running the query, not as the query runs:
# CREATE TABLE test (a INT PRIMARY KEY DEFERRABLE);
10
11. PostgreSQL 9
Exclusion Constraints
• Before 9.0, exclusion would be checked by using operator “=“
• Version 9.0 allows for a more complex approach
# CREATE TABLE reservation
(
room TEXT,
speaker TEXT,
during PERIOD);
ALTER TABLE reservation ADD CONSTRAINT test_exclude EXCLUDE USING gist
(room WITH =,during WITH &&);
• The constraint is defined on 2 fields; the point is not having the
same room reserved at the same time
• The example uses 2 modules from „contrib“ (temporal and gist)
11
12. PostgreSQL 9
Exclusion Constraints
• Example using the previous table definition:
# INSERT INTO reservation (speaker ,room, during) VALUES ( ‘Dan', ‘Flex
Room', period('2010-12-10 12:00:00', '2010-12-10 13:00:00'));
INSERT 0 1
# INSERT INTO reservation (speaker, room, during) VALUES ( ‘Catalin',
‘Presentation', period('2010-12-10 15:00:00', '2010-12-10 16:00:00'));
INSERT 0 1
# INSERT INTO reservation (speaker ,room, during) VALUES ( ‘Andrei', ‘Flex
Room', period('2010-12-10 12:30:00', '2010-12-10 13:00:00'));
ERROR: conflicting key value violates exclusion constraint "test_exclude"
DETAIL: Key (room, during)=(Flex Room, [2010-12-10 12:30:00+02, 2010-12-
10 13:00:00+02)) conflicts with existing key (room, during)=(Flex Room,
[2010-12-10 12:00:00+02, 2010-12-10 13:00:00+02)).
• This feature is available in PostgreSQL only
12
13. Smaller enhancements
• GRANT / REVOKE on Schemas
– PostgreSQL has Databases -> Schemas -> Tables -> Fields
– Until 9.0 you could grant (revoke) rights on Databases and Tables only
– This functionality could be achieved before 9.0 by writing a script
• Faster VACUUM FULL
– This is the more or less equivalent to the OPTIMIZE query in MySQL
– This command used to be pretty slow on large databases
– In 9.0 it works by performing a copy of the database
• Better 64bit support
– 64bit binaries were already available on Linux
– Windows native 64bit binary is the new thing in version 9.0
13
14. PL/PgSQL enhancements
• Unnamed functions
– In 9.0 you can run code snippets in place
– Before 9.0 you had to define a stored procedure and then call it
DO language plpgsql $$
DECLARE
vr record;
BEGIN
FOR vr IN SELECT tablename FROM pg_tables WHERE tableowner = ‘dan' AND schemaname
NOT IN ('pg_catalog','information_schema')
LOOP
EXECUTE 'GRANT SELECT ON ' || vr.tablename || ' TO tester';
END LOOP;
END
$$;
14
15. PL/PgSQL enhancements
• Named parameter calls
– Before 9.0 you had to provide all the function parameters and care for their order,
as provided in the function definition
– Version 8.4 added “default parameters”, allowing skipping certain parameters
(they would be replaced with their default values)
– Example function:
CREATE FUNCTION test (a INT, b TEXT) RETURNS TEXT AS $$
DECLARE
value TEXT;
BEGIN
value := 'a is ' || a::text || ' and b is ' || b;
RETURN value;
END;
$$ LANGUAGE plpgsql;
15
16. PL/PgSQL enhancements
• Named parameter calls
– Before 9.0 you would have called it this way:
SELECT test(1,'foo');
test
-------------------------
a is 1 and b is foo
(1 row)
– Version 9.0 allows this type of function call:
SELECT test( b:='foo', a:=1);
test
-------------------------
a is 1 and b is foo
(1 row)
16