Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
4996eea8
Commit
4996eea8
authored
Feb 19, 2003
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
This patch includes more SGML markup fixes as well as a few minor
additions to the docs. Neil Conway
parent
aca86479
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
262 additions
and
230 deletions
+262
-230
doc/src/sgml/ddl.sgml
doc/src/sgml/ddl.sgml
+5
-5
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/create_table.sgml
+7
-4
doc/src/sgml/ref/create_type.sgml
doc/src/sgml/ref/create_type.sgml
+5
-4
doc/src/sgml/rules.sgml
doc/src/sgml/rules.sgml
+239
-211
doc/src/sgml/syntax.sgml
doc/src/sgml/syntax.sgml
+6
-6
No files found.
doc/src/sgml/ddl.sgml
View file @
4996eea8
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.1
0 2002/11/15 03:11:15
momjian Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.1
1 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;
...
@@ -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</class
name> to obtain the table name.
<
structname>pg_class</struct
name> to obtain the table name.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -904,9 +904,9 @@ WHERE c.altitude > 500;
...
@@ -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
...
...
doc/src/sgml/ref/create_table.sgml
View file @
4996eea8
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.6
1 2003/01/19 00:13:29
momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.6
2 2003/02/19 03:13:25
momjian Exp $
PostgreSQL documentation
PostgreSQL documentation
-->
-->
...
@@ -230,7 +230,10 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
...
@@ -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<
...
@@ -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:
...
...
doc/src/sgml/ref/create_type.sgml
View file @
4996eea8
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.3
8 2003/01/19 00:13:29
momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.3
9 2003/02/19 03:13:25
momjian Exp $
PostgreSQL documentation
PostgreSQL documentation
-->
-->
...
@@ -218,7 +218,8 @@ CREATE TYPE
...
@@ -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
...
@@ -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>
...
...
doc/src/sgml/rules.sgml
View file @
4996eea8
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.2
6 2002/10/19 19:00:47 tgl
Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.2
7 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 @@
...
@@ -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</FileN
ame> catalog, which are
rules from the <
structname>pg_rewrite</structn
ame> 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 @@
...
@@ -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</FileN
ame> system catalog are
actions in the <
structname>pg_rewrite</structn
ame> 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 @@
...
@@ -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 @@
...
@@ -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 @@
...
@@ -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 @@
...
@@ -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 lis
t
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 @@
...
@@ -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 @@
...
@@ -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
...
@@ -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
a
bsolutely 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
p
lace instead of creating a new one.
p
arse 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
...
@@ -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
...
@@ -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 th
e
qualification (discussed later, with the non SELECT rules, sinc
e
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
...
@@ -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</File
name> entry aren't of interest
the <
structname>pg_rewrite</struct
name> 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
...
@@ -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,
...
@@ -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</File
name>
range table and checks if there are rules in <
structname>pg_rewrite</struct
name>
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,
...
@@ -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,
...
@@ -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,
...
@@ -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,
...
@@ -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;
...
@@ -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;
...
@@ -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;
...
@@ -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;
...
@@ -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;
...
@@ -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;
...
@@ -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
...
@@ -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
...
@@ -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
...
@@ -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(
...
@@ -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
...
@@ -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
...
@@ -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
t
o let those parse trees get t
hrown 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
...
@@ -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
...
@@ -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
...
@@ -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
...
@@ -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
...
@@ -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
...
@@ -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;
...
@@ -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;
...
@@ -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;
...
@@ -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;
...
@@ -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 canno
t
the data somewhere else and suppress the insert in the view. Bu
t
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'
...
@@ -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
...
...
doc/src/sgml/syntax.sgml
View file @
4996eea8
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.7
4 2002/11/15 03:11:17
momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.7
5 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');
...
@@ -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> )
...
@@ -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>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment