-
+
PL/pgSQL - SQL Procedural Language
While running
psql, you can load or reload such
- a function definition file with
+ a function definition file with:
\i filename.sql
approach, you never double any quote marks, but instead take care to
choose a different dollar-quoting delimiter for each level of
nesting you need. For example, you might write the CREATE
- FUNCTION command as
+ FUNCTION command as:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$
....
a_output := ''Blah'';
SELECT * FROM users WHERE f_name=''foobar'';
- In the dollar-quoting approach, you'd just write
+ In the dollar-quoting approach, you'd just write:
a_output := 'Blah';
SELECT * FROM users WHERE f_name='foobar';
AND name LIKE 'foobar' AND xyz.
- In the dollar-quoting approach, you'd write
+ In the dollar-quoting approach, you'd write:
a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
AND name LIKE 'foobar'.
- In the dollar-quoting approach, this becomes
+ In the dollar-quoting approach, this becomes:
a_output := a_output || $$ AND name LIKE 'foobar'$$
- In the dollar-quoting approach, this becomes
+ In the dollar-quoting approach, this becomes:
a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$
|| referrer_keys.key_string || $$'
name ALIAS FOR $n;
- The same example in this style looks like
+ The same example in this style looks like:
CREATE FUNCTION sales_tax(real) RETURNS real AS $$
DECLARE
$$ LANGUAGE plpgsql;
- and
+ and:
CREATE FUNCTION logfunc2(logtxt text) RETURNS timestamp AS $$
This two-step process allows
PL/pgSQL to plan the query just once
and re-use the plan on subsequent executions. As an example,
- if you write
+ if you write:
DECLARE
key TEXT;
...
UPDATE mytab SET val = val + delta WHERE id = key;
- the query text seen by the main SQL engine will look like
+ the query text seen by the main SQL engine will look like:
UPDATE mytab SET val = val + $1 WHERE id = $2;
Note that dollar quoting is only useful for quoting fixed text.
- It would be a very bad idea to try to do the above example as
+ It would be a very bad idea to try to do the above example as:
EXECUTE 'UPDATE tbl SET '
|| quote_ident(colname)
This example uses exception handling to perform either
- UPDATE> or INSERT>, as appropriate.
+ UPDATE> or INSERT>, as appropriate:
CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
In
PL/pgSQL>, when an exception is caught by an
EXCEPTION> clause, all database changes since the block's
BEGIN> are automatically rolled back. That is, the behavior
- is equivalent to what you'd get in Oracle with
+ is equivalent to what you'd get in Oracle with:
BEGIN
-
+
Queries
- A simple kind of query has the form
+ A simple kind of query has the form:
SELECT * FROM table1;
- To put this together, assume we have tables t1
+ To put this together, assume we have tables t1:
num | name
-----+------
2 | b
3 | c
- and t2
+ and t2:
num | value
-----+-------
The alias becomes the new name of the table reference for the
current query — it is no longer possible to refer to the table
- by the original name. Thus
+ by the original name. Thus:
SELECT * FROM my_table AS m WHERE my_table.a > 5;
off> (as it is by default). If it is on>,
an implicit table reference will be added to the
FROM clause, so the query is processed as if
- it were written as
+ it were written as:
SELECT * FROM my_table AS m, my_table AS my_table WHERE my_table.a > 5;
Table aliases are mainly for notational convenience, but it is
- necessary to use them when joining a table to itself, e.g.,
+ necessary to use them when joining a table to itself, e.g.:
SELECT * FROM people AS mother JOIN people AS child ON mother.id = child.mother_id;
When an alias is applied to the output of a JOIN>
clause, using any of these forms, the alias hides the original
- names within the JOIN>. For example,
+ names within the JOIN>. For example:
SELECT a.* FROM my_table AS a JOIN your_table AS b ON ...
- is valid SQL, but
+ is valid SQL, but:
SELECT a.* FROM (my_table AS a JOIN your_table AS b ON ...) AS c
FROM a, b WHERE a.id = b.id AND b.val > 5
- and
+ and:
FROM a INNER JOIN b ON (a.id = b.id) WHERE b.val > 5
- or perhaps even
+ or perhaps even:
FROM a NATURAL JOIN b WHERE b.val > 5
Here is another example: it calculates the total sales for each
- product (rather than the total sales on all products).
+ product (rather than the total sales on all products):
SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
FROM products p LEFT JOIN sales s USING (product_id)
If more than one table has a column of the same name, the table
- name must also be given, as in
+ name must also be given, as in:
SELECT tbl1.a, tbl2.a, tbl1.b FROM ...
, sort_expression2 ASC | DESC NULLS { FIRST | LAST } ...
The sort expression(s) can be any expression that would be valid in the
- query's select list. An example is
+ query's select list. An example is:
SELECT a, b FROM table1 ORDER BY a + b, c;
For backwards compatibility with the SQL92 version of the standard,
a sort_expression> can instead be the name or number
- of an output column, as in
+ of an output column, as in:
SELECT a + b AS sum, c FROM table1 ORDER BY sum;
SELECT a, max(b) FROM table1 GROUP BY a ORDER BY 1;
- As an example,
-
+ As an example:
VALUES (1, 'one'), (2, 'two'), (3, 'three');
will return a table of two columns and three rows. It's effectively
- equivalent to
-
+ equivalent to:
SELECT 1 AS column1, 'one' AS column2
UNION ALL
To give a schema-qualified operator name in
class="parameter">com_op or the other optional
- arguments, use the OPERATOR()> syntax, for example
+ arguments, use the OPERATOR()> syntax, for example:
COMMUTATOR = OPERATOR(myschema.===) ,
command, the NOTIFY command will be executed
unconditionally, that is, the NOTIFY will be
issued even if there are not any rows that the rule should apply
- to. For example, in
+ to. For example, in:
CREATE RULE notify_me AS ON UPDATE TO mytable DO ALSO NOTIFY mytable;
- Although you cannot update a sequence directly, you can use a query like
+ Although you cannot update a sequence directly, you can use a query like:
SELECT * FROM name;
Define a unique table constraint for the table
films. Unique table constraints can be defined
- on one or more columns of the table.
+ on one or more columns of the table:
CREATE TABLE films (
If the internal structure of box were an array of four
- float4> elements, we might instead use
+ float4> elements, we might instead use:
CREATE TYPE box (
INTERNALLENGTH = 16,
Be careful that the names and types of the view's columns will be
- assigned the way you want. For example,
+ assigned the way you want. For example:
CREATE VIEW vista AS SELECT 'Hello World';
is bad form in two ways: the column name defaults to ?column?>,
and the column data type defaults to unknown>. If you want a
- string literal in a view's result, use something like
+ string literal in a view's result, use something like:
CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
PostgreSQL lets you reference columns of
other tables in the WHERE> condition by specifying the
other tables in the USING clause. For example,
- to delete all films produced by a given producer, one can do
+ to delete all films produced by a given producer, one can do:
DELETE FROM films USING producers
WHERE producer_id = producers.id AND producers.name = 'foo';
What is essentially happening here is a join between films>
and producers>, with all successfully joined
films> rows being marked for deletion.
- This syntax is not standard. A more standard way to do it is
+ This syntax is not standard. A more standard way to do it is:
DELETE FROM films
WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');
Examples
- The following example traverses a table using a cursor.
+ The following example traverses a table using a cursor:
BEGIN WORK;
The above example display would be seen by user miriam> after
- creating table mytable> and doing
+ creating table mytable> and doing:
GRANT SELECT ON mytable TO PUBLIC;
-
+
$ pg_restore -l db.dump > db.list
- The listing file consists of a header and one line for each item, e.g.,
+ The listing file consists of a header and one line for each item, e.g.:
;
; Archive created at Fri Jul 28 22:28:36 2000
- Lines in the file can be commented out, deleted, and reordered. For example,
+ Lines in the file can be commented out, deleted, and reordered. For example:
10; 145433 TABLE map_resolutions postgres
;2; 145344 TABLE species postgres
An alternative way to specify connection parameters is in a
conninfo string, which is used instead of a
database name. This mechanism give you very wide control over the
- connection. For example,
+ connection. For example:
$ psql "service=myservice sslmode=require"
In normal operation,
psql provides a
prompt with the name of the database to which
psql is currently connected, followed by
- the string =>. For example,
+ the string =>. For example:
$ psql testdb
Welcome to psql &version;, the PostgreSQL interactive terminal.
The file name that will be used to store the history list. The default
- value is ~/.psql_history. For example, putting
+ value is ~/.psql_history. For example, putting:
\set HISTFILE ~/.psql_history- :DBNAME
variables is that you can substitute (interpolate
)
them into regular
SQL statements. The syntax for
this is again to prepend the variable name with a colon
- (:).
+ (:):
testdb=> \set foo 'my_table'
testdb=> SELECT * FROM :foo;
inserted
OID in subsequent statements to build a
foreign key scenario. Another possible use of this mechanism is to
copy the contents of a file into a table column. First load the file into a
- variable and then proceed as above.
+ variable and then proceed as above:
testdb=> \set content '''' `cat my_file.txt` ''''
testdb=> INSERT INTO my_table VALUES (:content);
non-printing control characters must be designated as invisible
by surrounding them with %[ and
%]. Multiple pairs of these can occur within
- the prompt. For example,
+ the prompt. For example:
testdb=> \set PROMPT1 '%[%033[1;33;40m%]%n@%/%R%[%033[0m%]%# '
compatibility this is still supported to some extent,
but we are not going to explain the details here as this use is
discouraged. If you get strange messages, keep this in mind.
- For example
+ For example:
testdb=> \foo
Field separator is "oo".
ORDER BY> (see above). Note that the first
row of each set is unpredictable unless ORDER
BY> is used to ensure that the desired row appears first. For
- example,
+ example:
SELECT DISTINCT ON (location) location, time, report
FROM weather_reports
Avoid locking a row and then modifying it within a later savepoint or
PL/pgSQL exception block. A subsequent
- rollback would cause the lock to be lost. For example,
+ rollback would cause the lock to be lost. For example:
BEGIN;
SELECT * FROM mytable WHERE key = 1 FOR UPDATE;
Attempt to insert a new stock item along with the quantity of stock. If
the item already exists, instead update the stock count of the existing
- item. To do this without failing the entire transaction, use savepoints.
+ item. To do this without failing the entire transaction, use savepoints:
BEGIN;
-- other operations
This will return a table of two columns and three rows. It's effectively
- equivalent to
+ equivalent to:
SELECT 1 AS column1, 'one' AS column2
-
+
Regression Tests
The random test script is intended to produce
random results. In rare cases, this causes the random regression
- test to fail. Typing
+ test to fail. Typing:
diff results/random.out expected/random.out
float8-small-is-zero.out, which includes
the results to be expected on these systems. To silence the bogus
failure
message on OpenBSD
- platforms, resultmap includes
+ platforms, resultmap includes:
float8/i.86-.*-openbsd=float8-small-is-zero
-
+
+
Composite Types
Whenever you create a table, a composite type is also automatically
created, with the same name as the table, to represent the table's
- row type. For example, had we said
+ row type. For example, had we said:
CREATE TABLE inventory_item (
name text,
'( val1 , val2 , ... )'
- An example is
+ An example is:
'("fuzzy dice",42,1.99)'
ROW('', 42, NULL)
The ROW keyword is actually optional as long as you have more than one
- field in the expression, so these can simplify to
+ field in the expression, so these can simplify to:
('fuzzy dice', 42, 1.99)
('', 42, NULL)
Similar syntactic issues apply whenever you select a field from a composite
value. For instance, to select just one field from the result of a function
- that returns a composite value, you'd need to write something like
+ that returns a composite value, you'd need to write something like:
SELECT (my_func(...)).field FROM ...
items. Whitespace outside the parentheses is ignored, but within the
parentheses it is considered part of the field value, and might or might not be
significant depending on the input conversion rules for the field data type.
- For example, in
+ For example, in:
'( 42)'
backslashes you need (assuming escape string syntax is used).
For example, to insert a text> field
containing a double quote and a backslash in a composite
- value, you'd need to write
+ value, you'd need to write:
INSERT ... VALUES (E'("\\"\\\\")');
-
+
The Rule System
Views in
PostgreSQL are implemented
using the rule system. In fact, there is essentially no difference
- between
+ between:
CREATE VIEW myview AS SELECT * FROM mytab;
- compared against the two commands
+ compared against the two commands:
CREATE TABLE myview (same column list as mytab);
For the example, we need a little min function that
-returns the lower of 2 integer values. We create that as
+returns the lower of 2 integer values. We create that as:
CREATE FUNCTION min(integer, integer) RETURNS integer AS $$
- The views are created as
+ The views are created as:
CREATE VIEW shoe AS
This is the simplest SELECT you can do on our
views, so we take this opportunity to explain the basics of view
rules. The SELECT * FROM shoelace was
- interpreted by the parser and produced the query tree
+ interpreted by the parser and produced the query tree:
SELECT shoelace.sl_name, shoelace.sl_avail,
range table and checks if there are rules
for any relation. When processing the range table entry for
shoelace (the only one up to now) it finds the
- _RETURN rule with the query tree
+ _RETURN rule with the query tree:
SELECT s.sl_name, s.sl_avail,
To expand the view, the rewriter simply creates a subquery range-table
entry containing the rule's action query tree, and substitutes this
range table entry for the original one that referenced the view. The
- resulting rewritten query tree is almost the same as if you had typed
+ resulting rewritten query tree is almost the same as if you had typed:
SELECT shoelace.sl_name, shoelace.sl_avail,
- The output of the parser this time is the query tree
+ The output of the parser this time is the query tree:
SELECT shoe_ready.shoename, shoe_ready.sh_avail,
The first rule applied will be the one for the
shoe_ready view and it results in the
- query tree
+ query tree:
SELECT shoe_ready.shoename, shoe_ready.sh_avail,
relation points to the range-table entry where the result should
go. Everything else is absolutely the same. So having two tables
t1> and t2> with columns a> and
- b>, the query trees for the two statements
+ b>, the query trees for the two statements:
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
execution plans: They are both joins over the two tables. For the
UPDATE the missing columns from t1> are added to
the target list by the planner and the final query tree will read
- as
+ as:
UPDATE t1 SET a = t1.a, b = t2.b FROM t2 WHERE t1.a = t2.a;
and thus the executor run over the join will produce exactly the
- same result set as a
+ same result set as a:
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
file block number and position in the block for the row. Knowing
the table, the
CTID> can be used to retrieve the
original row of t1> to be updated. After adding the
-
CTID> to the target list, the query actually looks like
+
CTID> to the target list, the query actually looks like:
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
How Update Rules Work
- Keep the syntax
+ Keep the syntax:
CREATE [ OR REPLACE ] RULE name AS ON event
That's what we expected. What happened in the background is the following.
- The parser created the query tree
+ The parser created the query tree:
UPDATE shoelace_data SET sl_avail = 6
There is a rule log_shoelace that is ON UPDATE> with the rule
- qualification expression
+ qualification expression:
NEW.sl_avail <> OLD.sl_avail
- and the action
+ and the action:
INSERT INTO shoelace_log VALUES (
The substitutions and the added qualifications
- ensure that, if the original query would be, say,
+ ensure that, if the original query would be, say:
UPDATE shoelace_data SET sl_color = 'green'
tree does not contain a target list entry for
sl_avail>, so NEW.sl_avail> will get
replaced by shoelace_data.sl_avail>. Thus, the extra
- command generated by the rule is
+ command generated by the rule is:
INSERT INTO shoelace_log VALUES (
It will also work if the original query modifies multiple rows. So
- if someone issued the command
+ if someone issued the command:
UPDATE shoelace_data SET sl_avail = 0
four rows in fact get updated (sl1>, sl2>, sl3>, and sl4>).
But sl3> already has sl_avail = 0>. In this case, the original
query trees qualification is different and that results
- in the extra query tree
+ in the extra query tree:
INSERT INTO shoelace_log
A simple way to protect view relations from the mentioned
possibility that someone can try to run INSERT,
UPDATE, or DELETE on them is
- to let those query trees get thrown away. So we could create the rules
+ to let those query trees get thrown away. So we could create the rules:
CREATE RULE shoe_ins_protect AS ON INSERT TO shoe
you need to make the rules include RETURNING> clauses that
compute the view rows. This is usually pretty trivial for views on a
single table, but it's a bit tedious for join views such as
- shoelace. An example for the insert case is
+ shoelace. An example for the insert case is:
CREATE RULE shoelace_ins AS ON INSERT TO shoelace
It's a long way from the one INSERT ... SELECT
to these results. And the description of the query-tree
transformation will be the last in this chapter. First, there is
- the parser's output
+ the parser's output:
INSERT INTO shoelace_ok
Now the first rule shoelace_ok_ins is applied and turns this
- into
+ into:
UPDATE shoelace
and throws away the original INSERT on
shoelace_ok. This rewritten query is passed to
the rule system again, and the second applied rule
- shoelace_upd produces
+ shoelace_upd produces:
UPDATE shoelace_data
Again it's an INSTEAD> rule and the previous query tree is trashed.
Note that this query still uses the view shoelace.
But the rule system isn't finished with this step, so it continues
- and applies the _RETURN rule on it, and we get
+ and applies the _RETURN rule on it, and we get:
UPDATE shoelace_data
Finally, the rule log_shoelace gets applied,
- producing the extra query tree
+ producing the extra query tree:
INSERT INTO shoelace_log
So we end up with two final query trees that are equivalent to the
INSERT INTO shoelace_log
We would like to make a view to check which
shoelace entries do not fit any shoe in color.
- The view for this is
+ The view for this is:
CREATE VIEW shoelace_mismatch AS
(SELECT shoename FROM shoe WHERE slcolor = sl_color);
- Its output is
+ Its output is:
SELECT * FROM shoelace_mismatch;
Now we want to set it up so that mismatching shoelaces that are
not in stock are deleted from the database.
To make it a little harder for
PostgreSQL,
- we don't delete it directly. Instead we create one more view
+ we don't delete it directly. Instead we create one more view:
CREATE VIEW shoelace_can_delete AS
Since the trigger is called for each individual row deleted from
computer>, it can prepare and save the plan for this
command and pass the hostname> value in the
- parameter. The rule would be written as
+ parameter. The rule would be written as:
CREATE RULE computer_del AS ON DELETE TO computer
- Now we look at different types of deletes. In the case of a
+ Now we look at different types of deletes. In the case of a:
DELETE FROM computer WHERE hostname = 'mypc.local.net';
the table computer> is scanned by index (fast), and the
command issued by the trigger would also use an index scan (also fast).
- The extra command from the rule would be
+ The extra command from the rule would be:
DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
With the next delete we want to get rid of all the 2000 computers
where the hostname> starts with
old>. There are two possible commands to do that. One
- is
+ is:
DELETE FROM computer WHERE hostname >= 'old'
AND hostname < 'ole'
- The command added by the rule will be
+ The command added by the rule will be:
DELETE FROM software WHERE computer.hostname >= 'old' AND computer.hostname < 'ole'
-> Index Scan using comp_hostidx on computer
- The other possible command is
+ The other possible command is:
DELETE FROM computer WHERE hostname ~ '^old';
- The last command we look at is
+ The last command we look at is:
DELETE FROM computer WHERE manufacturer = 'bim';
Again this could result in many rows to be deleted from
computer>. So the trigger will again run many commands
- through the executor. The command generated by the rule will be
+ through the executor. The command generated by the rule will be:
DELETE FROM software WHERE computer.manufacturer = 'bim'
-
+
Operating System Environment
In OS X 10.3.9 and later, instead of editing /etc/rc>
you can create a file named /etc/sysctl.conf>,
- containing variable assignments such as
+ containing variable assignments such as:
kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
In the default configuration, only 512 kB of shared memory per
segment is allowed. To increase the setting, first change to the
directory /etc/conf/cf.d>. To display the current value of
- SHMMAX>, run
+ SHMMAX>, run:
./configure -y SHMMAX
- To set a new value for SHMMAX>, run
+ To set a new value for SHMMAX>, run:
./configure SHMMAX=value>
On
UnixWare> 7, the maximum size for shared
memory segments is only 512 kB in the default configuration.
- To display the current value of SHMMAX>, run
+ To display the current value of SHMMAX>, run:
/etc/conf/bin/idtune -g SHMMAX
which displays the current, default, minimum, and maximum
values. To set a new value for SHMMAX>,
- run
+ run:
/etc/conf/bin/idtune SHMMAX value>
password can be left blank. The program will generate a key that is
passphrase protected; it will not accept a passphrase that is less
than four characters long. To remove the passphrase (as you must if
- you want automatic start-up of the server), run the commands
+ you want automatic start-up of the server), run the commands:
openssl rsa -in privkey.pem -out server.key
rm privkey.pem
- Enter the old passphrase to unlock the existing key. Now do
+ Enter the old passphrase to unlock the existing key. Now do:
openssl req -x509 -in server.req -text -key server.key -out server.crt
chmod og-rwx server.key
-
+
PostgreSQL Coding Conventions
The text browsing tools
more and
+
less can be invoked as
:
more -x4
less -x4
There is an older function elog> that is still heavily used.
- An elog> call
+ An elog> call:
elog(level, "format string", ...);
- is exactly equivalent to
+ is exactly equivalent to:
ereport(level, (errmsg_internal("format string", ...)));
- For example, instead of
+ For example, instead of:
IpcMemoryCreate: shmget(key=%d, size=%u, 0%o) failed: %m
(plus a long addendum that is basically a hint)
- write
+ write:
Primary: could not create shared memory segment: %m
Detail: Failed syscall was shmget(key=%d, size=%u, 0%o).
- There is a nontrivial semantic difference between sentences of the form
+ There is a nontrivial semantic difference between sentences of the form:
could not open file "%s": %m
-and
+and:
cannot open file "%s"
-
+
Server Programming Interface
for all rows that it applies to. If
count
is greater than 0, then the number of rows for which the command
will be executed is restricted (much like a
- LIMIT clause). For example,
+ LIMIT clause). For example:
SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5);
During the execution of an SQL command, any data changes made by
the command are invisible to the command itself. For
- example, in
+ example, in:
INSERT INTO a SELECT * FROM a;
-
+
SQL Syntax
of SQL commands
- Identifier and key word names are case insensitive. Therefore
+ Identifier and key word names are case insensitive. Therefore:
UPDATE MY_TABLE SET A = 5;
- can equivalently be written as
+ can equivalently be written as:
uPDaTE my_TabLE SeT a = 5;
A convention often used is to write key words in upper
- case and names in lower case, e.g.,
+ case and names in lower case, e.g.:
UPDATE my_table SET a = 5;
SELECT 'foo'
'bar';
- is equivalent to
+ is equivalent to:
SELECT 'foobar';
- but
+ but:
SELECT 'foo' 'bar';
force a numeric value to be interpreted as a specific data type
For example, you can force a numeric value to be treated as type
- real> (float4>) by writing
+ real> (float4>) by writing:
REAL '1.23' -- string style
>> have a different precedence than the Boolean
operators <=> and >=>. Also, you will
sometimes need to add parentheses when using combinations of
- binary and unary operators. For instance
+ binary and unary operators. For instance:
SELECT 5 ! - 6;
- will be parsed as
+ will be parsed as:
SELECT 5 ! (- 6);
because the parser has no idea — until it is too late
— that ! is defined as a postfix operator,
not an infix one. To get the desired behavior in this case, you
- must write
+ must write:
SELECT (5 !) - 6;
When a schema-qualified operator name is used in the
- OPERATOR> syntax, as for example in
+ OPERATOR> syntax, as for example in:
SELECT 3 OPERATOR(pg_catalog.+) 4;
For example, consider the definition of a function,
- dept, as
+ dept, as:
CREATE FUNCTION dept(text) RETURNS dept
to be subscripted is just a column reference or positional parameter.
Also, multiple subscripts can be concatenated when the original array
is multidimensional.
- For example,
+ For example:
mytable.arraycolumn[4]
In general the row expression must be
parenthesized, but the parentheses can be omitted when the expression
to be selected from is just a table reference or positional parameter.
- For example,
+ For example:
mytable.mycolumn
consists of the key word ARRAY, a left square bracket
[>, one or more expressions (separated by commas) for the
array element values, and finally a right square bracket ]>.
- For example,
+ For example:
SELECT ARRAY[1,2,3+4];
array
for its member fields. A row constructor consists of the key word
ROW, a left parenthesis, zero or more
expressions (separated by commas) for the row field values, and finally
- a right parenthesis. For example,
+ a right parenthesis. For example:
SELECT ROW(1,2.5,'this is a test');
in a composite-type table column, or to be passed to a function that
accepts a composite parameter. Also,
it is possible to compare two row values or test a row with
- IS NULL> or IS NOT NULL>, for example
+ IS NULL> or IS NOT NULL>, for example:
SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');
Furthermore, if the result of an expression can be determined by
evaluating only some parts of it, then other subexpressions
- might not be evaluated at all. For instance, if one wrote
+ might not be evaluated at all. For instance, if one wrote:
SELECT true OR somefunc();
then somefunc() would (probably) not be called
- at all. The same would be the case if one wrote
+ at all. The same would be the case if one wrote:
SELECT somefunc() OR true;
-
+
Triggers
any normal arguments, but it is passed a context>
pointer pointing to a TriggerData> structure. C
functions can check whether they were called from the trigger
- manager or not by executing the macro
+ manager or not by executing the macro:
CALLED_AS_TRIGGER(fcinfo)
- which expands to
+ which expands to:
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
-
+
Database Roles and Privileges
as the initial role name for a database connection. A role with
the LOGIN> attribute can be considered the same thing
as a database user>. To create a role with login privilege,
- use either
+ use either:
CREATE ROLE name LOGIN;
CREATE USER name;
configuration settings described in
linkend="runtime-config">. For example, if for some reason you
want to disable index scans (hint: not a good idea) anytime you
- connect, you can use
+ connect, you can use:
ALTER ROLE myname SET enable_indexscan TO off;
To assign privileges, the GRANT command is
used. So, if joe is an existing role, and
accounts is an existing table, the privilege to
- update the table can be granted with
+ update the table can be granted with:
GRANT UPDATE ON accounts TO joe;
considered owned by the group role not the login role. Second, member
roles that have the INHERIT> attribute automatically have use of
privileges of roles they are members of. As an example, suppose we have
- done
+ done:
CREATE ROLE joe LOGIN INHERIT;
CREATE ROLE admin NOINHERIT;
granted to wheel> are not available, because even though
joe> is indirectly a member of wheel>, the
membership is via admin> which has the NOINHERIT>
- attribute. After
+ attribute. After:
SET ROLE admin;
the session would have use of only those privileges granted to
- admin>, and not those granted to joe>. After
+ admin>, and not those granted to joe>. After:
SET ROLE wheel;
the session would have use of only those privileges granted to
wheel>, and not those granted to either joe>
or admin>. The original privilege state can be restored
- with any of
+ with any of:
SET ROLE joe;
SET ROLE NONE;
-
+
User-Defined Aggregates
A function written in C can detect that it is being called as an
aggregate transition or final function by seeing if it was passed
an AggState> node as the function call context>,
- for example by
+ for example by:
if (fcinfo->context && IsA(fcinfo->context, AggState))
-
+
User-Defined Functions
In practice one would probably like a more useful result from the
function than a constant 1, so a more likely definition
- is
+ is:
CREATE FUNCTION tf1 (integer, numeric) RETURNS numeric AS $$
When creating a family of overloaded functions, one should be
careful not to create ambiguities. For instance, given the
- functions
+ functions:
CREATE FUNCTION test(int, real) RETURNS ...
CREATE FUNCTION test(smallint, double precision) RETURNS ...
(usually the internal one). The alternative form of the
AS> clause for the SQL CREATE
FUNCTION command decouples the SQL function name from
- the function name in the C source code. For instance,
+ the function name in the C source code. For instance:
CREATE FUNCTION test(int) RETURNS int
AS 'filename>', 'test_1arg'
The version-1 calling convention relies on macros to suppress most
of the complexity of passing arguments and results. The C declaration
- of a version-1 function is always
+ of a version-1 function is always:
Datum funcname(PG_FUNCTION_ARGS)
- In addition, the macro call
+ In addition, the macro call:
PG_FUNCTION_INFO_V1(funcname);
- Suppose we want to write a function to answer the query
+ Suppose we want to write a function to answer the query:
SELECT name, c_overpaid(emp, 1500) AS overpaid
Several helper functions are available for setting up the needed
TupleDesc>. The recommended way to do this in most
- functions returning composite values is to call
+ functions returning composite values is to call:
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,
Oid *resultTypeId,
Older, now-deprecated functions for obtaining
- TupleDesc>s are
+ TupleDesc>s are:
TupleDesc RelationNameGetTupleDesc(const char *relname)
to get a TupleDesc> for the row type of a named relation,
- and
+ and:
TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
- Once you have a TupleDesc>, call
+ Once you have a TupleDesc>, call:
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
- if you plan to work with Datums, or
+ if you plan to work with Datums, or:
AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
- When working with Datums, use
+ When working with Datums, use:
HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)
- When working with C strings, use
+ When working with C strings, use:
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Once you have built a tuple to return from your function, it
- must be converted into a Datum>. Use
+ must be converted into a Datum>. Use:
HeapTupleGetDatum(HeapTuple tuple)
An
SRF> uses several functions and macros that
automatically manipulate the FuncCallContext>
- structure (and expect to find it via fn_extra>). Use
+ structure (and expect to find it via fn_extra>). Use:
SRF_IS_FIRSTCALL()
to determine if your function is being called for the first or a
- subsequent time. On the first call (only) use
+ subsequent time. On the first call (only) use:
SRF_FIRSTCALL_INIT()
to initialize the FuncCallContext>. On every function call,
- including the first, use
+ including the first, use:
SRF_PERCALL_SETUP()
- If your function has data to return, use
+ If your function has data to return, use:
SRF_RETURN_NEXT(funcctx, result)
to return it to the caller. (result> must be of type
Datum>, either a single value or a tuple prepared as
described above.) Finally, when your function is finished
- returning data, use
+ returning data, use:
SRF_RETURN_DONE(funcctx)
-
+
Interfacing Extensions To Indexes
is to write the B-tree comparison support function first, and then write the
other functions as one-line wrappers around the support function. This
reduces the odds of getting inconsistent results for corner cases.
- Following this approach, we first write
+ Following this approach, we first write:
#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
}
- Now the less-than function looks like
+ Now the less-than function looks like:
PG_FUNCTION_INFO_V1(complex_abs_lt);
- We could have written the operator entries more verbosely, as in
+ We could have written the operator entries more verbosely, as in:
OPERATOR 1 < (complex, complex) ,
Normally, declaring an operator as a member of an operator class
(or family) means
that the index method can retrieve exactly the set of rows
- that satisfy a WHERE> condition using the operator. For example,
+ that satisfy a WHERE> condition using the operator. For example:
SELECT * FROM table WHERE integer_column < 4;
case there's not much value in storing the whole polygon in the index
entry — we might as well store just a simpler object of type
box>. This situation is expressed by the STORAGE>
- option in CREATE OPERATOR CLASS>: we'd write something like
+ option in CREATE OPERATOR CLASS>: we'd write something like:
CREATE OPERATOR CLASS polygon_ops
-
+
User-Defined Operators
name, not an operator name.) RESTRICT> clauses only make sense for
binary operators that return boolean>. The idea behind a restriction
selectivity estimator is to guess what fraction of the rows in a
- table will satisfy a WHERE-clause condition of the form
+ table will satisfy a WHERE-clause condition of the form:
column OP constant
name, not an operator name.) JOIN> clauses only make sense for
binary operators that return boolean. The idea behind a join
selectivity estimator is to guess what fraction of the rows in a
- pair of tables will satisfy a WHERE>-clause condition of the form
+ pair of tables will satisfy a WHERE>-clause condition of the form:
table1.column1 OP table2.column2
-
+
Procedural Languages
linkend="app-createlang"> can be used to do this from the shell
command line. For example, to install the language
PL/pgSQL into the database
- template1>, use
+ template1>, use:
createlang plpgsql template1
- The command
+ The command:
CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
HANDLER plpgsql_call_handler