Commit a6554df4 authored by Peter Eisentraut's avatar Peter Eisentraut

In an effort to reduce the total number of chapters, combine the small

chapters on extending types, operators, and aggregates into the extending
functions chapter.  Move the information on how to call table functions
into the queries chapter.  Remove some outdated information that is
already present in a better form in other parts of the documentation.
parent 730840c9
......@@ -2,7 +2,7 @@
#
# PostgreSQL documentation makefile
#
# $Header: /cvsroot/pgsql/doc/src/sgml/Makefile,v 1.56 2003/03/25 16:15:35 petere Exp $
# $Header: /cvsroot/pgsql/doc/src/sgml/Makefile,v 1.57 2003/04/10 01:22:44 petere Exp $
#
#----------------------------------------------------------------------------
......@@ -77,7 +77,7 @@ all: html
.PHONY: html
html: postgres.sgml $(ALLSGML) stylesheet.dsl catalogs.gif connections.gif
html: postgres.sgml $(ALLSGML) stylesheet.dsl
@rm -f *.html
$(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -i output-html -t sgml $<
......@@ -114,8 +114,6 @@ features-unsupported.sgml: $(top_srcdir)/src/backend/catalog/sql_feature_package
%.rtf: %.sgml $(ALLSGML) stylesheet.dsl
$(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t rtf -V rtf-backend -i output-print $<
postgres.rtf: catalogs.gif connections.gif
# TeX
# Regular TeX and pdfTeX have slightly differing requirements, so we
# need to distinguish the path we're taking.
......@@ -123,13 +121,9 @@ postgres.rtf: catalogs.gif connections.gif
%.tex-ps: %.sgml $(ALLSGML) stylesheet.dsl
$(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t tex -V tex-backend -i output-print -V texdvi-output -o $@ $<
postgres.tex-ps: catalogs.eps connections.eps
%.tex-pdf: %.sgml $(ALLSGML) stylesheet.dsl
$(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t tex -V tex-backend -i output-print -V texpdf-output -o $@ $<
postgres.tex-pdf: catalogs.pdf connections.pdf
%.dvi: %.tex-ps
@rm -f $*.aux $*.log
jadetex $<
......
<Chapter Id="arch-pg">
<TITLE>Architecture</TITLE>
<Sect1 id="arch-pg-concepts">
<Title><ProductName>PostgreSQL</ProductName> Architectural Concepts</Title>
<Para>
Before we begin, you should understand the basic
<ProductName>PostgreSQL</ProductName> system architecture. Understanding how the
parts of <ProductName>PostgreSQL</ProductName> interact will make the next chapter
somewhat clearer.
In database jargon, <ProductName>PostgreSQL</ProductName> uses a simple "process
per-user" client/server model. A <ProductName>PostgreSQL</ProductName> session
consists of the following cooperating Unix processes (programs):
<ItemizedList>
<ListItem>
<Para>
A supervisory daemon process (the <Application>postmaster</Application>),
</Para>
</ListItem>
<ListItem>
<Para>
the user's frontend application (e.g., the <Application>psql</Application> program), and
</Para>
</ListItem>
<ListItem>
<Para>
one or more backend database servers (the <Application>postgres</Application> process itself).
</Para>
</ListItem>
</ItemizedList>
</para>
<Para>
A single <Application>postmaster</Application> manages a given collection of
databases on a single host. Such a collection of
databases is called a cluster (of databases). A frontend
application that wishes to access a given database
within a cluster makes calls to an interface library (e.g., <application>libpq</>)
that is linked into the application.
The library sends user requests over the network to the
<Application>postmaster</Application>
(<XRef LinkEnd="PGARCH-CONNECTIONS">(a)),
which in turn starts a new backend server process
(<XRef LinkEnd="PGARCH-CONNECTIONS">(b))
<figure id="PGARCH-CONNECTIONS">
<title>How a connection is established</title>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="connections">
</imageobject>
</mediaobject>
</figure>
and connects the frontend process to the new server
(<XRef LinkEnd="PGARCH-CONNECTIONS">(c)).
From that point on, the frontend process and the backend
server communicate without intervention by the
<Application>postmaster</Application>. Hence, the <Application>postmaster</Application> is always running, waiting
for connection requests, whereas frontend and backend processes
come and go. The <FileName>libpq</FileName> library allows a single
frontend to make multiple connections to backend processes.
However, each backend process is a single-threaded process that can
only execute one query at a time; so the communication over any one
frontend-to-backend connection is single-threaded.
</Para>
<Para>
One implication of this architecture is that the
<Application>postmaster</Application> and the backend always run on the
same machine (the database server), while the frontend
application may run anywhere. You should keep this
in mind,
because the files that can be accessed on a client
machine may not be accessible (or may only be accessed
using a different path name) on the database server
machine.
</Para>
<Para>
You should also be aware that the <Application>postmaster</Application> and
<application>postgres</> servers run with the user ID of the <ProductName>PostgreSQL</ProductName>
<quote>superuser</>.
Note that the <ProductName>PostgreSQL</ProductName> superuser does not
have to be any particular user (e.g., a user named
<literal>postgres</literal>), although many systems are installed that way.
Furthermore, the <ProductName>PostgreSQL</ProductName> superuser should
definitely not be the Unix superuser, <literal>root</literal>!
It is safest if the <ProductName>PostgreSQL</ProductName> superuser is an
ordinary, unprivileged user so far as the surrounding Unix system is
concerned.
In any case, all files relating to a database should belong to
this <ProductName>Postgres</ProductName> superuser.
</Para>
</sect1>
</Chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode:sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-tabs-mode:nil
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:("/usr/share/sgml/catalog")
sgml-local-ecat-files:nil
End:
-->
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.24 2003/03/25 16:15:35 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.25 2003/04/10 01:22:44 petere Exp $
-->
<sect2 id="dfunc">
......@@ -14,7 +14,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.24 2003/03/25 16:15:35 peter
</para>
<para>
For more information you should read the documentation of your
For information beyond what is contained in this section
you should read the documentation of your
operating system, in particular the manual pages for the C compiler,
<command>cc</command>, and the link editor, <command>ld</command>.
In addition, the <productname>PostgreSQL</productname> source code
......@@ -47,13 +48,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.24 2003/03/25 16:15:35 peter
here.
</para>
<para>
<!--
Note: Reading GNU Libtool sources is generally a good way of figuring out
this information. The methods used within
<productname>PostgreSQL</> source code are not
necessarily ideal.
Note: Reading GNU Libtool sources is generally a good way of
figuring out this information. The methods used within PostgreSQL
source code are not necessarily ideal.
-->
<variablelist>
......@@ -160,7 +158,7 @@ cc -shared -o foo.so foo.o
<indexterm><primary>MacOS X</></>
<listitem>
<para>
Here is a sample. It assumes the developer tools are installed.
Here is an example. It assumes the developer tools are installed.
<programlisting>
cc -c foo.c
cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o
......@@ -271,17 +269,13 @@ gcc -shared -o foo.so foo.o
</varlistentry>
</variablelist>
</para>
<tip>
<para>
If you want to package your extension modules for wide distribution
you should consider using <ulink
url="http://www.gnu.org/software/libtool/"><productname>GNU
Libtool</productname></ulink> for building shared libraries. It
encapsulates the platform differences into a general and powerful
interface. Serious packaging also requires considerations about
library versioning, symbol resolution methods, and other issues.
If this is too complicated for you, you should consider using
<ulink url="http://www.gnu.org/software/libtool/"><productname>GNU
Libtool</productname></ulink>, which hides the platform differences
behind a uniform interface.
</para>
</tip>
......
This diff is collapsed.
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.27 2003/03/25 16:15:36 petere Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.28 2003/04/10 01:22:44 petere Exp $ -->
<!entity history SYSTEM "history.sgml">
<!entity info SYSTEM "info.sgml">
......@@ -57,7 +57,6 @@
<!entity wal SYSTEM "wal.sgml">
<!-- programmer's guide -->
<!entity arch-pg SYSTEM "arch-pg.sgml">
<!entity dfunc SYSTEM "dfunc.sgml">
<!entity ecpg SYSTEM "ecpg.sgml">
<!entity extend SYSTEM "extend.sgml">
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.49 2003/03/25 16:15:38 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.50 2003/04/10 01:22:44 petere Exp $
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
......@@ -210,15 +210,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.49 2003/03/25 16:15:38 pe
</para>
</partintro>
&arch-pg;
&extend;
&xfunc;
&xtypes;
&xoper;
&xaggr;
&rules;
&xindex;
&indexcost;
&rules;
&trigger;
&spi;
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.20 2003/03/13 01:30:29 petere Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.21 2003/04/10 01:22:44 petere Exp $ -->
<chapter id="queries">
<title>Queries</title>
......@@ -550,6 +550,78 @@ FROM (SELECT * FROM table1) AS alias_name
grouping or aggregation.
</para>
</sect3>
<sect3 id="queries-tablefunctions">
<title>Table Functions</title>
<indexterm zone="queries-tablefunctions"><primary>table function</></>
<para>
Table functions are functions that produce a set of rows, made up
of either base data types (scalar types) or composite data types
(table rows). They are used like a table, view, or subquery in
the <literal>FROM</> clause of a query. Columns returned by table
functions may be included in <literal>SELECT</>,
<literal>JOIN</>, or <literal>WHERE</> clauses in the same manner
as a table, view, or subquery column.
</para>
<para>
If a table function returns a base data type, the single result
column is named like the function. If the function returns a
composite type, the result columns get the same names as the
individual attributes of the type.
</para>
<para>
A table function may be aliased in the <literal>FROM</> clause,
but it also may be left unaliased. If a function is used in the
<literal>FROM</> clause with no alias, the function name is used
as the resulting table name.
</para>
<para>
Some examples:
<programlisting>
CREATE TABLE foo (fooid int, foosubid int, fooname text);
CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS '
SELECT * FROM foo WHERE fooid = $1;
' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
SELECT * FROM foo
WHERE foosubid IN (select foosubid from getfoo(foo.fooid) z
where z.fooid = foo.fooid);
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
</programlisting>
</para>
<para>
In some cases it is useful to define table functions that can
return different column sets depending on how they are invoked.
To support this, the table function can be declared as returning
the pseudotype <type>record</>. When such a function is used in
a query, the expected row structure must be specified in the
query itself, so that the system can know how to parse and plan
the query. Consider this example:
<programlisting>
SELECT *
FROM dblink('dbname=mydb', 'select proname, prosrc from pg_proc')
AS t1(proname name, prosrc text)
WHERE proname LIKE 'bytea%';
</programlisting>
The <literal>dblink</> function executes a remote query (see
<filename>contrib/dblink</>). It is declared to return
<type>record</> since it might be used for any kind of query.
The actual column set must be specified in the calling query so
that the parser knows, for example, what <literal>*</> should
expand to.
</para>
</sect3>
</sect2>
<sect2 id="queries-where">
......@@ -951,7 +1023,7 @@ SELECT DISTINCT ON (<replaceable>expression</replaceable> <optional>, <replaceab
The <literal>DISTINCT ON</> clause is not part of the SQL standard
and is sometimes considered bad style because of the potentially
indeterminate nature of its results. With judicious use of
<literal>GROUP BY</> and subselects in <literal>FROM</> the
<literal>GROUP BY</> and subqueries in <literal>FROM</> the
construct can be avoided, but it is often the most convenient
alternative.
</para>
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.19 2003/03/25 16:15:38 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.20 2003/04/10 01:22:44 petere Exp $
-->
<chapter id="xaggr">
<title>Extending <acronym>SQL</acronym>: Aggregates</title>
<sect1 id="xaggr">
<title>User-Defined Aggregates</title>
<indexterm zone="xaggr">
<primary>aggregate functions</primary>
......@@ -22,38 +22,36 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.19 2003/03/25 16:15:38 peter
function. The state transition function is just an
ordinary function that could also be used outside the
context of the aggregate. A <firstterm>final function</firstterm>
can also be specified, in case the desired output of the aggregate
can also be specified, in case the desired result of the aggregate
is different from the data that needs to be kept in the running
state value.
</para>
<para>
Thus, in addition to the input and result data types seen by a user
Thus, in addition to the argument and result data types seen by a user
of the aggregate, there is an internal state-value data type that
may be different from both the input and result types.
may be different from both the argument and result types.
</para>
<para>
If we define an aggregate that does not use a final function,
we have an aggregate that computes a running function of
the column values from each row. <function>Sum</> is an
example of this kind of aggregate. <function>Sum</> starts at
the column values from each row. <function>sum</> is an
example of this kind of aggregate. <function>sum</> starts at
zero and always adds the current row's value to
its running total. For example, if we want to make a <function>sum</>
aggregate to work on a data type for complex numbers,
we only need the addition function for that data type.
The aggregate definition is:
The aggregate definition would be:
<programlisting>
<screen>
CREATE AGGREGATE complex_sum (
sfunc = complex_add,
basetype = complex,
stype = complex,
initcond = '(0,0)'
);
</programlisting>
<screen>
SELECT complex_sum(a) FROM test_complex;
complex_sum
......@@ -61,43 +59,43 @@ SELECT complex_sum(a) FROM test_complex;
(34,53.9)
</screen>
(In practice, we'd just name the aggregate <function>sum</function>, and rely on
(In practice, we'd just name the aggregate <function>sum</function> and rely on
<productname>PostgreSQL</productname> to figure out which kind
of sum to apply to a column of type <type>complex</type>.)
</para>
<para>
The above definition of <function>sum</function> will return zero (the initial
state condition) if there are no non-null input values.
Perhaps we want to return NULL in that case instead --- the SQL standard
state condition) if there are no nonnull input values.
Perhaps we want to return null in that case instead --- the SQL standard
expects <function>sum</function> to behave that way. We can do this simply by
omitting the <literal>initcond</literal> phrase, so that the initial state
condition is NULL. Ordinarily this would mean that the <literal>sfunc</literal>
would need to check for a NULL state-condition input, but for
condition is null. Ordinarily this would mean that the <literal>sfunc</literal>
would need to check for a null state-condition input, but for
<function>sum</function> and some other simple aggregates like <function>max</> and <function>min</>,
it's sufficient to insert the first non-null input value into
it would be sufficient to insert the first nonnull input value into
the state variable and then start applying the transition function
at the second non-null input value. <productname>PostgreSQL</productname>
will do that automatically if the initial condition is NULL and
at the second nonnull input value. <productname>PostgreSQL</productname>
will do that automatically if the initial condition is null and
the transition function is marked <quote>strict</> (i.e., not to be called
for NULL inputs).
for null inputs).
</para>
<para>
Another bit of default behavior for a <quote>strict</> transition function
is that the previous state value is retained unchanged whenever a
NULL input value is encountered. Thus, null values are ignored. If you
need some other behavior for NULL inputs, just define your transition
function as non-strict, and code it to test for NULL inputs and do
null input value is encountered. Thus, null values are ignored. If you
need some other behavior for null inputs, just do not define your transition
function as strict, and code it to test for null inputs and do
whatever is needed.
</para>
<para>
<function>Avg</> (average) is a more complex example of an aggregate. It requires
<function>avg</> (average) is a more complex example of an aggregate. It requires
two pieces of running state: the sum of the inputs and the count
of the number of inputs. The final result is obtained by dividing
these quantities. Average is typically implemented by using a
two-element array as the transition state value. For example,
two-element array as the state value. For example,
the built-in implementation of <function>avg(float8)</function>
looks like:
......@@ -116,7 +114,7 @@ CREATE AGGREGATE avg (
For further details see the description of the <command>CREATE
AGGREGATE</command> command in <xref linkend="reference">.
</para>
</chapter>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
......
This diff is collapsed.
This diff is collapsed.
<chapter id="xtypes">
<title>Extending <acronym>SQL</acronym>: Types</title>
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v 1.17 2003/04/10 01:22:45 petere Exp $
-->
<sect1 id="xtypes">
<title>User-Defined Types</title>
<indexterm zone="xtypes">
<primary>data types</primary>
......@@ -7,22 +11,20 @@
</indexterm>
<comment>
This chapter needs to be updated for the version-1 function manager
This section needs to be updated for the version-1 function manager
interface.
</comment>
<para>
As previously mentioned, there are two kinds of types in
<productname>PostgreSQL</productname>: base types (defined in a
programming language) and composite types. This chapter describes
how to define new base types.
As described above, there are two kinds of data types in
<productname>PostgreSQL</productname>: base types and composite
types. This section describes how to define new base types.
</para>
<para>
The examples in this section can be found in
<filename>complex.sql</filename> and <filename>complex.c</filename>
in the tutorial directory. Composite examples are in
<filename>funcs.sql</filename>.
in the tutorial directory.
</para>
<para>
......@@ -36,15 +38,15 @@
These functions determine how the type appears in strings (for input
by the user and output to the user) and how the type is organized in
memory. The input function takes a null-terminated character string
as its input and returns the internal (in memory) representation of
as its argument and returns the internal (in memory) representation of
the type. The output function takes the internal representation of
the type and returns a null-terminated character string.
the type as argument and returns a null-terminated character string.
</para>
<para>
Suppose we want to define a complex type which represents complex
numbers. Naturally, we would choose to represent a complex in memory
as the following <acronym>C</acronym> structure:
Suppose we want to define a type <type>complex</> that represents
complex numbers. A natural way to to represent a complex number in
memory would be the following C structure:
<programlisting>
typedef struct Complex {
......@@ -53,24 +55,16 @@ typedef struct Complex {
} Complex;
</programlisting>
and a string of the form <literal>(x,y)</literal> as the external string
representation.
As the external string representation of the type, we choose a
string of the form <literal>(x,y)</literal>.
</para>
<para>
The functions are usually not hard to write, especially the output
function. However, there are a number of points to remember:
<itemizedlist>
<listitem>
<para>
When defining your external (string) representation, remember
that you must eventually write a complete and robust parser for
that representation as your input function!
</para>
<para>
For instance:
The input and output functions are usually not hard to write,
especially the output function. But when defining the external
string representation of the type, remember that you must eventually
write a complete and robust parser for that representation as your
input function. For instance:
<programlisting>
Complex *
......@@ -78,48 +72,42 @@ complex_in(char *str)
{
double x, y;
Complex *result;
if (sscanf(str, " ( %lf , %lf )", &amp;x, &amp;y) != 2) {
if (sscanf(str, " ( %lf , %lf )", &amp;x, &amp;y) != 2)
{
elog(ERROR, "complex_in: error in parsing %s", str);
return NULL;
}
result = (Complex *)palloc(sizeof(Complex));
result = (Complex *) palloc(sizeof(Complex));
result-&gt;x = x;
result-&gt;y = y;
return (result);
return result;
}
</programlisting>
</para>
<para>
The output function can simply be:
The output function can simply be:
<programlisting>
char *
complex_out(Complex *complex)
{
char *result;
if (complex == NULL)
return(NULL);
result = (char *) palloc(60);
sprintf(result, "(%g,%g)", complex-&gt;x, complex-&gt;y);
return(result);
return result;
}
</programlisting>
</para>
</para>
</listitem>
<listitem>
<para>
You should try to make the input and output functions inverses of
each other. If you do not, you will have severe problems when
you need to dump your data into a file and then read it back in
(say, into someone else's database on another computer). This is
a particularly common problem when floating-point numbers are
involved.
</para>
</listitem>
</itemizedlist>
<para>
You should try to make the input and output functions inverses of
each other. If you do not, you will have severe problems when you
need to dump your data into a file and then read it back in. This
is a particularly common problem when floating-point numbers are
involved.
</para>
<para>
......@@ -130,14 +118,18 @@ complex_out(Complex *complex)
<programlisting>
CREATE FUNCTION complex_in(cstring)
RETURNS complex
AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
AS '<replaceable>filename</replaceable>'
LANGUAGE C;
CREATE FUNCTION complex_out(complex)
RETURNS cstring
AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
AS '<replaceable>filename</replaceable>'
LANGUAGE C;
</programlisting>
Notice that the declarations of the input and output functions must
reference the not-yet-defined type. This is allowed, but will draw
warning messages that may be ignored.
</para>
<para>
......@@ -149,49 +141,36 @@ CREATE TYPE complex (
output = complex_out
);
</programlisting>
Notice that the declarations of the input and output functions must
reference the not-yet-defined type. This is allowed, but will draw
warning messages that may be ignored.
</para>
<para>
<indexterm>
<primary>arrays</primary>
</indexterm>
As discussed earlier, <productname>PostgreSQL</productname> fully
supports arrays of base types. Additionally,
<productname>PostgreSQL</productname> supports arrays of
user-defined types as well. When you define a type,
When you define a new base type,
<productname>PostgreSQL</productname> automatically provides support
for arrays of that type. For historical reasons, the array type has
the same name as the user-defined type with the underscore character
<literal>_</> prepended.
for arrays of that
type.<indexterm><primary>array</primary><secondary>of user-defined
type</secondary></indexterm> For historical reasons, the array type
has the same name as the base type with the underscore character
(<literal>_</>) prepended.
</para>
<para>
Composite types do not need any function defined on them, since the
system already understands what they look like inside.
If the values of your data type might exceed a few hundred bytes in
size (in internal form), you should mark them
TOAST-able.<indexterm><primary>TOAST</primary><secondary>and
user-defined types</secondary></indexterm> To do this, the internal
representation must follow the standard layout for variable-length
data: the first four bytes must be an <type>int32</type> containing
the total length in bytes of the datum (including itself). Also,
when running the <command>CREATE TYPE</command> command, specify the
internal length as <literal>variable</> and select the appropriate
storage option.
</para>
<para>
<indexterm>
<primary>TOAST</primary>
<secondary>and user-defined types</secondary>
</indexterm>
If the values of your data type might exceed a few hundred bytes in
size (in internal form), you should be careful to mark them
TOAST-able. To do this, the internal representation must follow the
standard layout for variable-length data: the first four bytes must
be an <type>int32</type> containing the total length in bytes of the
datum (including itself). Then, all your functions that accept
values of the type must be careful to call
<function>pg_detoast_datum()</function> on the supplied values ---
after checking that the value is not NULL, if your function is not
strict. Finally, select the appropriate storage option when giving
the <command>CREATE TYPE</command> command.
For further details see the description of the <command>CREATE
TYPE</command> command in <xref linkend="reference">.
</para>
</chapter>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment