OSDN Git Service

Some preliminary documentation for composite-type stuff.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 7 Jun 2004 04:04:47 +0000 (04:04 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 7 Jun 2004 04:04:47 +0000 (04:04 +0000)
doc/src/sgml/array.sgml
doc/src/sgml/catalogs.sgml
doc/src/sgml/datatype.sgml
doc/src/sgml/extend.sgml
doc/src/sgml/filelist.sgml
doc/src/sgml/rowtypes.sgml [new file with mode: 0644]
doc/src/sgml/syntax.sgml

index 34ced3c..cbd576b 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/array.sgml,v 1.34 2003/11/29 19:51:36 pgsql Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/array.sgml,v 1.35 2004/06/07 04:04:47 tgl Exp $ -->
 
 <sect1 id="arrays">
  <title>Arrays</title>
@@ -10,7 +10,8 @@
  <para>
   <productname>PostgreSQL</productname> allows columns of a table to be
   defined as variable-length multidimensional arrays. Arrays of any
-  built-in type or user-defined type can be created.
+  built-in or user-defined base type can be created.  (Arrays of
+  composite types or domains are not yet supported, however.)
  </para>
 
  <sect2>
index 0cdbdcf..226eef1 100644 (file)
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.85 2004/04/01 21:28:43 tgl Exp $
+ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.86 2004/06/07 04:04:47 tgl Exp $
  -->
 
 <chapter id="catalogs">
    The catalog <structname>pg_class</structname> catalogs tables and most
    everything else that has columns or is otherwise similar to a
    table.  This includes indexes (but see also
-   <structname>pg_index</structname>), sequences, views, and some
-   kinds of special relation; see <structfield>relkind</>.
+   <structname>pg_index</structname>), sequences, views, composite types,
+   and some kinds of special relation; see <structfield>relkind</>.
    Below, when we mean all of these
    kinds of objects we speak of <quote>relations</quote>.  Not all
    columns are meaningful for all relation types.
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
       <entry>
-       The OID of the data type that corresponds to this table, if any
-       (zero for indexes, which have no <structname>pg_type</> entry)
+       The OID of the data type that corresponds to this table's rowtype,
+       if any (zero for indexes, which have no <structname>pg_type</> entry)
       </entry>
      </row>
 
       <entry></entry>
       <entry>
        <structfield>typtype</structfield> is <literal>b</literal> for
