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 @@ ...@@ -2,7 +2,7 @@
# #
# PostgreSQL documentation makefile # 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 ...@@ -77,7 +77,7 @@ all: html
.PHONY: html .PHONY: html
html: postgres.sgml $(ALLSGML) stylesheet.dsl catalogs.gif connections.gif html: postgres.sgml $(ALLSGML) stylesheet.dsl
@rm -f *.html @rm -f *.html
$(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -i output-html -t sgml $< $(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 ...@@ -114,8 +114,6 @@ features-unsupported.sgml: $(top_srcdir)/src/backend/catalog/sql_feature_package
%.rtf: %.sgml $(ALLSGML) stylesheet.dsl %.rtf: %.sgml $(ALLSGML) stylesheet.dsl
$(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t rtf -V rtf-backend -i output-print $< $(JADE) $(JADEFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t rtf -V rtf-backend -i output-print $<
postgres.rtf: catalogs.gif connections.gif
# TeX # TeX
# Regular TeX and pdfTeX have slightly differing requirements, so we # Regular TeX and pdfTeX have slightly differing requirements, so we
# need to distinguish the path we're taking. # need to distinguish the path we're taking.
...@@ -123,13 +121,9 @@ postgres.rtf: catalogs.gif connections.gif ...@@ -123,13 +121,9 @@ postgres.rtf: catalogs.gif connections.gif
%.tex-ps: %.sgml $(ALLSGML) stylesheet.dsl %.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 $@ $< $(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 %.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 $@ $< $(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 %.dvi: %.tex-ps
@rm -f $*.aux $*.log @rm -f $*.aux $*.log
jadetex $< 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"> <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 ...@@ -14,7 +14,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.24 2003/03/25 16:15:35 peter
</para> </para>
<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, operating system, in particular the manual pages for the C compiler,
<command>cc</command>, and the link editor, <command>ld</command>. <command>cc</command>, and the link editor, <command>ld</command>.
In addition, the <productname>PostgreSQL</productname> source code 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 ...@@ -47,13 +48,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.24 2003/03/25 16:15:35 peter
here. here.
</para> </para>
<para>
<!-- <!--
Note: Reading GNU Libtool sources is generally a good way of figuring out Note: Reading GNU Libtool sources is generally a good way of
this information. The methods used within figuring out this information. The methods used within PostgreSQL
<productname>PostgreSQL</> source code are not source code are not necessarily ideal.
necessarily ideal.
--> -->
<variablelist> <variablelist>
...@@ -160,7 +158,7 @@ cc -shared -o foo.so foo.o ...@@ -160,7 +158,7 @@ cc -shared -o foo.so foo.o
<indexterm><primary>MacOS X</></> <indexterm><primary>MacOS X</></>
<listitem> <listitem>
<para> <para>
Here is a sample. It assumes the developer tools are installed. Here is an example. It assumes the developer tools are installed.
<programlisting> <programlisting>
cc -c foo.c cc -c foo.c
cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o
...@@ -271,17 +269,13 @@ gcc -shared -o foo.so foo.o ...@@ -271,17 +269,13 @@ gcc -shared -o foo.so foo.o
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</para>
<tip> <tip>
<para> <para>
If you want to package your extension modules for wide distribution If this is too complicated for you, you should consider using
you should consider using <ulink <ulink url="http://www.gnu.org/software/libtool/"><productname>GNU
url="http://www.gnu.org/software/libtool/"><productname>GNU Libtool</productname></ulink>, which hides the platform differences
Libtool</productname></ulink> for building shared libraries. It behind a uniform interface.
encapsulates the platform differences into a general and powerful
interface. Serious packaging also requires considerations about
library versioning, symbol resolution methods, and other issues.
</para> </para>
</tip> </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 history SYSTEM "history.sgml">
<!entity info SYSTEM "info.sgml"> <!entity info SYSTEM "info.sgml">
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
<!entity wal SYSTEM "wal.sgml"> <!entity wal SYSTEM "wal.sgml">
<!-- programmer's guide --> <!-- programmer's guide -->
<!entity arch-pg SYSTEM "arch-pg.sgml">
<!entity dfunc SYSTEM "dfunc.sgml"> <!entity dfunc SYSTEM "dfunc.sgml">
<!entity ecpg SYSTEM "ecpg.sgml"> <!entity ecpg SYSTEM "ecpg.sgml">
<!entity extend SYSTEM "extend.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" [ <!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 ...@@ -210,15 +210,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.49 2003/03/25 16:15:38 pe
</para> </para>
</partintro> </partintro>
&arch-pg;
&extend; &extend;
&xfunc;
&xtypes;
&xoper;
&xaggr;
&rules;
&xindex; &xindex;
&indexcost; &indexcost;
&rules;
&trigger; &trigger;
&spi; &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"> <chapter id="queries">
<title>Queries</title> <title>Queries</title>
...@@ -550,6 +550,78 @@ FROM (SELECT * FROM table1) AS alias_name ...@@ -550,6 +550,78 @@ FROM (SELECT * FROM table1) AS alias_name
grouping or aggregation. grouping or aggregation.
</para> </para>
</sect3> </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>
<sect2 id="queries-where"> <sect2 id="queries-where">
...@@ -951,7 +1023,7 @@ SELECT DISTINCT ON (<replaceable>expression</replaceable> <optional>, <replaceab ...@@ -951,7 +1023,7 @@ SELECT DISTINCT ON (<replaceable>expression</replaceable> <optional>, <replaceab
The <literal>DISTINCT ON</> clause is not part of the SQL standard The <literal>DISTINCT ON</> clause is not part of the SQL standard
and is sometimes considered bad style because of the potentially and is sometimes considered bad style because of the potentially
indeterminate nature of its results. With judicious use of 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 construct can be avoided, but it is often the most convenient
alternative. alternative.
</para> </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"> <sect1 id="xaggr">
<title>Extending <acronym>SQL</acronym>: Aggregates</title> <title>User-Defined Aggregates</title>
<indexterm zone="xaggr"> <indexterm zone="xaggr">
<primary>aggregate functions</primary> <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 ...@@ -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 function. The state transition function is just an
ordinary function that could also be used outside the ordinary function that could also be used outside the
context of the aggregate. A <firstterm>final function</firstterm> 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 is different from the data that needs to be kept in the running
state value. state value.
</para> </para>
<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 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>
<para> <para>
If we define an aggregate that does not use a final function, If we define an aggregate that does not use a final function,
we have an aggregate that computes a running function of we have an aggregate that computes a running function of
the column values from each row. <function>Sum</> is an the column values from each row. <function>sum</> is an
example of this kind of aggregate. <function>Sum</> starts at example of this kind of aggregate. <function>sum</> starts at
zero and always adds the current row's value to zero and always adds the current row's value to
its running total. For example, if we want to make a <function>sum</> its running total. For example, if we want to make a <function>sum</>
aggregate to work on a data type for complex numbers, aggregate to work on a data type for complex numbers,
we only need the addition function for that data type. 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 ( CREATE AGGREGATE complex_sum (
sfunc = complex_add, sfunc = complex_add,
basetype = complex, basetype = complex,
stype = complex, stype = complex,
initcond = '(0,0)' initcond = '(0,0)'
); );
</programlisting>
<screen>
SELECT complex_sum(a) FROM test_complex; SELECT complex_sum(a) FROM test_complex;
complex_sum complex_sum
...@@ -61,43 +59,43 @@ SELECT complex_sum(a) FROM test_complex; ...@@ -61,43 +59,43 @@ SELECT complex_sum(a) FROM test_complex;
(34,53.9) (34,53.9)
</screen> </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 <productname>PostgreSQL</productname> to figure out which kind
of sum to apply to a column of type <type>complex</type>.) of sum to apply to a column of type <type>complex</type>.)
</para> </para>
<para> <para>
The above definition of <function>sum</function> will return zero (the initial The above definition of <function>sum</function> will return zero (the initial
state condition) if there are no non-null input values. state condition) if there are no nonnull input values.
Perhaps we want to return NULL in that case instead --- the SQL standard 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 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 omitting the <literal>initcond</literal> phrase, so that the initial state
condition is NULL. Ordinarily this would mean that the <literal>sfunc</literal> condition is null. Ordinarily this would mean that the <literal>sfunc</literal>
would need to check for a NULL state-condition input, but for 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</>, <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 the state variable and then start applying the transition function
at the second non-null input value. <productname>PostgreSQL</productname> at the second nonnull input value. <productname>PostgreSQL</productname>
will do that automatically if the initial condition is NULL and will do that automatically if the initial condition is null and
the transition function is marked <quote>strict</> (i.e., not to be called the transition function is marked <quote>strict</> (i.e., not to be called
for NULL inputs). for null inputs).
</para> </para>
<para> <para>
Another bit of default behavior for a <quote>strict</> transition function Another bit of default behavior for a <quote>strict</> transition function
is that the previous state value is retained unchanged whenever a is that the previous state value is retained unchanged whenever a
NULL input value is encountered. Thus, null values are ignored. If you null input value is encountered. Thus, null values are ignored. If you
need some other behavior for NULL inputs, just define your transition need some other behavior for null inputs, just do not define your transition
function as non-strict, and code it to test for NULL inputs and do function as strict, and code it to test for null inputs and do
whatever is needed. whatever is needed.
</para> </para>
<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 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 of the number of inputs. The final result is obtained by dividing
these quantities. Average is typically implemented by using a 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> the built-in implementation of <function>avg(float8)</function>
looks like: looks like:
...@@ -116,7 +114,7 @@ CREATE AGGREGATE avg ( ...@@ -116,7 +114,7 @@ CREATE AGGREGATE avg (
For further details see the description of the <command>CREATE For further details see the description of the <command>CREATE
AGGREGATE</command> command in <xref linkend="reference">. AGGREGATE</command> command in <xref linkend="reference">.
</para> </para>
</chapter> </sect1>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
Local variables: 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"> <indexterm zone="xtypes">
<primary>data types</primary> <primary>data types</primary>
...@@ -7,22 +11,20 @@ ...@@ -7,22 +11,20 @@
</indexterm> </indexterm>
<comment> <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. interface.
</comment> </comment>
<para> <para>
As previously mentioned, there are two kinds of types in As described above, there are two kinds of data types in
<productname>PostgreSQL</productname>: base types (defined in a <productname>PostgreSQL</productname>: base types and composite
programming language) and composite types. This chapter describes types. This section describes how to define new base types.
how to define new base types.
</para> </para>
<para> <para>
The examples in this section can be found in The examples in this section can be found in
<filename>complex.sql</filename> and <filename>complex.c</filename> <filename>complex.sql</filename> and <filename>complex.c</filename>
in the tutorial directory. Composite examples are in in the tutorial directory.
<filename>funcs.sql</filename>.
</para> </para>
<para> <para>
...@@ -36,15 +38,15 @@ ...@@ -36,15 +38,15 @@
These functions determine how the type appears in strings (for input 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 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 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. 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>
<para> <para>
Suppose we want to define a complex type which represents complex Suppose we want to define a type <type>complex</> that represents
numbers. Naturally, we would choose to represent a complex in memory complex numbers. A natural way to to represent a complex number in
as the following <acronym>C</acronym> structure: memory would be the following C structure:
<programlisting> <programlisting>
typedef struct Complex { typedef struct Complex {
...@@ -53,24 +55,16 @@ typedef struct Complex { ...@@ -53,24 +55,16 @@ typedef struct Complex {
} Complex; } Complex;
</programlisting> </programlisting>
and a string of the form <literal>(x,y)</literal> as the external string As the external string representation of the type, we choose a
representation. 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>
<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> <programlisting>
Complex * Complex *
...@@ -78,19 +72,19 @@ complex_in(char *str) ...@@ -78,19 +72,19 @@ complex_in(char *str)
{ {
double x, y; double x, y;
Complex *result; 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); elog(ERROR, "complex_in: error in parsing %s", str);
return NULL; return NULL;
} }
result = (Complex *)palloc(sizeof(Complex)); result = (Complex *) palloc(sizeof(Complex));
result-&gt;x = x; result-&gt;x = x;
result-&gt;y = y; result-&gt;y = y;
return (result); return result;
} }
</programlisting> </programlisting>
</para>
<para>
The output function can simply be: The output function can simply be:
<programlisting> <programlisting>
...@@ -98,29 +92,23 @@ char * ...@@ -98,29 +92,23 @@ char *
complex_out(Complex *complex) complex_out(Complex *complex)
{ {
char *result; char *result;
if (complex == NULL) if (complex == NULL)
return(NULL); return(NULL);
result = (char *) palloc(60); result = (char *) palloc(60);
sprintf(result, "(%g,%g)", complex-&gt;x, complex-&gt;y); sprintf(result, "(%g,%g)", complex-&gt;x, complex-&gt;y);
return(result); return result;
} }
</programlisting> </programlisting>
</para> </para>
</listitem>
<listitem>
<para> <para>
You should try to make the input and output functions inverses of You should try to make the input and output functions inverses of
each other. If you do not, you will have severe problems when each other. If you do not, you will have severe problems when you
you need to dump your data into a file and then read it back in need to dump your data into a file and then read it back in. This
(say, into someone else's database on another computer). This is is a particularly common problem when floating-point numbers are
a particularly common problem when floating-point numbers are
involved. involved.
</para> </para>
</listitem>
</itemizedlist>
</para>
<para> <para>
To define the <type>complex</type> type, we need to create the two To define the <type>complex</type> type, we need to create the two
...@@ -130,14 +118,18 @@ complex_out(Complex *complex) ...@@ -130,14 +118,18 @@ complex_out(Complex *complex)
<programlisting> <programlisting>
CREATE FUNCTION complex_in(cstring) CREATE FUNCTION complex_in(cstring)
RETURNS complex RETURNS complex
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' AS '<replaceable>filename</replaceable>'
LANGUAGE C; LANGUAGE C;
CREATE FUNCTION complex_out(complex) CREATE FUNCTION complex_out(complex)
RETURNS cstring RETURNS cstring
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' AS '<replaceable>filename</replaceable>'
LANGUAGE C; LANGUAGE C;
</programlisting> </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>
<para> <para>
...@@ -149,49 +141,36 @@ CREATE TYPE complex ( ...@@ -149,49 +141,36 @@ CREATE TYPE complex (
output = complex_out output = complex_out
); );
</programlisting> </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>
<para> <para>
<indexterm> When you define a new base type,
<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,
<productname>PostgreSQL</productname> automatically provides support <productname>PostgreSQL</productname> automatically provides support
for arrays of that type. For historical reasons, the array type has for arrays of that
the same name as the user-defined type with the underscore character type.<indexterm><primary>array</primary><secondary>of user-defined
<literal>_</> prepended. 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>
<para> <para>
Composite types do not need any function defined on them, since the If the values of your data type might exceed a few hundred bytes in
system already understands what they look like inside. 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>
<para> <para>
<indexterm> For further details see the description of the <command>CREATE
<primary>TOAST</primary> TYPE</command> command in <xref linkend="reference">.
<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.
</para> </para>
</chapter> </sect1>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
Local variables: 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