mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
This patch includes more SGML markup fixes as well as a few minor
additions to the docs. Neil Conway
This commit is contained in:
parent
aca86479fd
commit
4996eea81c
@ -1,4 +1,4 @@
|
|||||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.10 2002/11/15 03:11:15 momjian Exp $ -->
|
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.11 2003/02/19 03:13:24 momjian Exp $ -->
|
||||||
|
|
||||||
<chapter id="ddl">
|
<chapter id="ddl">
|
||||||
<title>Data Definition</title>
|
<title>Data Definition</title>
|
||||||
@ -189,7 +189,7 @@ DROP TABLE products;
|
|||||||
individual table a row came from. The
|
individual table a row came from. The
|
||||||
<structfield>tableoid</structfield> can be joined against the
|
<structfield>tableoid</structfield> can be joined against the
|
||||||
<structfield>oid</structfield> column of
|
<structfield>oid</structfield> column of
|
||||||
<classname>pg_class</classname> to obtain the table name.
|
<structname>pg_class</structname> to obtain the table name.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -904,9 +904,9 @@ WHERE c.altitude > 500;
|
|||||||
139798 | Madison | 845
|
139798 | Madison | 845
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
(If you try to reproduce this example, you will probably get different
|
(If you try to reproduce this example, you will probably get
|
||||||
numeric OIDs.) By doing a join with pg_class you can see the actual table
|
different numeric OIDs.) By doing a join with
|
||||||
names:
|
<structname>pg_class</> you can see the actual table names:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
SELECT p.relname, c.name, c.altitude
|
SELECT p.relname, c.name, c.altitude
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.61 2003/01/19 00:13:29 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.62 2003/02/19 03:13:25 momjian Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -230,7 +230,10 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
|
|||||||
for large tables, since it will reduce OID consumption and
|
for large tables, since it will reduce OID consumption and
|
||||||
thereby postpone wraparound of the 32-bit OID counter. Once the
|
thereby postpone wraparound of the 32-bit OID counter. Once the
|
||||||
counter wraps around, uniqueness of OIDs can no longer be
|
counter wraps around, uniqueness of OIDs can no longer be
|
||||||
assumed, which considerably reduces their usefulness.
|
assumed, which considerably reduces their usefulness. Specifying
|
||||||
|
<literal>WITHOUT OIDS</literal> also reduces the space required
|
||||||
|
to store the table on disk by 4 bytes per row of the table,
|
||||||
|
thereby improving performance.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -881,8 +884,8 @@ CREATE ASSERTION <replaceable>name</replaceable> CHECK ( <replaceable>condition<
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
<para>
|
<para>
|
||||||
Domain constraints are defined by CREATE DOMAIN or ALTER DOMAIN
|
Domain constraints are defined by <command>CREATE
|
||||||
statements:
|
DOMAIN</command> or <command>ALTER DOMAIN</command> statements:
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Domain constraint:
|
Domain constraint:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.38 2003/01/19 00:13:29 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.39 2003/02/19 03:13:25 momjian Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -218,7 +218,8 @@ CREATE TYPE
|
|||||||
<para>
|
<para>
|
||||||
The first form of <command>CREATE TYPE</command> creates a new base type
|
The first form of <command>CREATE TYPE</command> creates a new base type
|
||||||
(scalar type). It requires the
|
(scalar type). It requires the
|
||||||
registration of two functions (using CREATE FUNCTION) before defining the
|
registration of two functions (using <command>CREATE
|
||||||
|
FUNCTION</command>) before defining the
|
||||||
type. The representation of a new base type is determined by
|
type. The representation of a new base type is determined by
|
||||||
<replaceable class="parameter">input_function</replaceable>, which
|
<replaceable class="parameter">input_function</replaceable>, which
|
||||||
converts the type's external representation to an internal
|
converts the type's external representation to an internal
|
||||||
@ -400,8 +401,8 @@ CREATE TYPE
|
|||||||
<para>
|
<para>
|
||||||
User-defined type names cannot begin with the underscore character
|
User-defined type names cannot begin with the underscore character
|
||||||
(<quote><literal>_</literal></quote>) and can only be 62
|
(<quote><literal>_</literal></quote>) and can only be 62
|
||||||
characters long (or in general <literal>NAMEDATALEN-2</>, rather than
|
characters long (or in general <symbol>NAMEDATALEN</symbol> - 2, rather than
|
||||||
the <literal>NAMEDATALEN-1</> characters allowed for other names).
|
the <symbol>NAMEDATALEN</symbol> - 1 characters allowed for other names).
|
||||||
Type names beginning with underscore are
|
Type names beginning with underscore are
|
||||||
reserved for internally-created array type names.
|
reserved for internally-created array type names.
|
||||||
</para>
|
</para>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.26 2002/10/19 19:00:47 tgl Exp $ -->
|
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.27 2003/02/19 03:13:24 momjian Exp $ -->
|
||||||
|
|
||||||
<Chapter Id="rules">
|
<Chapter Id="rules">
|
||||||
<Title>The Rule System</Title>
|
<Title>The Rule System</Title>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<Para>
|
<Para>
|
||||||
The rule system is located between the query parser and the planner.
|
The rule system is located between the query parser and the planner.
|
||||||
It takes the output of the parser, one query tree, and the rewrite
|
It takes the output of the parser, one query tree, and the rewrite
|
||||||
rules from the <FileName>pg_rewrite</FileName> catalog, which are
|
rules from the <structname>pg_rewrite</structname> catalog, which are
|
||||||
query trees too with some extra information, and creates zero or many
|
query trees too with some extra information, and creates zero or many
|
||||||
query trees as result. So its input and output are always things
|
query trees as result. So its input and output are always things
|
||||||
the parser itself could have produced and thus, anything it sees
|
the parser itself could have produced and thus, anything it sees
|
||||||
@ -72,7 +72,7 @@
|
|||||||
it are stored separately. These query trees are visible when starting
|
it are stored separately. These query trees are visible when starting
|
||||||
the <ProductName>PostgreSQL</ProductName> backend with debug level 4
|
the <ProductName>PostgreSQL</ProductName> backend with debug level 4
|
||||||
and typing queries into the interactive backend interface. The rule
|
and typing queries into the interactive backend interface. The rule
|
||||||
actions in the <FileName>pg_rewrite</FileName> system catalog are
|
actions in the <structname>pg_rewrite</structname> system catalog are
|
||||||
also stored as query trees. They are not formatted like the debug
|
also stored as query trees. They are not formatted like the debug
|
||||||
output, but they contain exactly the same information.
|
output, but they contain exactly the same information.
|
||||||
</Para>
|
</Para>
|
||||||
@ -107,7 +107,9 @@
|
|||||||
<ListItem>
|
<ListItem>
|
||||||
<Para>
|
<Para>
|
||||||
This is a simple value telling which command
|
This is a simple value telling which command
|
||||||
(SELECT, INSERT, UPDATE, DELETE) produced the parse tree.
|
(<command>SELECT</command>, <command>INSERT</command>,
|
||||||
|
<command>UPDATE</command>, <command>DELETE</command>) produced
|
||||||
|
the parse tree.
|
||||||
</Para>
|
</Para>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</VarListEntry>
|
</VarListEntry>
|
||||||
@ -120,7 +122,7 @@
|
|||||||
<ListItem>
|
<ListItem>
|
||||||
<Para>
|
<Para>
|
||||||
The range table is a list of relations that are used in the query.
|
The range table is a list of relations that are used in the query.
|
||||||
In a SELECT statement these are the relations given after
|
In a <command>SELECT</command> statement these are the relations given after
|
||||||
the FROM keyword.
|
the FROM keyword.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
@ -148,16 +150,17 @@
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
SELECT queries
|
<command>SELECT</command> queries normally don't have a result
|
||||||
normally don't have a result relation. The special case
|
relation. The special case of a <command>SELECT INTO</command> is
|
||||||
of a SELECT INTO is mostly identical to a CREATE TABLE,
|
mostly identical to a <command>CREATE TABLE</command>,
|
||||||
INSERT ... SELECT sequence and is not discussed separately
|
<literal>INSERT ... SELECT</literal> sequence and is not discussed
|
||||||
here.
|
separately here.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
On INSERT, UPDATE and DELETE queries the result relation
|
On <command>INSERT</command>, <command>UPDATE</command> and
|
||||||
is the table (or view!) where the changes take effect.
|
<command>DELETE</command> queries the result relation is the table
|
||||||
|
(or view!) where the changes take effect.
|
||||||
</Para>
|
</Para>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</VarListEntry>
|
</VarListEntry>
|
||||||
@ -168,41 +171,44 @@
|
|||||||
</Term>
|
</Term>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Para>
|
<Para>
|
||||||
The target list is a list of expressions that define the result
|
The target list is a list of expressions that define the
|
||||||
of the query. In the case of a SELECT, the expressions are what
|
result of the query. In the case of a <command>SELECT</command>,
|
||||||
builds the final output of the query. They are the expressions
|
the expressions are what builds the final output of the
|
||||||
between the SELECT and the FROM keywords. (* is just an
|
query. They are the expressions between the
|
||||||
abbreviation for all the attribute names of a relation. It is
|
<command>SELECT</command> and the FROM keywords.
|
||||||
expanded by the parser into the individual attributes, so the
|
(<literal>*</literal> is just an abbreviation for all the
|
||||||
rule system never sees it.)
|
attribute names of a relation. It is expanded by the parser into
|
||||||
|
the individual attributes, so the rule system never sees it.)
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
DELETE queries don't need a target list because they don't
|
<command>DELETE</command> queries don't need a target list
|
||||||
produce any result. In fact the planner will add a special <acronym>CTID</>
|
because they don't produce any result. In fact the planner will
|
||||||
entry to the empty target list. But this is after the rule
|
add a special <acronym>CTID</> entry to the empty target list. But
|
||||||
system and will be discussed later. For the rule system the
|
this is after the rule system and will be discussed later. For the
|
||||||
target list is empty.
|
rule system the target list is empty.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
In INSERT queries the target list describes the new rows that
|
In <command>INSERT</command> queries the target list describes
|
||||||
should go into the result relation. It is the expressions in the VALUES
|
the new rows that should go into the result relation. It is the
|
||||||
clause or the ones from the SELECT clause in INSERT ... SELECT.
|
expressions in the VALUES clause or the ones from the
|
||||||
The first step of the rewrite process adds target list entries
|
<command>SELECT</command> clause in <literal>INSERT
|
||||||
for any columns that were not assigned to by the original query
|
... SELECT</literal>. The first step of the rewrite process adds
|
||||||
and have defaults. Any remaining columns (with neither a given
|
target list entries for any columns that were not assigned to by
|
||||||
value nor a default) will be filled in by the
|
the original query and have defaults. Any remaining columns (with
|
||||||
|
neither a given value nor a default) will be filled in by the
|
||||||
planner with a constant NULL expression.
|
planner with a constant NULL expression.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
In UPDATE queries, the target list describes the new rows that should
|
In <command>UPDATE</command> queries, the target list
|
||||||
replace the old ones. In the rule system, it contains just the
|
describes the new rows that should replace the old ones. In the
|
||||||
expressions from the SET attribute = expression part of the query.
|
rule system, it contains just the expressions from the SET
|
||||||
The planner will handle missing columns by inserting expressions that
|
attribute = expression part of the query. The planner will handle
|
||||||
copy the values from the old row into the new one. And it will add
|
missing columns by inserting expressions that copy the values from
|
||||||
the special <acronym>CTID</> entry just as for DELETE too.
|
the old row into the new one. And it will add the special
|
||||||
|
<acronym>CTID</> entry just as for <command>DELETE</command> too.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -220,12 +226,13 @@
|
|||||||
</Term>
|
</Term>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Para>
|
<Para>
|
||||||
The query's qualification is an expression much like one of those
|
The query's qualification is an expression much like one of
|
||||||
contained in the target list entries. The result value of this
|
those contained in the target list entries. The result value of
|
||||||
expression is a Boolean that tells if the operation
|
this expression is a Boolean that tells if the operation
|
||||||
(INSERT, UPDATE, DELETE or SELECT) for the final result row should be
|
(<command>INSERT</command>, <command>UPDATE</command>,
|
||||||
executed or not. It is the WHERE clause of an
|
<command>DELETE</command> or <command>SELECT</command>) for the
|
||||||
<Acronym>SQL</Acronym> statement.
|
final result row should be executed or not. It is the WHERE clause
|
||||||
|
of an <Acronym>SQL</Acronym> statement.
|
||||||
</Para>
|
</Para>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</VarListEntry>
|
</VarListEntry>
|
||||||
@ -247,7 +254,7 @@
|
|||||||
to those join tree nodes. It turns out to be convenient to store
|
to those join tree nodes. It turns out to be convenient to store
|
||||||
the top-level WHERE expression as a qualification attached to the
|
the top-level WHERE expression as a qualification attached to the
|
||||||
top-level join tree item, too. So really the join tree represents
|
top-level join tree item, too. So really the join tree represents
|
||||||
both the FROM and WHERE clauses of a SELECT.
|
both the FROM and WHERE clauses of a <command>SELECT</command>.
|
||||||
</Para>
|
</Para>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</VarListEntry>
|
</VarListEntry>
|
||||||
@ -296,26 +303,26 @@ CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD
|
|||||||
SELECT * FROM mytab;
|
SELECT * FROM mytab;
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
because this is exactly what the CREATE VIEW command does internally.
|
because this is exactly what the <command>CREATE VIEW</command>
|
||||||
This has some side effects. One of them is that
|
command does internally. This has some side effects. One of them
|
||||||
the information about a view in the <ProductName>PostgreSQL</ProductName>
|
is that the information about a view in the
|
||||||
system catalogs is exactly the same as it is for a table. So for the
|
<ProductName>PostgreSQL</ProductName> system catalogs is exactly
|
||||||
query parser, there is absolutely no difference between
|
the same as it is for a table. So for the query parser, there is
|
||||||
a table and a view. They are the same thing - relations. That is the
|
absolutely no difference between a table and a view. They are the
|
||||||
important one for now.
|
same thing - relations. That is the important one for now.
|
||||||
</Para>
|
</Para>
|
||||||
</Sect2>
|
</Sect2>
|
||||||
|
|
||||||
<Sect2>
|
<Sect2>
|
||||||
<Title>How SELECT Rules Work</Title>
|
<Title>How <command>SELECT</command> Rules Work</Title>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
Rules ON SELECT are applied to all queries as the
|
Rules ON SELECT are applied to all queries as the last step, even
|
||||||
last step, even if the command
|
if the command given is an <command>INSERT</command>,
|
||||||
given is an INSERT, UPDATE or DELETE. And they have different
|
<command>UPDATE</command> or <command>DELETE</command>. And they
|
||||||
semantics from the others in that they modify the parse tree in
|
have different semantics from the others in that they modify the
|
||||||
place instead of creating a new one.
|
parse tree in place instead of creating a new one. So
|
||||||
So SELECT rules are described first.
|
<command>SELECT</command> rules are described first.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -326,15 +333,16 @@ CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
The examples for this document are two join views that do some calculations
|
The examples for this document are two join views that do some
|
||||||
and some more views using them in turn.
|
calculations and some more views using them in turn. One of the
|
||||||
One of the two first views is customized later by adding rules for
|
two first views is customized later by adding rules for
|
||||||
INSERT, UPDATE and DELETE operations so that the final result will
|
<command>INSERT</command>, <command>UPDATE</command> and
|
||||||
be a view that behaves like a real table with some magic functionality.
|
<command>DELETE</command> operations so that the final result will
|
||||||
It is not such a simple example to start from and this makes things
|
be a view that behaves like a real table with some magic
|
||||||
harder to get into. But it's better to have one example that covers
|
functionality. It is not such a simple example to start from and
|
||||||
all the points discussed step by step rather than having many
|
this makes things harder to get into. But it's better to have one
|
||||||
different ones that might mix up in mind.
|
example that covers all the points discussed step by step rather
|
||||||
|
than having many different ones that might mix up in mind.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -428,21 +436,21 @@ CREATE VIEW shoe_ready AS
|
|||||||
AND rsl.sl_len_cm <= rsh.slmaxlen_cm;
|
AND rsl.sl_len_cm <= rsh.slmaxlen_cm;
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
The CREATE VIEW command for the <Filename>shoelace</Filename>
|
The <command>CREATE VIEW</command> command for the
|
||||||
view (which is the simplest one we have)
|
<literal>shoelace</literal> view (which is the simplest one we
|
||||||
will create a relation shoelace and an entry
|
have) will create a relation shoelace and an entry in
|
||||||
in <FileName>pg_rewrite</FileName>
|
<structname>pg_rewrite</structname> that tells that there is a
|
||||||
that tells that there is a rewrite rule that must be applied
|
rewrite rule that must be applied whenever the relation shoelace
|
||||||
whenever the relation shoelace is referenced in a query's range table.
|
is referenced in a query's range table. The rule has no rule
|
||||||
The rule has no rule qualification (discussed later, with the
|
qualification (discussed later, with the non SELECT rules, since
|
||||||
non SELECT rules, since SELECT rules currently cannot have them) and
|
SELECT rules currently cannot have them) and it is INSTEAD. Note
|
||||||
it is INSTEAD. Note that rule qualifications are not the same as
|
that rule qualifications are not the same as query qualifications!
|
||||||
query qualifications! The rule's action has a query qualification.
|
The rule's action has a query qualification.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
The rule's action is one query tree that is a copy of the
|
The rule's action is one query tree that is a copy of the
|
||||||
SELECT statement in the view creation command.
|
<command>SELECT</command> statement in the view creation command.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
<Title>Note</Title>
|
<Title>Note</Title>
|
||||||
@ -450,14 +458,14 @@ CREATE VIEW shoe_ready AS
|
|||||||
The two extra range
|
The two extra range
|
||||||
table entries for NEW and OLD (named *NEW* and *CURRENT* for
|
table entries for NEW and OLD (named *NEW* and *CURRENT* for
|
||||||
historical reasons in the printed query tree) you can see in
|
historical reasons in the printed query tree) you can see in
|
||||||
the <Filename>pg_rewrite</Filename> entry aren't of interest
|
the <structname>pg_rewrite</structname> entry aren't of interest
|
||||||
for SELECT rules.
|
for SELECT rules.
|
||||||
</Para>
|
</Para>
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
Now we populate <Filename>unit</Filename>, <Filename>shoe_data</Filename>
|
Now we populate <literal>unit</literal>, <literal>shoe_data</literal>
|
||||||
and <Filename>shoelace_data</Filename> and Al types the first
|
and <literal>shoelace_data</literal> and Al types the first
|
||||||
SELECT in his life:
|
<command>SELECT</command> in his life:
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
al_bundy=> INSERT INTO unit VALUES ('cm', 1.0);
|
al_bundy=> INSERT INTO unit VALUES ('cm', 1.0);
|
||||||
@ -504,10 +512,10 @@ sl6 | 0|brown | 0.9|m | 90
|
|||||||
(8 rows)
|
(8 rows)
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
It's the simplest SELECT Al can do on our views, so we take this
|
It's the simplest <command>SELECT</command> Al can do on our
|
||||||
to explain the basics of view rules.
|
views, so we take this opportunity to explain the basics of view
|
||||||
The <literal>SELECT * FROM shoelace</literal> was interpreted by the parser and
|
rules. The <literal>SELECT * FROM shoelace</literal> was
|
||||||
produced the parse tree
|
interpreted by the parser and produced the parse tree
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
SELECT shoelace.sl_name, shoelace.sl_avail,
|
SELECT shoelace.sl_name, shoelace.sl_avail,
|
||||||
@ -517,9 +525,9 @@ SELECT shoelace.sl_name, shoelace.sl_avail,
|
|||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
and this is given to the rule system. The rule system walks through the
|
and this is given to the rule system. The rule system walks through the
|
||||||
range table and checks if there are rules in <Filename>pg_rewrite</Filename>
|
range table and checks if there are rules in <structname>pg_rewrite</structname>
|
||||||
for any relation. When processing the range table entry for
|
for any relation. When processing the range table entry for
|
||||||
<Filename>shoelace</Filename> (the only one up to now) it finds the
|
<literal>shoelace</literal> (the only one up to now) it finds the
|
||||||
<literal>_RETURN</literal> rule with the parse tree
|
<literal>_RETURN</literal> rule with the parse tree
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
@ -618,7 +626,7 @@ SELECT shoe_ready.shoename, shoe_ready.sh_avail,
|
|||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
The first rule applied will be the one for the
|
The first rule applied will be the one for the
|
||||||
<Filename>shoe_ready</Filename> view and it results in the
|
<literal>shoe_ready</literal> view and it results in the
|
||||||
parse tree
|
parse tree
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
@ -637,8 +645,8 @@ SELECT shoe_ready.shoename, shoe_ready.sh_avail,
|
|||||||
WHERE int4ge(shoe_ready.total_avail, 2);
|
WHERE int4ge(shoe_ready.total_avail, 2);
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
Similarly, the rules for <Filename>shoe</Filename> and
|
Similarly, the rules for <literal>shoe</literal> and
|
||||||
<Filename>shoelace</Filename> are substituted into the range table of
|
<literal>shoelace</literal> are substituted into the range table of
|
||||||
the sub-query, leading to a three-level final query tree:
|
the sub-query, leading to a three-level final query tree:
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
@ -686,17 +694,16 @@ SELECT shoe_ready.shoename, shoe_ready.sh_avail,
|
|||||||
<Note>
|
<Note>
|
||||||
<Title>Note</Title>
|
<Title>Note</Title>
|
||||||
<Para>
|
<Para>
|
||||||
There is currently no recursion stopping mechanism for view
|
There is currently no recursion stopping mechanism for view rules
|
||||||
rules in the rule system (only for the other kinds of rules).
|
in the rule system (only for the other kinds of rules). This
|
||||||
This doesn't hurt much, because the only way to push this
|
doesn't hurt much, because the only way to push this into an
|
||||||
into an endless loop (blowing up the
|
endless loop (blowing up the backend until it reaches the memory
|
||||||
backend until it reaches the memory limit)
|
limit) is to create tables and then setup the view rules by hand
|
||||||
is to create tables and then setup the
|
with <command>CREATE RULE</command> in such a way, that one
|
||||||
view rules by hand with CREATE RULE in such a way, that
|
selects from the other that selects from the one. This could
|
||||||
one selects from the other that selects from the one.
|
never happen if <command>CREATE VIEW</command> is used because for
|
||||||
This could never happen if CREATE VIEW is used because
|
the first <command>CREATE VIEW</command>, the second relation does
|
||||||
for the first CREATE VIEW, the second relation does not exist
|
not exist and thus the first view cannot select from the second.
|
||||||
and thus the first view cannot select from the second.
|
|
||||||
</Para>
|
</Para>
|
||||||
</Note>
|
</Note>
|
||||||
</Para>
|
</Para>
|
||||||
@ -713,12 +720,13 @@ SELECT shoe_ready.shoename, shoe_ready.sh_avail,
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
There are only a few differences between a parse tree for a SELECT
|
There are only a few differences between a parse tree for a
|
||||||
and one for any other command. Obviously they have another command type
|
<command>SELECT</command> and one for any other command. Obviously
|
||||||
and this time the result relation points to the range table entry where
|
they have another command type and this time the result relation
|
||||||
the result should go. Everything else is absolutely the same.
|
points to the range table entry where the result should
|
||||||
So having two tables t1 and t2 with attributes
|
go. Everything else is absolutely the same. So having two tables
|
||||||
a and b, the parse trees for the two statements
|
t1 and t2 with attributes a and b, the parse trees for the two
|
||||||
|
statements
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
|
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
|
||||||
@ -756,10 +764,11 @@ UPDATE t1 SET b = t2.b WHERE t1.a = t2.a;
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
</ItemizedList>
|
</ItemizedList>
|
||||||
|
|
||||||
The consequence is, that both parse trees result in similar execution
|
The consequence is, that both parse trees result in similar
|
||||||
plans. They are both joins over the two tables. For the UPDATE
|
execution plans. They are both joins over the two tables. For the
|
||||||
the missing columns from t1 are added to the target list by the planner
|
<command>UPDATE</command> the missing columns from t1 are added to
|
||||||
and the final parse tree will read as
|
the target list by the planner and the final parse tree will read
|
||||||
|
as
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
UPDATE t1 SET a = t1.a, b = t2.b WHERE t1.a = t2.a;
|
UPDATE t1 SET a = t1.a, b = t2.b WHERE t1.a = t2.a;
|
||||||
@ -772,23 +781,27 @@ UPDATE t1 SET a = t1.a, b = t2.b WHERE t1.a = t2.a;
|
|||||||
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
|
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
will do. But there is a little problem in UPDATE. The executor does
|
will do. But there is a little problem in
|
||||||
not care what the results from the join it is doing are meant
|
<command>UPDATE</command>. The executor does not care what the
|
||||||
for. It just produces a result set of rows. The difference that one
|
results from the join it is doing are meant for. It just produces
|
||||||
is a SELECT command and the other is an UPDATE is handled in the
|
a result set of rows. The difference that one is a
|
||||||
caller of the executor. The caller still knows (looking at the
|
<command>SELECT</command> command and the other is an
|
||||||
parse tree) that this is an UPDATE, and he knows that this result
|
<command>UPDATE</command> is handled in the caller of the
|
||||||
should go into table t1. But which of the rows that are there
|
executor. The caller still knows (looking at the parse tree) that
|
||||||
has to be replaced by the new row?
|
this is an <command>UPDATE</command>, and he knows that this
|
||||||
|
result should go into table t1. But which of the rows that are
|
||||||
|
there has to be replaced by the new row?
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
To resolve this problem, another entry is added to the target list
|
To resolve this problem, another entry is added to the target list
|
||||||
in UPDATE (and also in DELETE) statements: the current tuple ID (<acronym>CTID</>).
|
in <command>UPDATE</command> (and also in
|
||||||
This is a system attribute containing the file
|
<command>DELETE</command>) statements: the current tuple ID
|
||||||
block number and position in the block for the row. Knowing the table,
|
(<acronym>CTID</>). This is a system attribute containing the
|
||||||
the <acronym>CTID</> can be used to retrieve the original t1 row to be updated.
|
file block number and position in the block for the row. Knowing
|
||||||
After adding the <acronym>CTID</> to the target list, the query actually looks like
|
the table, the <acronym>CTID</> can be used to retrieve the
|
||||||
|
original t1 row to be updated. After adding the <acronym>CTID</>
|
||||||
|
to the target list, the query actually looks like
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
|
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
|
||||||
@ -796,13 +809,14 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
|
|||||||
|
|
||||||
Now another detail of <ProductName>PostgreSQL</ProductName> enters
|
Now another detail of <ProductName>PostgreSQL</ProductName> enters
|
||||||
the stage. At this moment, table rows aren't overwritten and this
|
the stage. At this moment, table rows aren't overwritten and this
|
||||||
is why ABORT TRANSACTION is fast. In an UPDATE, the new result row
|
is why ABORT TRANSACTION is fast. In an <command>UPDATE</command>,
|
||||||
is inserted into the table (after stripping <acronym>CTID</>) and
|
the new result row is inserted into the table (after stripping
|
||||||
in the tuple header of the row that <acronym>CTID</> pointed to
|
<acronym>CTID</>) and in the tuple header of the row that
|
||||||
the <literal>cmax</> and <literal>xmax</> entries are set to the
|
<acronym>CTID</> pointed to the <literal>cmax</> and
|
||||||
current command counter and current transaction ID. Thus the old
|
<literal>xmax</> entries are set to the current command counter
|
||||||
row is hidden and after the transaction committed the vacuum
|
and current transaction ID. Thus the old row is hidden and after
|
||||||
cleaner can really move it out.
|
the transaction committed the vacuum cleaner can really move it
|
||||||
|
out.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -815,10 +829,11 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
|
|||||||
<Title>The Power of Views in <ProductName>PostgreSQL</ProductName></Title>
|
<Title>The Power of Views in <ProductName>PostgreSQL</ProductName></Title>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
The above demonstrates how the rule system incorporates
|
The above demonstrates how the rule system incorporates view
|
||||||
view definitions into the original parse tree. In the second example
|
definitions into the original parse tree. In the second example a
|
||||||
a simple SELECT from one view created a final parse tree that is
|
simple <command>SELECT</command> from one view created a final
|
||||||
a join of 4 tables (unit is used twice with different names).
|
parse tree that is a join of 4 tables (unit is used twice with
|
||||||
|
different names).
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Sect3>
|
<Sect3>
|
||||||
@ -848,16 +863,19 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
|
|||||||
<indexterm zone="rules-views-update"><primary>views</><secondary>updating</></>
|
<indexterm zone="rules-views-update"><primary>views</><secondary>updating</></>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
What happens if a view is named as the target relation for an INSERT,
|
What happens if a view is named as the target relation for an
|
||||||
UPDATE, or DELETE? After doing the substitutions described above,
|
<command>INSERT</command>, <command>UPDATE</command>, or
|
||||||
we will have a query tree in which the result relation points at a
|
<command>DELETE</command>? After doing the substitutions
|
||||||
subquery range table entry. This will not work, so the rewriter throws
|
described above, we will have a query tree in which the result
|
||||||
an error if it sees it has produced such a thing.
|
relation points at a subquery range table entry. This will not
|
||||||
|
work, so the rewriter throws an error if it sees it has produced
|
||||||
|
such a thing.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
To change this we can define rules that modify the behavior
|
To change this we can define rules that modify the behavior of
|
||||||
of non-SELECT queries. This is the topic of the next section.
|
non-<command>SELECT</command> queries. This is the topic of the
|
||||||
|
next section.
|
||||||
</Para>
|
</Para>
|
||||||
</Sect2>
|
</Sect2>
|
||||||
|
|
||||||
@ -870,10 +888,10 @@ SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
|
|||||||
<Title>Differences from View Rules</Title>
|
<Title>Differences from View Rules</Title>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
Rules that are defined ON INSERT, UPDATE and DELETE are
|
Rules that are defined ON INSERT, UPDATE and DELETE are totally
|
||||||
totally different from the view rules described
|
different from the view rules described in the previous
|
||||||
in the previous section. First, their CREATE RULE
|
section. First, their <command>CREATE RULE</command> command
|
||||||
command allows more:
|
allows more:
|
||||||
|
|
||||||
<ItemizedList>
|
<ItemizedList>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@ -932,7 +950,7 @@ CREATE RULE rule_name AS ON event
|
|||||||
<Para>
|
<Para>
|
||||||
Update rules get applied by the rule system when the result
|
Update rules get applied by the rule system when the result
|
||||||
relation and the command type of a parse tree are equal to the
|
relation and the command type of a parse tree are equal to the
|
||||||
object and event given in the CREATE RULE command.
|
object and event given in the <command>CREATE RULE</command> command.
|
||||||
For update rules, the rule system creates a list of parse trees.
|
For update rules, the rule system creates a list of parse trees.
|
||||||
Initially the parse tree list is empty.
|
Initially the parse tree list is empty.
|
||||||
There can be zero (NOTHING keyword), one or multiple actions.
|
There can be zero (NOTHING keyword), one or multiple actions.
|
||||||
@ -1050,15 +1068,17 @@ CREATE RULE rule_name AS ON event
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
The parse trees found in the actions of the <Filename>pg_rewrite</Filename>
|
The parse trees found in the actions of the
|
||||||
system catalog are only templates. Since they can reference the
|
<structname>pg_rewrite</structname> system catalog are only
|
||||||
range-table entries for NEW and OLD, some substitutions have to be made
|
templates. Since they can reference the range-table entries for
|
||||||
before they can be used. For any reference to NEW, the target list of
|
NEW and OLD, some substitutions have to be made before they can be
|
||||||
the original query is searched for a corresponding entry. If found,
|
used. For any reference to NEW, the target list of the original
|
||||||
that entry's expression replaces the reference. Otherwise
|
query is searched for a corresponding entry. If found, that
|
||||||
NEW means the same as OLD (for an UPDATE) or is replaced by NULL
|
entry's expression replaces the reference. Otherwise NEW means the
|
||||||
(for an INSERT). Any reference to OLD is replaced by a
|
same as OLD (for an <command>UPDATE</command>) or is replaced by
|
||||||
reference to the range-table entry which is the result relation.
|
NULL (for an <command>INSERT</command>). Any reference to OLD is
|
||||||
|
replaced by a reference to the range-table entry which is the
|
||||||
|
result relation.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -1072,9 +1092,10 @@ CREATE RULE rule_name AS ON event
|
|||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
We want to trace changes to the sl_avail column in the
|
We want to trace changes to the sl_avail column in the
|
||||||
<Filename>shoelace_data</Filename> relation. So we setup a
|
<literal>shoelace_data</literal> relation. So we setup a log table
|
||||||
log table and a rule that conditionally writes a log entry when
|
and a rule that conditionally writes a log entry when an
|
||||||
an UPDATE is performed on <Filename>shoelace_data</Filename>.
|
<command>UPDATE</command> is performed on
|
||||||
|
<literal>shoelace_data</literal>.
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
CREATE TABLE shoelace_log (
|
CREATE TABLE shoelace_log (
|
||||||
@ -1144,7 +1165,7 @@ INSERT INTO shoelace_log VALUES(
|
|||||||
INSERT ... VALUES ... FROM. The FROM clause here is just to indicate
|
INSERT ... VALUES ... FROM. The FROM clause here is just to indicate
|
||||||
that there are range-table entries in the parse tree for *NEW* and *OLD*.
|
that there are range-table entries in the parse tree for *NEW* and *OLD*.
|
||||||
These are needed so that they can be referenced by variables in the
|
These are needed so that they can be referenced by variables in the
|
||||||
INSERT command's query tree.
|
<command>INSERT</command> command's query tree.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -1287,11 +1308,11 @@ INSERT INTO shoelace_log SELECT
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
Here we can see why it is important that the original parse tree is
|
Here we can see why it is important that the original parse tree
|
||||||
executed last.
|
is executed last. If the <command>UPDATE</command> would have
|
||||||
If the UPDATE would have been executed first, all the rows
|
been executed first, all the rows are already set to zero, so the
|
||||||
are already set to zero, so the logging INSERT
|
logging <command>INSERT</command> would not find any row where 0
|
||||||
would not find any row where 0 != shoelace_data.sl_avail.
|
!= shoelace_data.sl_avail.
|
||||||
</Para>
|
</Para>
|
||||||
</Sect3>
|
</Sect3>
|
||||||
|
|
||||||
@ -1302,9 +1323,9 @@ INSERT INTO shoelace_log SELECT
|
|||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
A simple way to protect view relations from the mentioned
|
A simple way to protect view relations from the mentioned
|
||||||
possibility that someone can try to INSERT, UPDATE and DELETE
|
possibility that someone can try to <command>INSERT</command>,
|
||||||
on them is to let those parse trees get
|
<command>UPDATE</command> and <command>DELETE</command> on them is
|
||||||
thrown away. We create the rules
|
to let those parse trees get thrown away. We create the rules
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
CREATE RULE shoe_ins_protect AS ON INSERT TO shoe
|
CREATE RULE shoe_ins_protect AS ON INSERT TO shoe
|
||||||
@ -1316,7 +1337,7 @@ CREATE RULE shoe_del_protect AS ON DELETE TO shoe
|
|||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
If Al now tries to do any of these operations on the view
|
If Al now tries to do any of these operations on the view
|
||||||
relation <Filename>shoe</Filename>, the rule system will
|
relation <literal>shoe</literal>, the rule system will
|
||||||
apply the rules. Since the rules have
|
apply the rules. Since the rules have
|
||||||
no actions and are INSTEAD, the resulting list of
|
no actions and are INSTEAD, the resulting list of
|
||||||
parse trees will be empty and the whole query will become
|
parse trees will be empty and the whole query will become
|
||||||
@ -1328,7 +1349,7 @@ CREATE RULE shoe_del_protect AS ON DELETE TO shoe
|
|||||||
A more sophisticated way to use the rule system is to
|
A more sophisticated way to use the rule system is to
|
||||||
create rules that rewrite the parse tree into one that
|
create rules that rewrite the parse tree into one that
|
||||||
does the right operation on the real tables. To do that
|
does the right operation on the real tables. To do that
|
||||||
on the <Filename>shoelace</Filename> view, we create
|
on the <literal>shoelace</literal> view, we create
|
||||||
the following rules:
|
the following rules:
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
@ -1466,9 +1487,10 @@ UPDATE shoelace SET
|
|||||||
WHERE bpchareq(shoelace.sl_name, showlace_arrive.arr_name);
|
WHERE bpchareq(shoelace.sl_name, showlace_arrive.arr_name);
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
and throws away the original INSERT on <Filename>shoelace_ok</Filename>.
|
and throws away the original <command>INSERT</command> on
|
||||||
This rewritten query is passed to the rule system again and
|
<literal>shoelace_ok</literal>. This rewritten query is passed to
|
||||||
the second applied rule <literal>shoelace_upd</literal> produced
|
the rule system again and the second applied rule
|
||||||
|
<literal>shoelace_upd</literal> produced
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
UPDATE shoelace_data SET
|
UPDATE shoelace_data SET
|
||||||
@ -1486,7 +1508,7 @@ UPDATE shoelace_data SET
|
|||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
Again it's an INSTEAD rule and the previous parse tree is trashed.
|
Again it's an INSTEAD rule and the previous parse tree is trashed.
|
||||||
Note that this query still uses the view <Filename>shoelace</Filename>.
|
Note that this query still uses the view <literal>shoelace</literal>.
|
||||||
But the rule system isn't finished with this loop so it continues
|
But the rule system isn't finished with this loop so it continues
|
||||||
and applies the <literal>_RETURN</literal> rule on it and we get
|
and applies the <literal>_RETURN</literal> rule on it and we get
|
||||||
|
|
||||||
@ -1564,11 +1586,12 @@ UPDATE shoelace_data SET
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
There is a little detail that's a bit ugly. Looking at
|
There is a little detail that's a bit ugly. Looking at the two
|
||||||
the two queries turns out, that the <Filename>shoelace_data</Filename>
|
queries turns out, that the <literal>shoelace_data</literal>
|
||||||
relation appears twice in the range table where it could definitely
|
relation appears twice in the range table where it could
|
||||||
be reduced to one. The planner does not handle it and so the
|
definitely be reduced to one. The planner does not handle it and
|
||||||
execution plan for the rule systems output of the INSERT will be
|
so the execution plan for the rule systems output of the
|
||||||
|
<command>INSERT</command> will be
|
||||||
|
|
||||||
<ProgramListing>
|
<ProgramListing>
|
||||||
Nested Loop
|
Nested Loop
|
||||||
@ -1594,12 +1617,12 @@ Merge Join
|
|||||||
-> Seq Scan on shoelace_arrive
|
-> Seq Scan on shoelace_arrive
|
||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
that totally produces the same entries in the log relation.
|
that totally produces the same entries in the log relation. Thus,
|
||||||
Thus, the rule system caused one extra scan on the
|
the rule system caused one extra scan on the
|
||||||
<Filename>shoelace_data</Filename> relation that is
|
<literal>shoelace_data</literal> relation that is absolutely not
|
||||||
absolutely not necessary. And the same obsolete scan
|
necessary. And the same obsolete scan is done once more in the
|
||||||
is done once more in the UPDATE. But it was a really hard
|
<command>UPDATE</command>. But it was a really hard job to make
|
||||||
job to make that all possible at all.
|
that all possible at all.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -1738,15 +1761,17 @@ GRANT SELECT ON phone_number TO secretary;
|
|||||||
</ProgramListing>
|
</ProgramListing>
|
||||||
|
|
||||||
Nobody except him (and the database superusers) can access the
|
Nobody except him (and the database superusers) can access the
|
||||||
phone_data table. But due to the GRANT, the secretary can SELECT from the
|
phone_data table. But due to the GRANT, the secretary can
|
||||||
phone_number view. The rule system will rewrite
|
<command>SELECT</command> from the phone_number view. The rule
|
||||||
the SELECT from phone_number into a SELECT from phone_data and add the qualification
|
system will rewrite the <command>SELECT</command> from
|
||||||
that only entries where private is false are wanted. Since the
|
phone_number into a <command>SELECT</command> from phone_data and
|
||||||
user is the owner of phone_number, the read access to phone_data
|
add the qualification that only entries where private is false are
|
||||||
is now checked against his permissions and the query is considered
|
wanted. Since the user is the owner of phone_number, the read
|
||||||
granted. The check for accessing phone_number is also performed,
|
access to phone_data is now checked against his permissions and
|
||||||
but this is done against the invoking user, so nobody but the user and the
|
the query is considered granted. The check for accessing
|
||||||
secretary can use it.
|
phone_number is also performed, but this is done against the
|
||||||
|
invoking user, so nobody but the user and the secretary can use
|
||||||
|
it.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -1767,9 +1792,10 @@ GRANT SELECT ON phone_number TO secretary;
|
|||||||
hole, but in fact it isn't. If this would not work, the secretary
|
hole, but in fact it isn't. If this would not work, the secretary
|
||||||
could setup a table with the same columns as phone_number and
|
could setup a table with the same columns as phone_number and
|
||||||
copy the data to there once per day. Then it's his own data and
|
copy the data to there once per day. Then it's his own data and
|
||||||
he can grant access to everyone he wants. A GRANT means <quote>I trust you</quote>.
|
he can grant access to everyone he wants. A
|
||||||
|
<command>GRANT</command> means <quote>I trust you</quote>.
|
||||||
If someone you trust does the thing above, it's time to
|
If someone you trust does the thing above, it's time to
|
||||||
think it over and then REVOKE.
|
think it over and then <command>REVOKE</command>.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -1823,12 +1849,14 @@ GRANT SELECT ON phone_number TO secretary;
|
|||||||
<para>
|
<para>
|
||||||
If there is any unconditional INSTEAD rule for the query, then
|
If there is any unconditional INSTEAD rule for the query, then
|
||||||
the original query will not be executed at all. In this case,
|
the original query will not be executed at all. In this case,
|
||||||
the server will return the command status for the last query that
|
the server will return the command status for the last query
|
||||||
was inserted by an INSTEAD rule (conditional or unconditional)
|
that was inserted by an INSTEAD rule (conditional or
|
||||||
and is of the same type (INSERT, UPDATE, or DELETE) as the original
|
unconditional) and is of the same type
|
||||||
query. If no query meeting those requirements is added by any
|
(<command>INSERT</command>, <command>UPDATE</command>, or
|
||||||
rule, then the returned command status shows the original query
|
<command>DELETE</command>) as the original query. If no query
|
||||||
type and zeroes for the tuple-count and OID fields.
|
meeting those requirements is added by any rule, then the
|
||||||
|
returned command status shows the original query type and
|
||||||
|
zeroes for the tuple-count and OID fields.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
@ -1859,13 +1887,13 @@ GRANT SELECT ON phone_number TO secretary;
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
On the other hand a trigger that is fired on INSERT
|
On the other hand a trigger that is fired on
|
||||||
on a view can do the same as a rule, put the data somewhere
|
<command>INSERT</command> on a view can do the same as a rule, put
|
||||||
else and suppress the insert in the view. But it cannot
|
the data somewhere else and suppress the insert in the view. But
|
||||||
do the same thing on UPDATE or DELETE, because there is
|
it cannot do the same thing on <command>UPDATE</command> or
|
||||||
no real data in the view relation that could be scanned
|
<command>DELETE</command>, because there is no real data in the
|
||||||
and thus the trigger would never get called. Only a rule
|
view relation that could be scanned and thus the trigger would
|
||||||
will help.
|
never get called. Only a rule will help.
|
||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
@ -2018,7 +2046,7 @@ DELETE FROM software WHERE computer.manufacurer = 'bim'
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
Another situation is cases on UPDATE where it depends on the
|
Another situation is cases on <command>UPDATE</command> where it depends on the
|
||||||
change of an attribute if an action should be performed or
|
change of an attribute if an action should be performed or
|
||||||
not. In <ProductName>PostgreSQL</ProductName> version 6.4, the
|
not. In <ProductName>PostgreSQL</ProductName> version 6.4, the
|
||||||
attribute specification for rule events is disabled (it will have
|
attribute specification for rule events is disabled (it will have
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.74 2002/11/15 03:11:17 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.75 2003/02/19 03:13:24 momjian Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="sql-syntax">
|
<chapter id="sql-syntax">
|
||||||
@ -121,9 +121,9 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there');
|
|||||||
characters of an identifier; longer names can be written in
|
characters of an identifier; longer names can be written in
|
||||||
commands, but they will be truncated. By default,
|
commands, but they will be truncated. By default,
|
||||||
<symbol>NAMEDATALEN</symbol> is 64 so the maximum identifier
|
<symbol>NAMEDATALEN</symbol> is 64 so the maximum identifier
|
||||||
length is 63 (but at the time <productname>PostgreSQL</> is built,
|
length is 63. If this limit is problematic, it can be raised by
|
||||||
<symbol>NAMEDATALEN</symbol> can be changed in
|
changing the <symbol>NAMEDATALEN</symbol> constant in
|
||||||
<filename>src/include/postgres_ext.h</filename>).
|
<filename>src/include/postgres_ext.h</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -541,8 +541,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
|
|||||||
<para>
|
<para>
|
||||||
A dollar sign (<literal>$</literal>) followed by digits is used
|
A dollar sign (<literal>$</literal>) followed by digits is used
|
||||||
to represent the positional parameters in the body of a function
|
to represent the positional parameters in the body of a function
|
||||||
definition. In other contexts the dollar sign may be part of an
|
definition or a prepared statement. In other contexts the
|
||||||
operator name.
|
dollar sign may be part of an operator name.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user