-       a base type, <literal>c</literal> for a composite type (i.e., a
+       a base type, <literal>c</literal> for a composite type (e.g., a
        table's row type), <literal>d</literal> for a domain, or
        <literal>p</literal> for a pseudo-type.  See also
        <structfield>typrelid</structfield> and
        <structname>pg_class</structname> entry doesn't really represent
        a table, but it is needed anyway for the type's
        <structname>pg_attribute</structname> entries to link to.)
-       Zero for base types.
+       Zero for non-composite types.
       </entry>
      </row>
 
index 769357a..19feebe 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.144 2004/03/23 02:47:35 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.145 2004/06/07 04:04:47 tgl Exp $
 -->
 
  <chapter id="datatype">
@@ -2879,6 +2879,8 @@ SELECT * FROM test;
 
   &array;
 
+  &rowtypes;
+
   <sect1 id="datatype-oid">
    <title>Object Identifier Types</title>
 
index 47b0262..7019434 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.27 2003/11/29 19:51:37 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.28 2004/06/07 04:04:47 tgl Exp $
 -->
 
  <chapter id="extend">
@@ -151,7 +151,7 @@ $PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.27 2003/11/29 19:51:37 pgsql Exp
     </para>
 
     <para>
-     Domains can be created using the <acronym>SQL</> commands
+     Domains can be created using the <acronym>SQL</> command
      <command>CREATE DOMAIN</command>.  Their creation and use is not
      discussed in this chapter.
     </para>
index ae0a44f..d8e5b30 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/filelist.sgml,v 1.37 2004/04/20 01:11:49 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/filelist.sgml,v 1.38 2004/06/07 04:04:47 tgl Exp $ -->
 
 <!entity history    SYSTEM "history.sgml">
 <!entity info       SYSTEM "info.sgml">
@@ -17,6 +17,7 @@
 
 <!-- user's guide -->
 <!entity array      SYSTEM "array.sgml">
+<!entity rowtypes   SYSTEM "rowtypes.sgml">
 <!entity datatype   SYSTEM "datatype.sgml">
 <!entity ddl        SYSTEM "ddl.sgml">
 <!entity dml        SYSTEM "dml.sgml">
diff --git a/doc/src/sgml/rowtypes.sgml b/doc/src/sgml/rowtypes.sgml
new file mode 100644 (file)
index 0000000..4a5d013
--- /dev/null
@@ -0,0 +1,261 @@
+<!-- $PostgreSQL: pgsql/doc/src/sgml/rowtypes.sgml,v 2.1 2004/06/07 04:04:47 tgl Exp $ -->
+
+<sect1 id="rowtypes">
+ <title>Composite Types</title>
+
+ <indexterm>
+  <primary>composite type</primary>
+ </indexterm>
+
+ <indexterm>
+  <primary>row type</primary>
+ </indexterm>
+
+ <para>
+  A <firstterm>composite type</> describes the structure of a row or record;
+  it is in essence just a list of field names and their datatypes.
+  <productname>PostgreSQL</productname> allows values of composite types to be
+  used in many of the same ways that simple types can be used.  For example, a
+  column of a table can be declared to be of a composite type.
+ </para>
+
+ <sect2>
+  <title>Declaration of Composite Types</title>
+
+ <para>
+  Here are two simple examples of defining composite types:
+<programlisting>
+CREATE TYPE complex AS (
+    r       double precision,
+    i       double precision
+);
+
+CREATE TYPE inventory_item AS (
+    name            text,
+    supplier_id     integer,
+    price           numeric
+);
+</programlisting>
+  The syntax is comparable to <command>CREATE TABLE</>, except that only
+  field names and types can be specified; no constraints (such as <literal>NOT
+  NULL</>) can presently be included.  Note that the <literal>AS</> keyword
+  is essential; without it, the system will think a quite different kind
+  of <command>CREATE TYPE</> command is meant, and you'll get odd syntax
+  errors.
+ </para>
+
+ <para>
+  Having defined the types, we can use them to create tables:
+
+<programlisting>
+CREATE TABLE on_hand (
+    item      inventory_item,
+    count     integer
+);
+
+INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);
+</programlisting>
+
+  or functions:
+
+<programlisting>
+CREATE FUNCTION price_extension(inventory_item, integer) RETURNS numeric
+AS 'SELECT $1.price * $2' LANGUAGE SQL;
+
+SELECT price_extension(item, 10) FROM on_hand;
+</programlisting>
+
+ </para>
+ </sect2>
+
+ <sect2>
+  <title>Composite Value Input</title>
+
+  <indexterm>
+   <primary>composite type</primary>
+   <secondary>constant</secondary>
+  </indexterm>
+
+  <para>
+   To write a composite value as a literal constant, enclose the field
+   values within parentheses and separate them by commas.  You may put double
+   quotes around any field value, and must do so if it contains commas or
+   parentheses.  (More details appear below.)  Thus, the general format of a
+   composite constant is the following:
+<synopsis>
+'( <replaceable>val1</replaceable> , <replaceable>val2</replaceable> , ... )'
+</synopsis>
+   An example is
+<programlisting>
+'("fuzzy dice",42,1.99)'
+</programlisting>
+   which would be a valid value of the <literal>inventory_item</> type
+   defined above.  To make a field be NULL, write no characters at all
+   in its position in the list.  For example, this constant specifies
+   a NULL third field:
+<programlisting>
+'("fuzzy dice",42,)'
+</programlisting>
+   If you want an empty string rather than NULL, write double quotes:
+<programlisting>
+'("",42,)'
+</programlisting>
+   Here the first field is a non-NULL empty string, the third is NULL.
+  </para>
+
+  <para>
+   (These constants are actually only a special case of
+   the generic type constants discussed in <xref
+   linkend="sql-syntax-constants-generic">.  The constant is initially
+   treated as a string and passed to the composite-type input conversion
+   routine.  An explicit type specification might be necessary.)
+  </para>
+
+ <para>
+  The <literal>ROW</literal> expression syntax may also be used to
+  construct composite values.  In most cases this is considerably
+  simpler to use than the string-literal syntax, since you don't have
+  to worry about multiple layers of quoting.  We already used this
+  method above:
+<programlisting>
+ROW('fuzzy dice', 42, 1.99)
+ROW('', 42, NULL)
+</programlisting>
+  The ROW keyword is actually optional as long as you have more than one
+  field in the expression, so these can simplify to
+<programlisting>
+('fuzzy dice', 42, 1.99)
+('', 42, NULL)
+</programlisting>
+  The <literal>ROW</> expression syntax is discussed in more detail in <xref
+  linkend="sql-syntax-row-constructors">.
+ </para>
+ </sect2>
+
+ <sect2>
+  <title>Accessing Composite Types</title>
+
+ <para>
+  To access a field of a composite column, one writes a dot and the field
+  name, much like selecting a field from a table name.  In fact, it's so
+  much like selecting from a table name that you often have to use parentheses
+  to keep from confusing the parser.  For example, you might try to select
+  some subfields from our <literal>on_hand</> example table with something
+  like:
+
+<programlisting>
+SELECT item.name FROM on_hand WHERE item.price > 9.99;
+</programlisting>
+
+  This will not work since the name <literal>item</> is taken to be a table
+  name, not a field name, per SQL syntax rules.  You must write it like this:
+
+<programlisting>
+SELECT (item).name FROM on_hand WHERE (item).price > 9.99;
+</programlisting>
+
+  or if you need to use the table name as well (for instance in a multi-table
+  query), like this:
+
+<programlisting>
+SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;
+</programlisting>
+
+  Now the parenthesized object is correctly interpreted as a reference to
+  the <literal>item</> column, and then the subfield can be selected from it.
+ </para>
+
+ <para>
+  Similar syntactic issues apply whenever you select a field from a composite
+  value.  For instance, to select just one field from the result of a function
+  that returns a composite value, you'd need to write something like
+
+<programlisting>
+SELECT (my_func(...)).field FROM ...
+</programlisting>
+
+  Without the extra parentheses, this will provoke a syntax error.
+ </para>
+ </sect2>
+
+ <sect2>
+  <title>Composite Type Input and Output Syntax</title>
+
+  <para>
+   The external text representation of a composite value consists of items that
+   are interpreted according to the I/O conversion rules for the individual
+   field types, plus decoration that indicates the composite structure.
+   The decoration consists of parentheses (<literal>(</> and <literal>)</>)
+   around the whole value, plus commas (<literal>,</>) between adjacent
+   items.  Whitespace outside the parentheses is ignored, but within the
+   parentheses it is considered part of the field value, and may or may not be
+   significant depending on the input conversion rules for the field datatype.
+   For example, in
+<programlisting>
+'(  42)'
+</programlisting>
+   the whitespace will be ignored if the field type is integer, but not if
+   it is text.
+  </para>
+
+  <para>
+   As shown previously, when writing a composite value you may write double
+   quotes around any individual field value.
+   You <emphasis>must</> do so if the field value would otherwise
+   confuse the composite-value parser.  In particular, fields containing
+   parentheses, commas, double quotes, or backslashes must be double-quoted.
+   To put a double quote or backslash in a quoted composite field value,
+   precede it with a backslash.  (Also, a pair of double quotes within a
+   double-quoted field value is taken to represent a double quote character,
+   analogously to the rules for single quotes in SQL literal strings.)
+   Alternatively, you can use backslash-escaping to protect all data characters
+   that would otherwise be taken as composite syntax.
+  </para>
+
+  <para>
+   A completely empty field value (no characters at all between the commas
+   or parentheses) represents a NULL.  To write a value that is an empty
+   string rather than NULL, write <literal>""</>.
+  </para>
+
+  <para>
+   The composite output routine will put double quotes around field values
+   if they are empty strings or contain parentheses, commas,
+   double quotes, backslashes, or white space.  (Doing so for white space
+   is not essential, but aids legibility.)  Double quotes and backslashes
+   embedded in field values will be doubled.
+  </para>
+
+ <note>
+  <para>
+   Remember that what you write in an SQL command will first be interpreted
+   as a string literal, and then as a composite.  This doubles the number of
+   backslashes you need.  For example, to insert a <type>text</> field
+   containing a double quote and a backslash in a composite
+   value, you'd need to write
+<programlisting>
+INSERT ... VALUES ('("\\"\\\\")');
+</programlisting>
+   The string-literal processor removes one level of backslashes, so that
+   what arrives at the composite-value parser looks like
+   <literal>("\"\\")</>.  In turn, the string
+   fed to the <type>text</> data type's input routine
+   becomes <literal>"\</>.  (If we were working
+   with a data type whose input routine also treated backslashes specially,
+   <type>bytea</> for example, we might need as many as eight backslashes
+   in the command to get one backslash into the stored composite field.)
+  </para>
+ </note>
+
+ <tip>
+  <para>
+   The <literal>ROW</> constructor syntax is usually easier to work with
+   than the composite-literal syntax when writing composite values in SQL
+   commands. 
+   In <literal>ROW</>, individual field values are written the same way
+   they would be written when not members of a composite.
+  </para>
+ </tip>
+ </sect2>
+
+</sect1>
index 18eaac0..693f638 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.92 2004/05/16 23:22:07 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.93 2004/06/07 04:04:47 tgl Exp $
 -->
 
 <chapter id="sql-syntax">
