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
705869dd
Commit
705869dd
authored
Oct 12, 2001
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Uppercase keywords where appropriate.
parent
b5770567
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
215 additions
and
222 deletions
+215
-222
doc/src/sgml/gist.sgml
doc/src/sgml/gist.sgml
+3
-3
doc/src/sgml/jdbc.sgml
doc/src/sgml/jdbc.sgml
+7
-7
doc/src/sgml/libpgtcl.sgml
doc/src/sgml/libpgtcl.sgml
+1
-1
doc/src/sgml/libpq++.sgml
doc/src/sgml/libpq++.sgml
+3
-3
doc/src/sgml/libpq.sgml
doc/src/sgml/libpq.sgml
+8
-8
doc/src/sgml/maintenance.sgml
doc/src/sgml/maintenance.sgml
+2
-2
doc/src/sgml/perform.sgml
doc/src/sgml/perform.sgml
+13
-13
doc/src/sgml/plsql.sgml
doc/src/sgml/plsql.sgml
+119
-124
doc/src/sgml/spi.sgml
doc/src/sgml/spi.sgml
+14
-14
doc/src/sgml/syntax.sgml
doc/src/sgml/syntax.sgml
+2
-2
doc/src/sgml/trigger.sgml
doc/src/sgml/trigger.sgml
+19
-19
doc/src/sgml/typeconv.sgml
doc/src/sgml/typeconv.sgml
+24
-26
No files found.
doc/src/sgml/gist.sgml
View file @
705869dd
...
@@ -51,8 +51,8 @@ to check that. Other examples also worked, except polygons: I got an
...
@@ -51,8 +51,8 @@ to check that. Other examples also worked, except polygons: I got an
error doing
error doing
<ProgramListing>
<ProgramListing>
test=>
create index pix on
polytmp
test=>
CREATE INDEX pix ON
polytmp
test->
using gist (p:box gist_poly_ops) with (islossy
);
test->
USING GIST (p:box gist_poly_ops) WITH (ISLOSSY
);
ERROR: cannot open pix
ERROR: cannot open pix
(PostgreSQL 6.3 Sun Feb 1 14:57:30 EST 1998)
(PostgreSQL 6.3 Sun Feb 1 14:57:30 EST 1998)
...
@@ -92,7 +92,7 @@ A few notes on the sources:
...
@@ -92,7 +92,7 @@ A few notes on the sources:
<ProgramListing>
<ProgramListing>
-- -- there's a memory leak in rtree poly_ops!!
-- -- there's a memory leak in rtree poly_ops!!
-- --
create index pix2 on polytmp using rtree
(p poly_ops);
-- --
CREATE INDEX pix2 ON polytmp USING RTREE
(p poly_ops);
</ProgramListing>
</ProgramListing>
Roger that!! I thought it could be related to a number of
Roger that!! I thought it could be related to a number of
...
...
doc/src/sgml/jdbc.sgml
View file @
705869dd
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.2
5 2001/09/13 15:55:22 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.2
6 2001/10/12 23:32:33 momjian
Exp $
-->
-->
<chapter id="jdbc">
<chapter id="jdbc">
...
@@ -2311,21 +2311,21 @@ public void unlink(int oid) throws SQLException
...
@@ -2311,21 +2311,21 @@ public void unlink(int oid) throws SQLException
One of the consequences of this, is that you can have one table
One of the consequences of this, is that you can have one table
refer to a row in another table. For example:
refer to a row in another table. For example:
<screen>
<screen>
test=>
create table users (username name,fullname text
);
test=>
CREATE TABLE users (username NAME,fullname TEXT
);
CREATE
CREATE
test=>
create table server (servername name
,adminuser users);
test=>
CREATE TABLE server (servername NAME
,adminuser users);
CREATE
CREATE
test=>
insert into users values
('peter','Peter Mount');
test=>
INSERT INTO users VALUES
('peter','Peter Mount');
INSERT 2610132 1
INSERT 2610132 1
test=>
insert into server values
('maidast',2610132::users);
test=>
INSERT INTO server VALUES
('maidast',2610132::users);
INSERT 2610133 1
INSERT 2610133 1
test=>
select * from
users;
test=>
SELECT * FROM
users;
username|fullname
username|fullname
--------+--------------
--------+--------------
peter |Peter Mount
peter |Peter Mount
(1 row)
(1 row)
test=>
select * from
server;
test=>
SELECT * FROM
server;
servername|adminuser
servername|adminuser
----------+---------
----------+---------
maidast | 2610132
maidast | 2610132
...
...
doc/src/sgml/libpgtcl.sgml
View file @
705869dd
...
@@ -917,7 +917,7 @@ given chunk of code for each tuple in the result.
...
@@ -917,7 +917,7 @@ given chunk of code for each tuple in the result.
This would work if table <classname>table</> has fields <structfield>control</> and <structfield>name</>
This would work if table <classname>table</> has fields <structfield>control</> and <structfield>name</>
(and, perhaps, other fields):
(and, perhaps, other fields):
<ProgramListing>
<ProgramListing>
pg_select $pgconn "SELECT *
from
table" array {
pg_select $pgconn "SELECT *
FROM
table" array {
puts [format "%5d %s" array(control) array(name)]
puts [format "%5d %s" array(control) array(name)]
}
}
</ProgramListing>
</ProgramListing>
...
...
doc/src/sgml/libpq++.sgml
View file @
705869dd
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.3
2 2001/09/13 15:55:23 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.3
3 2001/10/12 23:32:34 momjian
Exp $
-->
-->
<chapter id="libpqplusplus">
<chapter id="libpqplusplus">
...
@@ -794,8 +794,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.32 2001/09/13 15:55:
...
@@ -794,8 +794,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.32 2001/09/13 15:55:
<programlisting>
<programlisting>
PgDatabase data;
PgDatabase data;
data.Exec("
create table
foo (a int4, b char(16), d double precision)");
data.Exec("
CREATE TABLE
foo (a int4, b char(16), d double precision)");
data.Exec("
copy foo from stdin
");
data.Exec("
COPY foo FROM STDIN
");
data.PutLine("3\tHello World\t4.5\n");
data.PutLine("3\tHello World\t4.5\n");
data.PutLine("4\tGoodbye World\t7.11\n");
data.PutLine("4\tGoodbye World\t7.11\n");
&...
&...
...
...
doc/src/sgml/libpq.sgml
View file @
705869dd
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.7
2 2001/09/13 15:55:23 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.7
3 2001/10/12 23:32:34 momjian
Exp $
-->
-->
<chapter id="libpq">
<chapter id="libpq">
...
@@ -302,11 +302,11 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn)
...
@@ -302,11 +302,11 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn)
proceed with the connection sequence. Loop thus: Consider a connection
proceed with the connection sequence. Loop thus: Consider a connection
<quote>inactive</quote> by default. If <function>PQconnectPoll</function> last returned <symbol>PGRES_POLLING_ACTIVE</>,
<quote>inactive</quote> by default. If <function>PQconnectPoll</function> last returned <symbol>PGRES_POLLING_ACTIVE</>,
consider it <quote>active</quote> instead. If <function>PQconnectPoll(conn)</function> last returned
consider it <quote>active</quote> instead. If <function>PQconnectPoll(conn)</function> last returned
<symbol>PGRES_POLLING_READING</symbol>, perform a
select
for reading on <function>PQsocket(conn)</function>. If
<symbol>PGRES_POLLING_READING</symbol>, perform a
SELECT
for reading on <function>PQsocket(conn)</function>. If
it last returned <symbol>PGRES_POLLING_WRITING</symbol>, perform a
select
for writing on
it last returned <symbol>PGRES_POLLING_WRITING</symbol>, perform a
SELECT
for writing on
<function>PQsocket(conn)</function>. If you have yet to call <function>PQconnectPoll</function>, i.e. after the call
<function>PQsocket(conn)</function>. If you have yet to call <function>PQconnectPoll</function>, i.e. after the call
to <function>PQconnectStart</function>, behave as if it last returned <symbol>PGRES_POLLING_WRITING</symbol>. If
to <function>PQconnectStart</function>, behave as if it last returned <symbol>PGRES_POLLING_WRITING</symbol>. If
the
select
shows that the socket is ready, consider it <quote>active</quote>. If it has
the
SELECT
shows that the socket is ready, consider it <quote>active</quote>. If it has
been decided that this connection is <quote>active</quote>, call <function>PQconnectPoll(conn)</function>
been decided that this connection is <quote>active</quote>, call <function>PQconnectPoll(conn)</function>
again. If this call returns <symbol>PGRES_POLLING_FAILED</symbol>, the connection procedure
again. If this call returns <symbol>PGRES_POLLING_FAILED</symbol>, the connection procedure
has failed. If this call returns <symbol>PGRES_POLLING_OK</symbol>, the connection has been
has failed. If this call returns <symbol>PGRES_POLLING_OK</symbol>, the connection has been
...
@@ -1763,8 +1763,8 @@ int PQendcopy(PGconn *conn);
...
@@ -1763,8 +1763,8 @@ int PQendcopy(PGconn *conn);
As an example:
As an example:
<programlisting>
<programlisting>
PQexec(conn, "
create table
foo (a int4, b char(16), d double precision)");
PQexec(conn, "
CREATE TABLE
foo (a int4, b char(16), d double precision)");
PQexec(conn, "
copy foo from stdin
");
PQexec(conn, "
COPY foo FROM STDIN
");
PQputline(conn, "3\thello world\t4.5\n");
PQputline(conn, "3\thello world\t4.5\n");
PQputline(conn,"4\tgoodbye world\t7.11\n");
PQputline(conn,"4\tgoodbye world\t7.11\n");
...
...
...
@@ -2270,7 +2270,7 @@ main()
...
@@ -2270,7 +2270,7 @@ main()
* fetch rows from the pg_database, the system catalog of
* fetch rows from the pg_database, the system catalog of
* databases
* databases
*/
*/
res = PQexec(conn, "DECLARE mycursor CURSOR FOR
select * from
pg_database");
res = PQexec(conn, "DECLARE mycursor CURSOR FOR
SELECT * FROM
pg_database");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
{
fprintf(stderr, "DECLARE CURSOR command failed\n");
fprintf(stderr, "DECLARE CURSOR command failed\n");
...
@@ -2541,7 +2541,7 @@ main()
...
@@ -2541,7 +2541,7 @@ main()
* fetch rows from the pg_database, the system catalog of
* fetch rows from the pg_database, the system catalog of
* databases
* databases
*/
*/
res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR
select * from
test1");
res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR
SELECT * FROM
test1");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
{
fprintf(stderr, "DECLARE CURSOR command failed\n");
fprintf(stderr, "DECLARE CURSOR command failed\n");
...
...
doc/src/sgml/maintenance.sgml
View file @
705869dd
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.
4 2001/09/23 04:06:2
4 momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.
5 2001/10/12 23:32:3
4 momjian Exp $
-->
-->
<chapter id="maintenance">
<chapter id="maintenance">
...
@@ -304,7 +304,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.4 2001/09/23 04:06:24
...
@@ -304,7 +304,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/maintenance.sgml,v 1.4 2001/09/23 04:06:24
examine this information is to execute the query
examine this information is to execute the query
<informalexample>
<informalexample>
<programlisting>
<programlisting>
select datname, age(datfrozenxid) from
pg_database;
SELECT datname, age(datfrozenxid) FROM
pg_database;
</programlisting>
</programlisting>
</informalexample>
</informalexample>
The <literal>age</> column measures the number of transactions from the
The <literal>age</> column measures the number of transactions from the
...
...
doc/src/sgml/perform.sgml
View file @
705869dd
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.1
1 2001/10/09 18:46:00 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.1
2 2001/10/12 23:32:34 momjian
Exp $
-->
-->
<chapter id="performance-tips">
<chapter id="performance-tips">
...
@@ -95,7 +95,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.11 2001/10/09 18:46:00 pet
...
@@ -95,7 +95,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.11 2001/10/09 18:46:00 pet
vacuum analyze, and 7.2 development sources):
vacuum analyze, and 7.2 development sources):
<programlisting>
<programlisting>
regression=#
explain select * from
tenk1;
regression=#
EXPLAIN SELECT * FROM
tenk1;
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
...
@@ -106,7 +106,7 @@ Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
...
@@ -106,7 +106,7 @@ Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
This is about as straightforward as it gets. If you do
This is about as straightforward as it gets. If you do
<programlisting>
<programlisting>
select * from pg_class where
relname = 'tenk1';
SELECT * FROM pg_class WHERE
relname = 'tenk1';
</programlisting>
</programlisting>
you will find out that <classname>tenk1</classname> has 233 disk
you will find out that <classname>tenk1</classname> has 233 disk
...
@@ -119,7 +119,7 @@ select * from pg_class where relname = 'tenk1';
...
@@ -119,7 +119,7 @@ select * from pg_class where relname = 'tenk1';
Now let's modify the query to add a qualification clause:
Now let's modify the query to add a qualification clause:
<programlisting>
<programlisting>
regression=#
explain select * from tenk1 where
unique1 < 1000;
regression=#
EXPLAIN SELECT * FROM tenk1 WHERE
unique1 < 1000;
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
Seq Scan on tenk1 (cost=0.00..358.00 rows=1007 width=148)
Seq Scan on tenk1 (cost=0.00..358.00 rows=1007 width=148)
...
@@ -144,7 +144,7 @@ Seq Scan on tenk1 (cost=0.00..358.00 rows=1007 width=148)
...
@@ -144,7 +144,7 @@ Seq Scan on tenk1 (cost=0.00..358.00 rows=1007 width=148)
Modify the query to restrict the qualification even more:
Modify the query to restrict the qualification even more:
<programlisting>
<programlisting>
regression=#
explain select * from tenk1 where
unique1 < 50;
regression=#
EXPLAIN SELECT * FROM tenk1 WHERE
unique1 < 50;
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.09 rows=49 width=148)
Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.09 rows=49 width=148)
...
@@ -162,7 +162,7 @@ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.09 rows=49 width=148)
...
@@ -162,7 +162,7 @@ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.09 rows=49 width=148)
Add another condition to the qualification:
Add another condition to the qualification:
<programlisting>
<programlisting>
regression=#
explain select * from tenk1 where unique1 < 50 and
regression=#
EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50 AND
regression-# stringu1 = 'xxx';
regression-# stringu1 = 'xxx';
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
...
@@ -177,8 +177,8 @@ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.22 rows=1 width=148)
...
@@ -177,8 +177,8 @@ Index Scan using tenk1_unique1 on tenk1 (cost=0.00..181.22 rows=1 width=148)
Let's try joining two tables, using the fields we have been discussing:
Let's try joining two tables, using the fields we have been discussing:
<programlisting>
<programlisting>
regression=#
explain select * from tenk1 t1, tenk2 t2 where
t1.unique1 < 50
regression=#
EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE
t1.unique1 < 50
regression-#
and
t1.unique2 = t2.unique2;
regression-#
AND
t1.unique2 = t2.unique2;
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
Nested Loop (cost=0.00..330.41 rows=49 width=296)
Nested Loop (cost=0.00..330.41 rows=49 width=296)
...
@@ -225,8 +225,8 @@ Nested Loop (cost=0.00..330.41 rows=49 width=296)
...
@@ -225,8 +225,8 @@ Nested Loop (cost=0.00..330.41 rows=49 width=296)
<programlisting>
<programlisting>
regression=# set enable_nestloop = off;
regression=# set enable_nestloop = off;
SET VARIABLE
SET VARIABLE
regression=#
explain select * from tenk1 t1, tenk2 t2 where
t1.unique1 < 50
regression=#
EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE
t1.unique1 < 50
regression-#
and
t1.unique2 = t2.unique2;
regression-#
AND
t1.unique2 = t2.unique2;
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
Hash Join (cost=181.22..564.83 rows=49 width=296)
Hash Join (cost=181.22..564.83 rows=49 width=296)
...
@@ -257,9 +257,9 @@ Hash Join (cost=181.22..564.83 rows=49 width=296)
...
@@ -257,9 +257,9 @@ Hash Join (cost=181.22..564.83 rows=49 width=296)
For example, we might get a result like this:
For example, we might get a result like this:
<screen>
<screen>
regression=#
explain analyze
regression=#
EXPLAIN ANALYZE
regression-#
select * from
tenk1 t1, tenk2 t2
regression-#
SELECT * FROM
tenk1 t1, tenk2 t2
regression-#
where t1.unique1 < 50 and
t1.unique2 = t2.unique2;
regression-#
WHERE t1.unique1 < 50 AND
t1.unique2 = t2.unique2;
NOTICE: QUERY PLAN:
NOTICE: QUERY PLAN:
Nested Loop (cost=0.00..330.41 rows=49 width=296) (actual time=1.31..28.90 rows=50 loops=1)
Nested Loop (cost=0.00..330.41 rows=49 width=296) (actual time=1.31..28.90 rows=50 loops=1)
...
...
doc/src/sgml/plsql.sgml
View file @
705869dd
<
!--
<
!--
$
Header
:
/
cvsroot
/
pgsql
/
doc
/
src
/
sgml
/
Attic
/
plsql
.
sgml
,
v
2.4
3
2001
/
10
/
12
21
:
19
:
09
momjian
Exp
$
$
Header
:
/
cvsroot
/
pgsql
/
doc
/
src
/
sgml
/
Attic
/
plsql
.
sgml
,
v
2.4
4
2001
/
10
/
12
23
:
32
:
34
momjian
Exp
$
-->
-->
<
chapter
id
=
"plpgsql"
>
<
chapter
id
=
"plpgsql"
>
...
@@ -709,10 +709,10 @@ PERFORM <replaceable>query</replaceable>
...
@@ -709,10 +709,10 @@ PERFORM <replaceable>query</replaceable>
</
para
>
</
para
>
<
programlisting
>
<
programlisting
>
PERFORM
create_mv
(
''
cs_session_page_requests_mv
''
,
''
PERFORM
create_mv
(
''
cs_session_page_requests_mv
''
,
''
select
session_id
,
page_id
,
count
(*)
as
n_hits
,
SELECT
session_id
,
page_id
,
count
(*)
AS
n_hits
,
sum
(
dwell_time
)
as
dwell_time
,
count
(
dwell_time
)
as
dwell_count
sum
(
dwell_time
)
AS
dwell_time
,
count
(
dwell_time
)
AS
dwell_count
from
cs_fact_table
FROM
cs_fact_table
group
by
session_id
,
page_id
''
);
GROUP
BY
session_id
,
page_id
''
);
</
programlisting
>
</
programlisting
>
</
sect3
>
</
sect3
>
...
@@ -804,19 +804,19 @@ BEGIN
...
@@ -804,19 +804,19 @@ BEGIN
-- using the FOR <record> construct.
-- using the FOR <record> construct.
--
--
FOR referrer_keys IN
select * from cs_referrer_keys order by
try_order LOOP
FOR referrer_keys IN
SELECT * FROM cs_referrer_keys ORDER BY
try_order LOOP
a_output := a_output || ''
if v_'' || referrer_keys.kind || '' like
''''''''''
a_output := a_output || ''
IF v_'' || referrer_keys.kind || '' LIKE
''''''''''
|| referrer_keys.key_string || ''''''''''
then return
''''''
|| referrer_keys.key_string || ''''''''''
THEN RETURN
''''''
|| referrer_keys.referrer_type || '''''';
end if
;'';
|| referrer_keys.referrer_type || '''''';
END IF
;'';
END LOOP;
END LOOP;
a_output := a_output || ''
return null; end; '''' language
''''plpgsql'''';'';
a_output := a_output || ''
RETURN NULL; END; '''' LANGUAGE
''''plpgsql'''';'';
-- This works because we are not substituting any variables
-- This works because we are not substituting any variables
-- Otherwise it would fail. Look at PERFORM for another way to run functions
-- Otherwise it would fail. Look at PERFORM for another way to run functions
EXECUTE a_output;
EXECUTE a_output;
end
;
END
;
'
LANGUAGE
'plpgsql'
;
'
LANGUAGE
'plpgsql'
;
</
programlisting
>
</
programlisting
>
</
para
>
</
para
>
...
@@ -1262,7 +1262,7 @@ BEGIN
...
@@ -1262,7 +1262,7 @@ BEGIN
IF
users_rec
.
homepage
IS
NULL
THEN
IF
users_rec
.
homepage
IS
NULL
THEN
--
user
entered
no
homepage
,
return
"http://"
--
user
entered
no
homepage
,
return
"http://"
return
''
http
://
''
;
RETURN
''
http
://
''
;
END
IF
;
END
IF
;
END
;
END
;
</
programlisting
>
</
programlisting
>
...
@@ -1283,13 +1283,13 @@ FOR <replaceable>record | row</replaceable> IN <replaceable>select_clause</repla
...
@@ -1283,13 +1283,13 @@ FOR <replaceable>record | row</replaceable> IN <replaceable>select_clause</repla
END
LOOP
;
END
LOOP
;
</
synopsis
>
</
synopsis
>
The
record
or
row
is
assigned
all
the
rows
The
record
or
row
is
assigned
all
the
rows
resulting
from
the
select
clause
and
the
loop
body
executed
resulting
from
the
SELECT
clause
and
the
loop
body
executed
for
each
.
Here
is
an
example
:
for
each
.
Here
is
an
example
:
</
para
>
</
para
>
<
para
>
<
para
>
<
programlisting
>
<
programlisting
>
create
function
cs_refresh_mviews
()
returns
INTEGER
as
'
CREATE
FUNCTION
cs_refresh_mviews
()
RETURNS
INTEGER
AS
'
DECLARE
DECLARE
mviews RECORD;
mviews RECORD;
...
@@ -1310,7 +1310,7 @@ BEGIN
...
@@ -1310,7 +1310,7 @@ BEGIN
END LOOP;
END LOOP;
PERFORM cs_log(''Done refreshing materialized views.'');
PERFORM cs_log(''Done refreshing materialized views.'');
return
1;
RETURN
1;
end;
end;
'
language
'plpgsql'
;
'
language
'plpgsql'
;
</
programlisting
>
</
programlisting
>
...
@@ -2030,25 +2030,25 @@ END;
...
@@ -2030,25 +2030,25 @@ END;
single quotes in PostgreSQL.
single quotes in PostgreSQL.
<programlisting>
<programlisting>
create or replace procedure cs_update_referrer_type_proc is
CREATE OR REPLACE PROCEDURE cs_update_referrer_type_proc IS
cursor referrer_keys is
CURSOR referrer_keys IS
select * from
cs_referrer_keys
SELECT * FROM
cs_referrer_keys
order by
try_order;
ORDER BY
try_order;
a_output
varchar
(4000);
a_output
VARCHAR
(4000);
begin
BEGIN
a_output := '
create
or
replace
function
cs_find_referrer_type
(
v_host
IN
varchar
,
v_domain
IN
varchar
,
a_output := '
CREATE
OR
REPLACE
FUNCTION
cs_find_referrer_type
(
v_host
IN
VARCHAR
,
v_domain
IN
VARCHAR
,
v_url
IN
varchar
)
return
varchar
is
begin
';
v_url
IN
VARCHAR
)
RETURN
VARCHAR
IS
BEGIN
';
for referrer_key in referrer_keys loop
FOR referrer_key IN referrer_keys LOOP
a_output := a_output || '
if
v_
' || referrer_key.kind || '
like
''' ||
a_output := a_output || '
IF
v_
' || referrer_key.kind || '
LIKE
''' ||
referrer_key.key_string || '''
then
return
''' || referrer_key.referrer_type ||
referrer_key.key_string || '''
THEN
RETURN
''' || referrer_key.referrer_type ||
'''
;
end
if
;
';
'''
;
END
IF
;
';
end loop
;
END LOOP
;
a_output := a_output || '
return
null
;
end
;
';
a_output := a_output || '
RETURN
NULL
;
END
;
';
execute immediate
a_output;
EXECUTE IMMEDIATE
a_output;
end
;
END
;
/
/
show errors
show errors
</programlisting>
</programlisting>
...
@@ -2075,19 +2075,19 @@ BEGIN
...
@@ -2075,19 +2075,19 @@ BEGIN
--
using
the
FOR
&
lt
;
record
&
gt
;
construct
.
--
using
the
FOR
&
lt
;
record
&
gt
;
construct
.
--
--
FOR
referrer_keys
IN
select
*
from
cs_referrer_keys
order
by
try_order
LOOP
FOR
referrer_keys
IN
SELECT
*
FROM
cs_referrer_keys
ORDER
BY
try_order
LOOP
a_output
:=
a_output
||
''
if
v_
''
||
referrer_keys
.
kind
||
''
like
''''''''''
a_output
:=
a_output
||
''
IF
v_
''
||
referrer_keys
.
kind
||
''
LIKE
''''''''''
||
referrer_keys
.
key_string
||
''''''''''
then
return
''''''
||
referrer_keys
.
key_string
||
''''''''''
THEN
RETURN
''''''
||
referrer_keys
.
referrer_type
||
''''''
;
end
if
;
''
;
||
referrer_keys
.
referrer_type
||
''''''
;
END
IF
;
''
;
END
LOOP
;
END
LOOP
;
a_output
:=
a_output
||
''
return
null
;
end
;
''''
language
''''
plpgsql
''''
;
''
;
a_output
:=
a_output
||
''
RETURN
NULL
;
END
;
''''
LANGUAGE
''''
plpgsql
''''
;
''
;
--
This
works
because
we
are
not
substituting
any
variables
--
This
works
because
we
are
not
substituting
any
variables
--
Otherwise
it
would
fail
.
Look
at
PERFORM
for
another
way
to
run
functions
--
Otherwise
it
would
fail
.
Look
at
PERFORM
for
another
way
to
run
functions
EXECUTE
a_output
;
EXECUTE
a_output
;
end
;
END
;
' LANGUAGE '
plpgsql
';
' LANGUAGE '
plpgsql
';
</programlisting>
</programlisting>
</para>
</para>
...
@@ -2109,41 +2109,41 @@ end;
...
@@ -2109,41 +2109,41 @@ end;
</para>
</para>
<programlisting>
<programlisting>
create or replace procedure
cs_parse_url(
CREATE OR REPLACE PROCEDURE
cs_parse_url(
v_url IN
varchar
,
v_url IN
VARCHAR
,
v_host OUT
varchar
, -- This will be passed back
v_host OUT
VARCHAR
, -- This will be passed back
v_path OUT
varchar
, -- This one too
v_path OUT
VARCHAR
, -- This one too
v_query OUT
varchar
) -- And this one
v_query OUT
VARCHAR
) -- And this one
is
is
a_pos1
integer
;
a_pos1
INTEGER
;
a_pos2
integer
;
a_pos2
INTEGER
;
begin
begin
v_host := NULL;
v_host := NULL;
v_path := NULL;
v_path := NULL;
v_query := NULL;
v_query := NULL;
a_pos1 := instr(v_url, '
//
'); -- PostgreSQL doesn'
t
have
an
instr
function
a_pos1 := instr(v_url, '
//
'); -- PostgreSQL doesn'
t
have
an
instr
function
if
a_pos1
=
0
then
IF
a_pos1
=
0
THEN
return
;
RETURN
;
end
if
;
END
IF
;
a_pos2
:=
instr
(
v_url
,
'/'
,
a_pos1
+
2
);
a_pos2
:=
instr
(
v_url
,
'/'
,
a_pos1
+
2
);
if
a_pos2
=
0
then
IF
a_pos2
=
0
THEN
v_host
:=
substr
(
v_url
,
a_pos1
+
2
);
v_host
:=
substr
(
v_url
,
a_pos1
+
2
);
v_path
:=
'/'
;
v_path
:=
'/'
;
return
;
RETURN
;
end
if
;
END
IF
;
v_host
:=
substr
(
v_url
,
a_pos1
+
2
,
a_pos2
-
a_pos1
-
2
);
v_host
:=
substr
(
v_url
,
a_pos1
+
2
,
a_pos2
-
a_pos1
-
2
);
a_pos1
:=
instr
(
v_url
,
'?'
,
a_pos2
+
1
);
a_pos1
:=
instr
(
v_url
,
'?'
,
a_pos2
+
1
);
if
a_pos1
=
0
then
IF
a_pos1
=
0
THEN
v_path
:=
substr
(
v_url
,
a_pos2
);
v_path
:=
substr
(
v_url
,
a_pos2
);
return
;
RETURN
;
end
if
;
END
IF
;
v_path
:=
substr
(
v_url
,
a_pos2
,
a_pos1
-
a_pos2
);
v_path
:=
substr
(
v_url
,
a_pos2
,
a_pos1
-
a_pos2
);
v_query
:=
substr
(
v_url
,
a_pos1
+
1
);
v_query
:=
substr
(
v_url
,
a_pos1
+
1
);
end
;
END
;
/
/
show
errors
;
show
errors
;
</
programlisting
>
</
programlisting
>
...
@@ -2152,34 +2152,34 @@ show errors;
...
@@ -2152,34 +2152,34 @@ show errors;
Here
is
how
this
procedure
could
be
translated
for
PostgreSQL
:
Here
is
how
this
procedure
could
be
translated
for
PostgreSQL
:
<
programlisting
>
<
programlisting
>
drop
function
cs_parse_url_host
(
VARCHAR
);
DROP
FUNCTION
cs_parse_url_host
(
VARCHAR
);
create
function
cs_parse_url_host
(
VARCHAR
)
RETURNS
VARCHAR
AS
'
CREATE
FUNCTION
cs_parse_url_host
(
VARCHAR
)
RETURNS
VARCHAR
AS
'
declare
DECLARE
v_url ALIAS FOR $1;
v_url ALIAS FOR $1;
v_host
varchar
;
v_host
VARCHAR
;
v_path
varchar
;
v_path
VARCHAR
;
a_pos1
integer
;
a_pos1
INTEGER
;
a_pos2
integer
;
a_pos2
INTEGER
;
a_pos3
integer
;
a_pos3
INTEGER
;
begin
BEGIN
v_host := NULL;
v_host := NULL;
a_pos1 := instr(v_url,''//'');
a_pos1 := instr(v_url,''//'');
if a_pos1 = 0 then
IF a_pos1 = 0 THEN
return
''''; -- Return a blank
RETURN
''''; -- Return a blank
end if
;
END IF
;
a_pos2 := instr(v_url,''/'',a_pos1 + 2);
a_pos2 := instr(v_url,''/'',a_pos1 + 2);
if a_pos2 = 0 then
IF a_pos2 = 0 THEN
v_host := substr(v_url, a_pos1 + 2);
v_host := substr(v_url, a_pos1 + 2);
v_path := ''/'';
v_path := ''/'';
return
v_host;
RETURN
v_host;
end if
;
END IF
;
v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2 );
v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2 );
return
v_host;
RETURN
v_host;
end
;
END
;
'
language
'plpgsql'
;
'
LANGUAGE
'plpgsql'
;
</
programlisting
>
</
programlisting
>
</
para
>
</
para
>
</
example
>
</
example
>
...
@@ -2211,30 +2211,30 @@ end;
...
@@ -2211,30 +2211,30 @@ end;
An example:
An example:
<programlisting>
<programlisting>
create or replace procedure cs_create_job(v_job_id in integer)
CREATE OR REPLACE PROCEDURE cs_create_job(v_job_id IN INTEGER) IS
is
a_running_job_count INTEGER;
a_running_job_count integer;
PRAGMA AUTONOMOUS_TRANSACTION;<co id="co.plpgsql-porting-pragma">
pragma autonomous_transaction;<co id="co.plpgsql-porting-pragma">
BEGIN
begin
LOCK TABLE cs_jobs IN EXCLUSIVE MODE;<co id="co.plpgsql-porting-locktable">
lock table cs_jobs in exclusive mode;<co id="co.plpgsql-porting-locktable">
select count(*) into a_running_job_count from cs_jobs
SELECT count(*) INTO a_running_job_count
where end_stamp is null;
FROM cs_jobs
WHERE end_stamp IS NULL;
if a_running_job_count > 0 then
IF a_running_job_count > 0 THEN
commit
; -- free lock<co id="co.plpgsql-porting-commit">
COMMIT
; -- free lock<co id="co.plpgsql-porting-commit">
raise_application_error(-20000, '
Unable
to
create
a
new
job
:
a
job
is
currently
running
.
');
raise_application_error(-20000, '
Unable
to
create
a
new
job
:
a
job
is
currently
running
.
');
end if
;
END IF
;
delete from
cs_active_job;
DELETE FROM
cs_active_job;
insert into cs_active_job(job_id) values
(v_job_id);
INSERT INTO cs_active_job(job_id) VALUES
(v_job_id);
begin
BEGIN
insert into cs_jobs(job_id, start_stamp) values
(v_job_id, sysdate);
INSERT INTO cs_jobs (job_id, start_stamp) VALUES
(v_job_id, sysdate);
exception when dup_val_on_index then null
; -- don'
t
worry
if
it
already
exists
<
co
id
=
"co.plpgsql-porting-exception"
>
EXCEPTION WHEN dup_val_on_index THEN NULL
; -- don'
t
worry
if
it
already
exists
<
co
id
=
"co.plpgsql-porting-exception"
>
end
;
END
;
commit
;
COMMIT
;
end
;
END
;
/
/
show
errors
show
errors
</
programlisting
>
</
programlisting
>
...
@@ -2282,12 +2282,12 @@ show errors
...
@@ -2282,12 +2282,12 @@ show errors
So
let
's see one of the ways we could port this procedure to <application>PL/pgSQL</>:
So
let
's see one of the ways we could port this procedure to <application>PL/pgSQL</>:
<programlisting>
<programlisting>
drop function
cs_create_job(INTEGER);
DROP FUNCTION
cs_create_job(INTEGER);
create function
cs_create_job(INTEGER) RETURNS INTEGER AS '
DECLARE
CREATE FUNCTION
cs_create_job(INTEGER) RETURNS INTEGER AS '
DECLARE
v_job_id
ALIAS
FOR
$
1
;
v_job_id
ALIAS
FOR
$
1
;
a_running_job_count
INTEGER
;
a_running_job_count
INTEGER
;
a_num
integer
;
a_num
INTEGER
;
--
pragma
autonomous_transaction
;
--
PRAGMA
AUTONOMOUS_TRANSACTION
;
BEGIN
BEGIN
LOCK
TABLE
cs_jobs
IN
EXCLUSIVE
MODE
;
LOCK
TABLE
cs_jobs
IN
EXCLUSIVE
MODE
;
SELECT
count
(*)
INTO
a_running_job_count
SELECT
count
(*)
INTO
a_running_job_count
...
@@ -2351,29 +2351,25 @@ END;
...
@@ -2351,29 +2351,25 @@ END;
System
</
ulink
>):
System
</
ulink
>):
<
programlisting
>
<
programlisting
>
create
or
replace
package
body
acs
CREATE
OR
REPLACE
PACKAGE
BODY
acs
as
AS
function
add_user
(
FUNCTION
add_user
(
user_id
in
users
.
user_id
%
TYPE
default
null
,
user_id
IN
users
.
user_id
%
TYPE
DEFAULT
NULL
,
object_type
in
acs_objects
.
object_type
%
TYPE
object_type
IN
acs_objects
.
object_type
%
TYPE
DEFAULT
'user'
,
default
'user'
,
creation_date
IN
acs_objects
.
creation_date
%
TYPE
DEFAULT
sysdate
,
creation_date
in
acs_objects
.
creation_date
%
TYPE
creation_user
IN
acs_objects
.
creation_user
%
TYPE
DEFAULT
NULL
,
default
sysdate
,
creation_ip
IN
acs_objects
.
creation_ip
%
TYPE
DEFAULT
NULL
,
creation_user
in
acs_objects
.
creation_user
%
TYPE
default
null
,
creation_ip
in
acs_objects
.
creation_ip
%
TYPE
default
null
,
...
...
)
return
users
.
user_id
%
TYPE
)
RETURN
users
.
user_id
%
TYPE
is
IS
v_user_id
users
.
user_id
%
TYPE
;
v_user_id
users
.
user_id
%
TYPE
;
v_rel_id
membership_rels
.
rel_id
%
TYPE
;
v_rel_id
membership_rels
.
rel_id
%
TYPE
;
begin
BEGIN
v_user_id
:=
acs_user
.
new
(
user_id
,
object_type
,
creation_date
,
v_user_id
:=
acs_user
.
new
(
user_id
,
object_type
,
creation_date
,
creation_user
,
creation_ip
,
email
,
creation_user
,
creation_ip
,
email
,
...
...
RETURN
v_user_id
;
return
v_user_id
;
END
;
end
;
END
acs
;
end
acs
;
/
/
show
errors
show
errors
</
programlisting
>
</
programlisting
>
...
@@ -2491,7 +2487,7 @@ BEGIN
...
@@ -2491,7 +2487,7 @@ BEGIN
pos
:=
instr
($
1
,$
2
,
1
);
pos
:=
instr
($
1
,$
2
,
1
);
RETURN
pos
;
RETURN
pos
;
END
;
END
;
'
language
'
plpgsql
';
'
LANGUAGE
'
plpgsql
';
DROP FUNCTION instr(VARCHAR,VARCHAR,INTEGER);
DROP FUNCTION instr(VARCHAR,VARCHAR,INTEGER);
...
@@ -2501,10 +2497,10 @@ DECLARE
...
@@ -2501,10 +2497,10 @@ DECLARE
string_to_search
ALIAS
FOR
$
2
;
string_to_search
ALIAS
FOR
$
2
;
beg_index
ALIAS
FOR
$
3
;
beg_index
ALIAS
FOR
$
3
;
pos
integer
NOT
NULL
DEFAULT
0
;
pos
integer
NOT
NULL
DEFAULT
0
;
temp_str
varchar
;
temp_str
VARCHAR
;
beg
integer
;
beg
INTEGER
;
length
integer
;
length
INTEGER
;
ss_length
integer
;
ss_length
INTEGER
;
BEGIN
BEGIN
IF
beg_index
>
0
THEN
IF
beg_index
>
0
THEN
...
@@ -2522,7 +2518,6 @@ BEGIN
...
@@ -2522,7 +2518,6 @@ BEGIN
beg
:=
length
+
beg_index
-
ss_length
+
2
;
beg
:=
length
+
beg_index
-
ss_length
+
2
;
WHILE
beg
>
0
LOOP
WHILE
beg
>
0
LOOP
temp_str
:=
substring
(
string
FROM
beg
FOR
ss_length
);
temp_str
:=
substring
(
string
FROM
beg
FOR
ss_length
);
pos
:=
position
(
string_to_search
IN
temp_str
);
pos
:=
position
(
string_to_search
IN
temp_str
);
...
@@ -2549,7 +2544,7 @@ DECLARE
...
@@ -2549,7 +2544,7 @@ DECLARE
beg_index
ALIAS
FOR
$
3
;
beg_index
ALIAS
FOR
$
3
;
occur_index
ALIAS
FOR
$
4
;
occur_index
ALIAS
FOR
$
4
;
pos
integer
NOT
NULL
DEFAULT
0
;
pos
integer
NOT
NULL
DEFAULT
0
;
occur_number
integer
NOT
NULL
DEFAULT
0
;
occur_number
INTEGER
NOT
NULL
DEFAULT
0
;
temp_str
VARCHAR
;
temp_str
VARCHAR
;
beg
INTEGER
;
beg
INTEGER
;
i
INTEGER
;
i
INTEGER
;
...
...
doc/src/sgml/spi.sgml
View file @
705869dd
...
@@ -447,7 +447,7 @@ Maximum number of tuples to return
...
@@ -447,7 +447,7 @@ Maximum number of tuples to return
which the query will be executed. For example,
which the query will be executed. For example,
<ProgramListing>
<ProgramListing>
SPI_exec ("
insert into table select * from table
", 5);
SPI_exec ("
INSERT INTO tab SELECT * FROM tab
", 5);
</ProgramListing>
</ProgramListing>
will allow at most 5 tuples to be inserted into table.
will allow at most 5 tuples to be inserted into table.
...
@@ -2821,19 +2821,19 @@ execq(text *sql, int cnt)
...
@@ -2821,19 +2821,19 @@ execq(text *sql, int cnt)
Now, compile and create the function:
Now, compile and create the function:
<ProgramListing>
<ProgramListing>
create function execq (text, int4) returns int4 as '...path_to_so' language
'c';
CREATE FUNCTION execq (TEXT, INT4) RETURNS INT4 AS '...path_to_so' LANGUAGE
'c';
</ProgramListing>
</ProgramListing>
<ProgramListing>
<ProgramListing>
vac=>
select execq('create table a (x int
4)', 0);
vac=>
SELECT execq('CREATE TABLE a (x INT
4)', 0);
execq
execq
-----
-----
0
0
(1 row)
(1 row)
vac=>
insert into a values (execq('insert into a values
(0)',0));
vac=>
INSERT INTO a VALUES (execq('INSERT INTO a VALUES
(0)',0));
INSERT 167631 1
INSERT 167631 1
vac=> select execq('
select * from
a',0);
vac=> select execq('
SELECT * FROM
a',0);
NOTICE:EXECQ: 0 <<< inserted by execq
NOTICE:EXECQ: 0 <<< inserted by execq
NOTICE:EXECQ: 1 <<< value returned by execq and inserted by upper INSERT
NOTICE:EXECQ: 1 <<< value returned by execq and inserted by upper INSERT
...
@@ -2843,13 +2843,13 @@ execq
...
@@ -2843,13 +2843,13 @@ execq
2
2
(1 row)
(1 row)
vac=>
select execq('insert into a select x + 2 from
a',1);
vac=>
SELECT execq('INSERT INTO a SELECT x + 2 FROM
a',1);
execq
execq
-----
-----
1
1
(1 row)
(1 row)
vac=>
select execq('select * from
a', 10);
vac=>
SELECT execq('SELECT * FROM
a', 10);
NOTICE:EXECQ: 0
NOTICE:EXECQ: 0
NOTICE:EXECQ: 1
NOTICE:EXECQ: 1
...
@@ -2861,20 +2861,20 @@ execq
...
@@ -2861,20 +2861,20 @@ execq
3 <<< 10 is max value only, 3 is real # of tuples
3 <<< 10 is max value only, 3 is real # of tuples
(1 row)
(1 row)
vac=>
delete from
a;
vac=>
DELETE FROM
a;
DELETE 3
DELETE 3
vac=>
insert into a values (execq('select * from
a', 0) + 1);
vac=>
INSERT INTO a VALUES (execq('SELECT * FROM
a', 0) + 1);
INSERT 167712 1
INSERT 167712 1
vac=>
select * from
a;
vac=>
SELECT * FROM
a;
x
x
-
-
1 <<< no tuples in a (0) + 1
1 <<< no tuples in a (0) + 1
(1 row)
(1 row)
vac=>
insert into a values (execq('select * from
a', 0) + 1);
vac=>
INSERT INTO a VALUES (execq('SELECT * FROM
a', 0) + 1);
NOTICE:EXECQ: 0
NOTICE:EXECQ: 0
INSERT 167713 1
INSERT 167713 1
vac=>
select * from
a;
vac=>
SELECT * FROM
a;
x
x
-
-
1
1
...
@@ -2883,14 +2883,14 @@ x
...
@@ -2883,14 +2883,14 @@ x
-- This demonstrates data changes visibility rule:
-- This demonstrates data changes visibility rule:
vac=>
insert into a select execq('select * from a', 0) * x from
a;
vac=>
INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM
a;
NOTICE:EXECQ: 1
NOTICE:EXECQ: 1
NOTICE:EXECQ: 2
NOTICE:EXECQ: 2
NOTICE:EXECQ: 1
NOTICE:EXECQ: 1
NOTICE:EXECQ: 2
NOTICE:EXECQ: 2
NOTICE:EXECQ: 2
NOTICE:EXECQ: 2
INSERT 0 2
INSERT 0 2
vac=>
select * from
a;
vac=>
SELECT * FROM
a;
x
x
-
-
1
1
...
...
doc/src/sgml/syntax.sgml
View file @
705869dd
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.4
8 2001/10/09 18:46:00 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.4
9 2001/10/12 23:32:34 momjian
Exp $
-->
-->
<chapter id="sql-syntax">
<chapter id="sql-syntax">
...
@@ -909,7 +909,7 @@ $<replaceable>number</replaceable>
...
@@ -909,7 +909,7 @@ $<replaceable>number</replaceable>
<programlisting>
<programlisting>
CREATE FUNCTION dept (text) RETURNS dept
CREATE FUNCTION dept (text) RETURNS dept
AS '
select * from dept where
name = $1'
AS '
SELECT * FROM dept WHERE
name = $1'
LANGUAGE 'sql';
LANGUAGE 'sql';
</programlisting>
</programlisting>
...
...
doc/src/sgml/trigger.sgml
View file @
705869dd
...
@@ -486,7 +486,7 @@ trigf(PG_FUNCTION_ARGS)
...
@@ -486,7 +486,7 @@ trigf(PG_FUNCTION_ARGS)
elog(NOTICE, "trigf (fired %s): SPI_connect returned %d", when, ret);
elog(NOTICE, "trigf (fired %s): SPI_connect returned %d", when, ret);
/* Get number of tuples in relation */
/* Get number of tuples in relation */
ret = SPI_exec("
select count(*) from
ttest", 0);
ret = SPI_exec("
SELECT count(*) FROM
ttest", 0);
if (ret < 0)
if (ret < 0)
elog(NOTICE, "trigf (fired %s): SPI_exec returned %d", when, ret);
elog(NOTICE, "trigf (fired %s): SPI_exec returned %d", when, ret);
...
@@ -513,70 +513,70 @@ trigf(PG_FUNCTION_ARGS)
...
@@ -513,70 +513,70 @@ trigf(PG_FUNCTION_ARGS)
Now, compile and create the trigger function:
Now, compile and create the trigger function:
<programlisting>
<programlisting>
create function trigf () returns opaque as
CREATE FUNCTION trigf () RETURNS OPAQUE AS
'...path_to_so'
language
'C';
'...path_to_so'
LANGUAGE
'C';
create table
ttest (x int4);
CREATE TABLE
ttest (x int4);
</programlisting>
</programlisting>
<programlisting>
<programlisting>
vac=>
create trigger tbefore before insert or update or delete on
ttest
vac=>
CREATE TRIGGER tbefore BEFORE INSERT OR UPDATE OR DELETE ON
ttest
for each row execute procedure
trigf();
FOR EACH ROW EXECUTE PROCEDURE
trigf();
CREATE
CREATE
vac=>
create trigger tafter after insert or update or delete on
ttest
vac=>
CREATE TRIGGER tafter AFTER INSERT OR UPDATE OR DELETE ON
ttest
for each row execute procedure
trigf();
FOR EACH ROW EXECUTE PROCEDURE
trigf();
CREATE
CREATE
vac=>
insert into ttest values (null
);
vac=>
INSERT INTO ttest VALUES (NULL
);
NOTICE:trigf (fired before): there are 0 tuples in ttest
NOTICE:trigf (fired before): there are 0 tuples in ttest
INSERT 0 0
INSERT 0 0
-- Insertion skipped and AFTER trigger is not fired
-- Insertion skipped and AFTER trigger is not fired
vac=>
select * from
ttest;
vac=>
SELECT * FROM
ttest;
x
x
-
-
(0 rows)
(0 rows)
vac=>
insert into ttest values
(1);
vac=>
INSERT INTO ttest VALUES
(1);
NOTICE:trigf (fired before): there are 0 tuples in ttest
NOTICE:trigf (fired before): there are 0 tuples in ttest
NOTICE:trigf (fired after ): there are 1 tuples in ttest
NOTICE:trigf (fired after ): there are 1 tuples in ttest
^^^^^^^^
^^^^^^^^
remember what we said about visibility.
remember what we said about visibility.
INSERT 167793 1
INSERT 167793 1
vac=>
select * from
ttest;
vac=>
SELECT * FROM
ttest;
x
x
-
-
1
1
(1 row)
(1 row)
vac=>
insert into ttest select x * 2 from
ttest;
vac=>
INSERT INTO ttest SELECT x * 2 FROM
ttest;
NOTICE:trigf (fired before): there are 1 tuples in ttest
NOTICE:trigf (fired before): there are 1 tuples in ttest
NOTICE:trigf (fired after ): there are 2 tuples in ttest
NOTICE:trigf (fired after ): there are 2 tuples in ttest
^^^^^^^^
^^^^^^^^
remember what we said about visibility.
remember what we said about visibility.
INSERT 167794 1
INSERT 167794 1
vac=>
select * from
ttest;
vac=>
SELECT * FROM
ttest;
x
x
-
-
1
1
2
2
(2 rows)
(2 rows)
vac=>
update ttest set x = null where
x = 2;
vac=>
UPDATE ttest SET x = null WHERE
x = 2;
NOTICE:trigf (fired before): there are 2 tuples in ttest
NOTICE:trigf (fired before): there are 2 tuples in ttest
UPDATE 0
UPDATE 0
vac=>
update ttest set x = 4 where
x = 2;
vac=>
UPDATE ttest SET x = 4 WHERE
x = 2;
NOTICE:trigf (fired before): there are 2 tuples in ttest
NOTICE:trigf (fired before): there are 2 tuples in ttest
NOTICE:trigf (fired after ): there are 2 tuples in ttest
NOTICE:trigf (fired after ): there are 2 tuples in ttest
UPDATE 1
UPDATE 1
vac=>
select * from
ttest;
vac=>
SELECT * FROM
ttest;
x
x
-
-
1
1
4
4
(2 rows)
(2 rows)
vac=>
delete from
ttest;
vac=>
DELETE FROM
ttest;
NOTICE:trigf (fired before): there are 2 tuples in ttest
NOTICE:trigf (fired before): there are 2 tuples in ttest
NOTICE:trigf (fired after ): there are 1 tuples in ttest
NOTICE:trigf (fired after ): there are 1 tuples in ttest
NOTICE:trigf (fired before): there are 1 tuples in ttest
NOTICE:trigf (fired before): there are 1 tuples in ttest
...
@@ -584,7 +584,7 @@ NOTICE:trigf (fired after ): there are 0 tuples in ttest
...
@@ -584,7 +584,7 @@ NOTICE:trigf (fired after ): there are 0 tuples in ttest
^^^^^^^^
^^^^^^^^
remember what we said about visibility.
remember what we said about visibility.
DELETE 2
DELETE 2
vac=>
select * from
ttest;
vac=>
SELECT * FROM
ttest;
x
x
-
-
(0 rows)
(0 rows)
...
...
doc/src/sgml/typeconv.sgml
View file @
705869dd
...
@@ -281,19 +281,18 @@ If only one candidate remains, use it; else continue to the next step.
...
@@ -281,19 +281,18 @@ If only one candidate remains, use it; else continue to the next step.
</step>
</step>
<step performance="required">
<step performance="required">
<para>
<para>
If any input arguments are <quote>unknown</quote>, check the type categories accepted
If any input arguments are <quote>unknown</quote>, check the type
at those argument positions by the remaining candidates. At each position,
categories accepted at those argument positions by the remaining
select "string"
candidates. At each position, try the "string" category if any
category if any candidate accepts that category (this bias towards string
candidate accepts that category (this bias towards string is appropriate
is appropriate since an unknown-type literal does look like a string).
since an unknown-type literal does look like a string). Otherwise, if
Otherwise, if all the remaining candidates accept the same type category,
all the remaining candidates accept the same type category, select that
select that category; otherwise fail because
category; otherwise fail because the correct choice cannot be deduced
the correct choice cannot be deduced without more clues. Also note whether
without more clues. Also note whether any of the candidates accept a
any of the candidates accept a preferred data type within the selected category.
preferred data type within the selected category. Now discard operator
Now discard operator candidates that do not accept the selected type category;
candidates that do not accept the selected type category; furthermore,
furthermore, if any candidate accepts a preferred type at a given argument
if any candidate accepts a preferred type at a given argument position,
position, discard candidates that accept non-preferred types for that
discard candidates that accept non-preferred types for that argument.
argument.
</para>
</para>
</step>
</step>
<step performance="required">
<step performance="required">
...
@@ -319,7 +318,7 @@ operator defined in the catalog, and it takes arguments of type
...
@@ -319,7 +318,7 @@ operator defined in the catalog, and it takes arguments of type
The scanner assigns an initial type of <type>integer</type> to both arguments
The scanner assigns an initial type of <type>integer</type> to both arguments
of this query expression:
of this query expression:
<screen>
<screen>
tgl=>
select
2 ^ 3 AS "Exp";
tgl=>
SELECT
2 ^ 3 AS "Exp";
Exp
Exp
-----
-----
8
8
...
@@ -330,7 +329,7 @@ So the parser does a type conversion on both operands and the query
...
@@ -330,7 +329,7 @@ So the parser does a type conversion on both operands and the query
is equivalent to
is equivalent to
<screen>
<screen>
tgl=>
select
CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp";
tgl=>
SELECT
CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp";
Exp
Exp
-----
-----
8
8
...
@@ -340,7 +339,7 @@ tgl=> select CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp";
...
@@ -340,7 +339,7 @@ tgl=> select CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp";
or
or
<screen>
<screen>
tgl=>
select
2.0 ^ 3.0 AS "Exp";
tgl=>
SELECT
2.0 ^ 3.0 AS "Exp";
Exp
Exp
-----
-----
8
8
...
@@ -417,7 +416,7 @@ will try to convert that argument to an integer for evaluation of the
...
@@ -417,7 +416,7 @@ will try to convert that argument to an integer for evaluation of the
factorial.
factorial.
<screen>
<screen>
tgl=>
select
(4.3 !);
tgl=>
SELECT
(4.3 !);
?column?
?column?
----------
----------
24
24
...
@@ -508,8 +507,7 @@ If only one candidate remains, use it; else continue to the next step.
...
@@ -508,8 +507,7 @@ If only one candidate remains, use it; else continue to the next step.
<para>
<para>
If any input arguments are <type>unknown</type>, check the type categories accepted
If any input arguments are <type>unknown</type>, check the type categories accepted
at those argument positions by the remaining candidates. At each position,
at those argument positions by the remaining candidates. At each position,
select <type>string</type>
try the <type>string</type> category if any candidate accepts that category (this bias towards string
category if any candidate accepts that category (this bias towards string
is appropriate since an unknown-type literal does look like a string).
is appropriate since an unknown-type literal does look like a string).
Otherwise, if all the remaining candidates accept the same type category,
Otherwise, if all the remaining candidates accept the same type category,
select that category; otherwise fail because
select that category; otherwise fail because
...
@@ -543,7 +541,7 @@ So the following query automatically converts the <type>int2</type> argument
...
@@ -543,7 +541,7 @@ So the following query automatically converts the <type>int2</type> argument
to <type>int4</type>:
to <type>int4</type>:
<screen>
<screen>
tgl=>
select
int4fac(int2 '4');
tgl=>
SELECT
int4fac(int2 '4');
int4fac
int4fac
---------
---------
24
24
...
@@ -552,7 +550,7 @@ tgl=> select int4fac(int2 '4');
...
@@ -552,7 +550,7 @@ tgl=> select int4fac(int2 '4');
and is actually transformed by the parser to
and is actually transformed by the parser to
<screen>
<screen>
tgl=>
select
int4fac(int4(int2 '4'));
tgl=>
SELECT
int4fac(int4(int2 '4'));
int4fac
int4fac
---------
---------
24
24
...
@@ -573,7 +571,7 @@ only one takes two arguments, of types <type>text</type> and <type>int4</type>.
...
@@ -573,7 +571,7 @@ only one takes two arguments, of types <type>text</type> and <type>int4</type>.
If called with a string constant of unspecified type, the type is matched up
If called with a string constant of unspecified type, the type is matched up
directly with the only candidate function type:
directly with the only candidate function type:
<screen>
<screen>
tgl=>
select
substr('1234', 3);
tgl=>
SELECT
substr('1234', 3);
substr
substr
--------
--------
34
34
...
@@ -585,7 +583,7 @@ tgl=> select substr('1234', 3);
...
@@ -585,7 +583,7 @@ tgl=> select substr('1234', 3);
If the string is declared to be of type <type>varchar</type>, as might be the case
If the string is declared to be of type <type>varchar</type>, as might be the case
if it comes from a table, then the parser will try to coerce it to become <type>text</type>:
if it comes from a table, then the parser will try to coerce it to become <type>text</type>:
<screen>
<screen>
tgl=>
select
substr(varchar '1234', 3);
tgl=>
SELECT
substr(varchar '1234', 3);
substr
substr
--------
--------
34
34
...
@@ -593,7 +591,7 @@ tgl=> select substr(varchar '1234', 3);
...
@@ -593,7 +591,7 @@ tgl=> select substr(varchar '1234', 3);
</screen>
</screen>
which is transformed by the parser to become
which is transformed by the parser to become
<screen>
<screen>
tgl=>
select
substr(text(varchar '1234'), 3);
tgl=>
SELECT
substr(text(varchar '1234'), 3);
substr
substr
--------
--------
34
34
...
@@ -615,7 +613,7 @@ explicit type conversion call is really inserted in this case.
...
@@ -615,7 +613,7 @@ explicit type conversion call is really inserted in this case.
And, if the function is called with an <type>int4</type>, the parser will
And, if the function is called with an <type>int4</type>, the parser will
try to convert that to <type>text</type>:
try to convert that to <type>text</type>:
<screen>
<screen>
tgl=>
select
substr(1234, 3);
tgl=>
SELECT
substr(1234, 3);
substr
substr
--------
--------
34
34
...
@@ -623,7 +621,7 @@ tgl=> select substr(1234, 3);
...
@@ -623,7 +621,7 @@ tgl=> select substr(1234, 3);
</screen>
</screen>
actually executes as
actually executes as
<screen>
<screen>
tgl=>
select
substr(text(1234), 3);
tgl=>
SELECT
substr(text(1234), 3);
substr
substr
--------
--------
34
34
...
...
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