@@ -1496,18 +1496,24 @@ SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');
    <title>Row Constructors</title>
 
    <indexterm>
-    <primary>row</primary>
+    <primary>composite type</primary>
+    <secondary>constructor</secondary>
+   </indexterm>
+
+   <indexterm>
+    <primary>row type</primary>
     <secondary>constructor</secondary>
    </indexterm>
 
    <para>
-    A row constructor is an expression that builds a row value from values
+    A row constructor is an expression that builds a row value (also
+    called a composite value) from values
     for its member fields.  A row constructor consists of the key word
     <literal>ROW</literal>, a left parenthesis <literal>(</>, zero or more
     expressions (separated by commas) for the row field values, and finally
     a right parenthesis <literal>)</>.  For example,
 <programlisting>
-SELECT myfunc(ROW(1,2.5,'this is a test'));
+SELECT ROW(1,2.5,'this is a test');
 </programlisting>
     The key word <literal>ROW</> is optional when there is more than one
     expression in the list.
@@ -1549,10 +1555,10 @@ SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype));
   </para>
 
   <para>
-   Row constructors have only limited uses, other than creating an argument
-   value for a user-defined function that accepts a rowtype parameter, as
-   illustrated above.
-   It is possible to compare two row values or test a row with
+   Row constructors can be used to build composite values to be stored
+   in a composite-type table column, or to be passed to a function that
+   accepts a composite parameter.  Also,
+   it is possible to compare two row values or test a row with
    <literal>IS NULL</> or <literal>IS NOT NULL</>, for example
 <programlisting>
 SELECT ROW(1,2.5,'this is a test') = ROW(1, 3, 'not the same');