]> granicus.if.org Git - postgresql/commitdiff
Back out array mega-patch.
authorBruce Momjian <bruce@momjian.us>
Wed, 25 Jun 2003 21:30:34 +0000 (21:30 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 25 Jun 2003 21:30:34 +0000 (21:30 +0000)
Joe Conway

42 files changed:
doc/src/sgml/array.sgml
doc/src/sgml/func.sgml
src/backend/catalog/pg_aggregate.c
src/backend/commands/aggregatecmds.c
src/backend/executor/execQual.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeSubplan.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/util/clauses.c
src/backend/parser/gram.y
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_func.c
src/backend/parser/parse_oper.c
src/backend/utils/adt/acl.c
src/backend/utils/adt/array_userfuncs.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/varlena.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/fmgr/fmgr.c
src/include/catalog/pg_amop.h
src/include/catalog/pg_amproc.h
src/include/catalog/pg_opclass.h
src/include/catalog/pg_operator.h
src/include/catalog/pg_proc.h
src/include/fmgr.h
src/include/nodes/primnodes.h
src/include/optimizer/clauses.h
src/include/parser/parse_oper.h
src/include/utils/acl.h
src/include/utils/array.h
src/include/utils/builtins.h
src/include/utils/lsyscache.h
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/type.c
src/interfaces/ecpg/preproc/variable.c
src/test/regress/expected/arrays.out
src/test/regress/sql/arrays.sql

index a7a05762de3cb50e25f615856f02a2c3c89281a4..985a92f7fa1b31b58e9ea413865fbc437881820b 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.26 2003/06/24 23:14:42 momjian Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.27 2003/06/25 21:30:25 momjian Exp $ -->
 
 <sect1 id="arrays">
  <title>Arrays</title>
@@ -60,74 +60,14 @@ INSERT INTO sal_emp
 </programlisting>
  </para>
 
- <para>
-  A limitation of the present array implementation is that individual
-  elements of an array cannot be SQL null values.  The entire array can be set
-  to null, but you can't have an array with some elements null and some
-  not.
- </para>
- <para>
-  This can lead to surprising results. For example, the result of the
-  previous two inserts looks like this:
-<programlisting>
-SELECT * FROM sal_emp;
- name  |      pay_by_quarter       |      schedule
--------+---------------------------+--------------------
- Bill  | {10000,10000,10000,10000} | {{meeting},{""}}
- Carol | {20000,25000,25000,25000} | {{talk},{meeting}}
-(2 rows)
-</programlisting>
-  Because the <literal>[2][2]</literal> element of
-  <structfield>schedule</structfield> is missing in each of the
-  <command>INSERT</command> statements, the <literal>[1][2]</literal>
-  element is discarded.
- </para>
-
  <note>
   <para>
-   Fixing this is on the to-do list.
+   A limitation of the present array implementation is that individual
+   elements of an array cannot be SQL null values.  The entire array can be set
+   to null, but you can't have an array with some elements null and some
+   not.  Fixing this is on the to-do list.
   </para>
  </note>
-
- <para>
-  The <command>ARRAY</command> expression syntax may also be used:
-<programlisting>
-INSERT INTO sal_emp
-    VALUES ('Bill',
-    ARRAY[10000, 10000, 10000, 10000],
-    ARRAY[['meeting', 'lunch'], ['','']]);
-
-INSERT INTO sal_emp
-    VALUES ('Carol',
-    ARRAY[20000, 25000, 25000, 25000],
-    ARRAY[['talk', 'consult'], ['meeting', '']]);
-SELECT * FROM sal_emp;
- name  |      pay_by_quarter       |           schedule
--------+---------------------------+-------------------------------
- Bill  | {10000,10000,10000,10000} | {{meeting,lunch},{"",""}}
- Carol | {20000,25000,25000,25000} | {{talk,consult},{meeting,""}}
-(2 rows)
-</programlisting>
-  Note that with this syntax, multidimensional arrays must have matching
-  extents for each dimension. This eliminates the missing-array-elements
-  problem above. For example:
-<programlisting>
-INSERT INTO sal_emp
-    VALUES ('Carol',
-    ARRAY[20000, 25000, 25000, 25000],
-    ARRAY[['talk', 'consult'], ['meeting']]);
-ERROR:  Multidimensional arrays must have array expressions with matching dimensions
-</programlisting>
-  Also notice that string literals are single quoted instead of double quoted.
- </para>
-
- <note>
-  <para>
-   The examples in the rest of this section are based on the
-   <command>ARRAY</command> expression syntax <command>INSERT</command>s.
-  </para>
- </note>
-
  </sect2>
 
  <sect2>
@@ -192,30 +132,11 @@ SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill';
 </programlisting>
 
   with the same result.  An array subscripting operation is always taken to
-  represent an array slice if any of the subscripts are written in the form
+  represent an array slice if any of the subscripts are written in the
+  form
   <literal><replaceable>lower</replaceable>:<replaceable>upper</replaceable></literal>.
   A lower bound of 1 is assumed for any subscript where only one value
-  is specified; another example follows:
-<programlisting>
-SELECT schedule[1:2][2] FROM sal_emp WHERE name = 'Bill';
-         schedule
----------------------------
- {{meeting,lunch},{"",""}}
-(1 row)
-</programlisting>
- </para>
-
- <para>
-  Additionally, we can also access a single arbitrary array element of 
-  a one-dimensional array with the <function>array_subscript</function>
-  function:
-<programlisting>
-SELECT array_subscript(pay_by_quarter, 2) FROM sal_emp WHERE name = 'Bill';
- array_subscript
------------------
-           10000
-(1 row)
-</programlisting>
+  is specified.
  </para>
 
  <para>
@@ -226,23 +147,7 @@ UPDATE sal_emp SET pay_by_quarter = '{25000,25000,27000,27000}'
     WHERE name = 'Carol';
 </programlisting>
 
-  or using the <command>ARRAY</command> expression syntax:
-
-<programlisting>
-UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000]
-    WHERE name = 'Carol';
-</programlisting>
-
-  <note>
-   <para>
-    Anywhere you can use the <quote>curly braces</quote> array syntax,
-    you can also use the <command>ARRAY</command> expression syntax. The
-    remainder of this section will illustrate only one or the other, but
-    not both.
-   </para>
-  </note>
-
-  An array may also be updated at a single element:
+  or updated at a single element:
 
 <programlisting>
 UPDATE sal_emp SET pay_by_quarter[4] = 15000
@@ -255,14 +160,6 @@ UPDATE sal_emp SET pay_by_quarter[4] = 15000
 UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}'
     WHERE name = 'Carol';
 </programlisting>
-
-  A one-dimensional array may also be updated with the
-  <function>array_assign</function> function:
-
-<programlisting>
-UPDATE sal_emp SET pay_by_quarter = array_assign(pay_by_quarter, 4, 15000)
-    WHERE name = 'Bill';
-</programListing>
  </para>
 
  <para>
@@ -281,88 +178,6 @@ UPDATE sal_emp SET pay_by_quarter = array_assign(pay_by_quarter, 4, 15000)
   create an array with subscript values running from -2 to 7.
  </para>
 
- <para>
-  An array can also be enlarged by using the concatenation operator,
-  <command>||</command>.
-<programlisting>
-SELECT ARRAY[1,2] || ARRAY[3,4];
-   ?column?
----------------
- {{1,2},{3,4}}
-(1 row)
-
-SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]];
-      ?column?
----------------------
- {{5,6},{1,2},{3,4}}
-(1 row)
-</programlisting>
-
-  The concatenation operator allows a single element to be pushed on to the
-  beginning or end of a one-dimensional array. It also allows two
-  <replaceable>N</>-dimensional arrays, or an <replaceable>N</>-dimensional
-  and an <replaceable>N+1</>-dimensional array. In the former case, the two
-  <replaceable>N</>-dimension arrays become outer elements of an
-  <replaceable>N+1</>-dimensional array. In the latter, the
-  <replaceable>N</>-dimensional array is added as either the first or last
-  outer element of the <replaceable>N+1</>-dimensional array.
-
-  The array is extended in the direction of the push. Hence, by pushing
-  onto the beginning of an array with a one-based subscript, a zero-based
-  subscript array is created:
-
-<programlisting>
-SELECT array_dims(t.f) FROM (SELECT 1 || ARRAY[2,3] AS f) AS t;
- array_dims
-------------
- [0:2]
-(1 row)
-</programlisting>
- </para>
-
- <para>
-  An array can also be enlarged by using the functions
-  <function>array_prepend</function>, <function>array_append</function>,
-  or <function>array_cat</function>. The first two only support one-dimensional
-  arrays, but <function>array_cat</function> supports multidimensional arrays.
-
-  Note that the concatenation operator discussed above is preferred over
-  direct use of these functions. In fact, the functions are primarily for use
-  in implementing the concatenation operator. However, they may be directly
-  useful in the creation of user-defined aggregates. Some examples:
-
-<programlisting>
-SELECT array_prepend(1, ARRAY[2,3]);
- array_prepend
----------------
- {1,2,3}
-(1 row)
-
-SELECT array_append(ARRAY[1,2], 3);
- array_append
---------------
- {1,2,3}
-(1 row)
-
-SELECT array_cat(ARRAY[1,2], ARRAY[3,4]);
-   array_cat
----------------
- {{1,2},{3,4}}
-(1 row)
-
-SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]);
-      array_cat
----------------------
- {{1,2},{3,4},{5,6}}
-(1 row)
-
-SELECT array_cat(ARRAY[5,6], ARRAY[[1,2],[3,4]]);
-      array_cat
----------------------
- {{5,6},{1,2},{3,4}}
-</programlisting>
- </para>
-
  <para>
   The syntax for <command>CREATE TABLE</command> allows fixed-length
   arrays to be defined:
@@ -378,16 +193,6 @@ CREATE TABLE tictactoe (
   length.
  </para>
 
- <para>
-  An alternative syntax for one-dimensional arrays may be used.
-  <structfield>pay_by_quarter</structfield> could have been defined as:
-<programlisting>
-    pay_by_quarter  integer ARRAY[4],
-</programlisting>
-  This syntax may <emphasis>only</emphasis> be used with the integer
-  constant to denote the array size.
- </para>
-
  <para>
   Actually, the current implementation does not enforce the declared
   number of dimensions either.  Arrays of a particular element type are
@@ -495,72 +300,6 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
    is not ignored, however: after skipping leading whitespace, everything
    up to the next right brace or delimiter is taken as the item value.
   </para>
-
-  <para>
-   As illustrated earlier in this chapter, arrays may also be represented
-   using the <command>ARRAY</command> expression syntax. This representation
-   of an array value consists of items that are interpreted according to the
-   I/O conversion rules for the array's element type, plus decoration that
-   indicates the array structure. The decoration consists of the keyword
-   <command>ARRAY</command> and square brackets (<literal>[</> and
-   <literal>]</>) around the array values, plus delimiter characters between
-   adjacent items. The delimiter character is always a comma (<literal>,</>).
-   When representing multidimensional arrays, the keyword
-   <command>ARRAY</command> is only necessary for the outer level. For example,
-   <literal>'{{"hello world", "happy birthday"}}'</literal> could be written as:
-<programlisting>
-SELECT ARRAY[['hello world', 'happy birthday']];
-               array
-------------------------------------
- {{"hello world","happy birthday"}}
-(1 row)
-</programlisting>
-  or it also could be written as:
-<programlisting>
-SELECT ARRAY[ARRAY['hello world', 'happy birthday']];
-               array
-------------------------------------
- {{"hello world","happy birthday"}}
-(1 row)
-</programlisting>
-  </para>
-
-  <para>
-   A final method to represent an array, is through an
-   <command>ARRAY</command> sub-select expression. For example:
-<programlisting>
-SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');
-                          ?column?
--------------------------------------------------------------
- {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31}
-(1 row)
-</programlisting>
-  The sub-select may <emphasis>only</emphasis> return a single column. The
-  resulting one-dimensional array will have an element for each row in the
-  sub-select result, with an element type matching that of the sub-select's
-  target column.
-  </para>
-
-  <para>
-   Arrays may be cast from one type to another in similar fashion to other
-   data types:
-
-<programlisting>
-SELECT ARRAY[1,2,3]::oid[];
-  array
----------
- {1,2,3}
-(1 row)
-
-SELECT CAST(ARRAY[1,2,3] AS float8[]);
-  array
----------
- {1,2,3}
-(1 row)
-</programlisting>
-
-  </para>
-
  </sect2>
 
  <sect2>
@@ -578,14 +317,6 @@ SELECT CAST(ARRAY[1,2,3] AS float8[]);
    that would otherwise be taken as array syntax or ignorable white space.
   </para>
 
- <note>
-  <para>
-   The discussion in the preceding paragraph with respect to double quoting does
-   not pertain to the <command>ARRAY</command> expression syntax. In that case,
-   each element is quoted exactly as any other literal value of the element type.
-  </para>
- </note>
-
   <para>
    The array output routine will put double quotes around element values
    if they are empty strings or contain curly braces, delimiter characters,
index d092cafa2da475ccc527cfb5e2bd9ff2f109faff..3db3ab34e83a84193b129235212d9e0e9b7782ad 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.155 2003/06/24 23:14:42 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.156 2003/06/25 21:30:25 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -6962,203 +6962,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
 
   </sect1>
 
- <sect1 id="functions-array">
-  <title>Array Functions</title>
-
-  <para>
-   <xref linkend="array-operators-table"> shows the operators
-   available for the <type>array</type> types.
-  </para>
-
-    <table id="array-operators-table">
-     <title><type>array</type> Operators</title>
-     <tgroup cols="4">
-      <thead>
-       <row>
-       <entry>Operator</entry>
-       <entry>Description</entry>
-       <entry>Example</entry>
-       <entry>Result</entry>
-       </row>
-      </thead>
-      <tbody>
-       <row>
-       <entry> <literal>=</literal> </entry>
-       <entry>equals</entry>
-       <entry><literal>ARRAY[1.1,2.1,3.1]::int[] = ARRAY[1,2,3]</literal></entry>
-       <entry><literal>t</literal></entry>
-       </row>
-       <row>
-       <entry> <literal>||</literal> </entry>
-       <entry>array-to-array concatenation</entry>
-       <entry><literal>ARRAY[1,2,3] || ARRAY[4,5,6]</literal></entry>
-       <entry><literal>{{1,2,3},{4,5,6}}</literal></entry>
-       </row>
-       <row>
-       <entry> <literal>||</literal> </entry>
-       <entry>array-to-array concatenation</entry>
-       <entry><literal>ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9]]</literal></entry>
-       <entry><literal>{{1,2,3},{4,5,6},{7,8,9}}</literal></entry>
-       </row>
-       <row>
-       <entry> <literal>||</literal> </entry>
-       <entry>element-to-array concatenation</entry>
-       <entry><literal>3 || ARRAY[4,5,6]</literal></entry>
-       <entry><literal>{3,4,5,6}</literal></entry>
-       </row>
-       <row>
-       <entry> <literal>||</literal> </entry>
-       <entry>array-to-element concatenation</entry>
-       <entry><literal>ARRAY[4,5,6] || 7</literal></entry>
-       <entry><literal>{4,5,6,7}</literal></entry>
-       </row>
-      </tbody>
-     </tgroup>
-    </table>
-
-  <para>
-   <xref linkend="array-functions-table"> shows the functions
-   available for use with array types. See <xref linkend="arrays">
-   for more discussion and examples for the use of these functions.
-  </para>
-
-    <table id="array-functions-table">
-     <title><type>array</type> Functions</title>
-     <tgroup cols="5">
-      <thead>
-       <row>
-       <entry>Function</entry>
-       <entry>Return Type</entry>
-       <entry>Description</entry>
-       <entry>Example</entry>
-       <entry>Result</entry>
-       </row>
-      </thead>
-      <tbody>
-       <row>
-       <entry>
-     <literal>
-      <function>array_append</function>
-      (<type>anyarray</type>, <type>anyelement</type>)
-     </literal>
-    </entry>
-       <entry><type>anyarray</type></entry>
-       <entry>
-     append an element to the end of an array, returning
-     <literal>NULL</literal> for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_append(ARRAY[1,2], 3)</literal></entry>
-       <entry><literal>{1,2,3}</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>array_cat</function>
-      (<type>anyarray</type>, <type>anyarray</type>)
-     </literal>
-    </entry>
-       <entry><type>anyarray</type></entry>
-       <entry>
-     concatenate two arrays, returning <literal>NULL</literal>
-     for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_cat(ARRAY[1,2,3], ARRAY[4,5,6])</literal></entry>
-       <entry><literal>{{1,2,3},{4,5,6}}</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>array_dims</function>
-      (<type>anyarray</type>)
-     </literal>
-    </entry>
-       <entry><type>text</type></entry>
-       <entry>
-     returns a text representation of array dimension lower and upper bounds,
-     generating an ERROR for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_dims(array[[1,2,3],[4,5,6]])</literal></entry>
-       <entry><literal>[1:2][1:3]</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>array_lower</function>
-      (<type>anyarray</type>, <type>integer</type>)
-     </literal>
-    </entry>
-       <entry><type>integer</type></entry>
-       <entry>
-     returns lower bound of the requested array dimension, returning
-     <literal>NULL</literal> for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_lower(array_prepend(0, ARRAY[1,2,3]), 1)</literal></entry>
-       <entry><literal>0</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>array_prepend</function>
-      (<type>anyelement</type>, <type>anyarray</type>)
-     </literal>
-    </entry>
-       <entry><type>anyarray</type></entry>
-       <entry>
-     append an element to the beginning of an array, returning
-     <literal>NULL</literal> for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_prepend(1, ARRAY[2,3])</literal></entry>
-       <entry><literal>{1,2,3}</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>array_to_string</function>
-      (<type>anyarray</type>, <type>text</type>)
-     </literal>
-    </entry>
-       <entry><type>text</type></entry>
-       <entry>
-     concatenates array elements using provided delimiter, returning
-     <literal>NULL</literal> for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_to_string(array[1.1,2.2,3.3]::numeric(4,2)[],'~^~')</literal></entry>
-       <entry><literal>1.10~^~2.20~^~3.30</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>array_upper</function>
-      (<type>anyarray</type>, <type>integer</type>)
-     </literal>
-    </entry>
-       <entry><type>integer</type></entry>
-       <entry>
-     returns upper bound of the requested array dimension, returning
-     <literal>NULL</literal> for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>array_upper(array_append(ARRAY[1,2,3], 4), 1)</literal></entry>
-       <entry><literal>4</literal></entry>
-       </row>
-       <row>
-       <entry>
-     <literal>
-      <function>string_to_array</function>
-      (<type>text</type>, <type>text</type>)
-     </literal>
-    </entry>
-       <entry><type>text[]</type></entry>
-       <entry>
-     splits string into array elements using provided delimiter, returning
-     <literal>NULL</literal> for <literal>NULL</literal> inputs
-    </entry>
-       <entry><literal>string_to_array('1.10~^~2.20~^~3.30','~^~')::float8[]</literal></entry>
-       <entry><literal>{1.1,2.2,3.3}</literal></entry>
-       </row>
-      </tbody>
-     </tgroup>
-    </table>
-  </sect1>
 
  <sect1 id="functions-aggregate">
   <title>Aggregate Functions</title>
index 9025862be123f6734e65b537207ea2cfd1117ae9..a2160fa0251b0615c460a08071753bf39c4530e3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.57 2003/06/24 23:14:42 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.58 2003/06/25 21:30:25 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,16 +50,10 @@ AggregateCreate(const char *aggName,
        Oid                     finalfn = InvalidOid;   /* can be omitted */
        Oid                     finaltype;
        Oid                     fnArgs[FUNC_MAX_ARGS];
-       int                     nargs_transfn;
-       int                     nargs_finalfn;
+       int                     nargs;
        Oid                     procOid;
        TupleDesc       tupDesc;
        int                     i;
-       Oid                     rettype;
-       Oid                *true_oid_array_transfn;
-       Oid                *true_oid_array_finalfn;
-       bool            retset;
-       FuncDetailCode fdresult;
        ObjectAddress myself,
                                referenced;
 
@@ -74,49 +68,24 @@ AggregateCreate(const char *aggName,
        MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid));
        fnArgs[0] = aggTransType;
        if (aggBaseType == ANYOID)
-               nargs_transfn = 1;
+               nargs = 1;
        else
        {
                fnArgs[1] = aggBaseType;
-               nargs_transfn = 2;
+               nargs = 2;
        }
-
-       /*
-        * func_get_detail looks up the function in the catalogs, does
-        * disambiguation for polymorphic functions, handles inheritance, and
-        * returns the funcid and type and set or singleton status of the
-        * function's return value.  it also returns the true argument types
-        * to the function.
-        */
-       fdresult = func_get_detail(aggtransfnName, NIL, nargs_transfn, fnArgs,
-                                                          &transfn, &rettype, &retset,
-                                                          &true_oid_array_transfn);
-
-       /* only valid case is a normal function */
-       if (fdresult != FUNCDETAIL_NORMAL)
-               func_error("AggregateCreate", aggtransfnName, nargs_transfn, fnArgs, NULL);
-
+       transfn = LookupFuncName(aggtransfnName, nargs, fnArgs);
        if (!OidIsValid(transfn))
-               func_error("AggregateCreate", aggtransfnName, nargs_transfn, fnArgs, NULL);
-
-       /*
-        * enforce consistency with ANYARRAY and ANYELEMENT argument
-        * and return types, possibly modifying return type along the way
-        */
-       rettype = enforce_generic_type_consistency(fnArgs, true_oid_array_transfn,
-                                                                                                          nargs_transfn, rettype);
-
-       if (rettype != aggTransType)
-               elog(ERROR, "return type of transition function %s is not %s",
-                NameListToString(aggtransfnName), format_type_be(aggTransType));
-
+               func_error("AggregateCreate", aggtransfnName, nargs, fnArgs, NULL);
        tup = SearchSysCache(PROCOID,
                                                 ObjectIdGetDatum(transfn),
                                                 0, 0, 0);
        if (!HeapTupleIsValid(tup))
-               func_error("AggregateCreate", aggtransfnName,
-                                               nargs_transfn, fnArgs, NULL);
+               func_error("AggregateCreate", aggtransfnName, nargs, fnArgs, NULL);
        proc = (Form_pg_proc) GETSTRUCT(tup);
+       if (proc->prorettype != aggTransType)
+               elog(ERROR, "return type of transition function %s is not %s",
+                NameListToString(aggtransfnName), format_type_be(aggTransType));
 
        /*
         * If the transfn is strict and the initval is NULL, make sure input
@@ -136,26 +105,17 @@ AggregateCreate(const char *aggName,
        {
                MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid));
                fnArgs[0] = aggTransType;
-               nargs_finalfn = 1;
-
-               fdresult = func_get_detail(aggfinalfnName, NIL, 1, fnArgs,
-                                                                  &finalfn, &rettype, &retset,
-                                                                  &true_oid_array_finalfn);
-
-               /* only valid case is a normal function */
-               if (fdresult != FUNCDETAIL_NORMAL)
-                       func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL);
-
+               finalfn = LookupFuncName(aggfinalfnName, 1, fnArgs);
                if (!OidIsValid(finalfn))
                        func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL);
-
-               /*
-                * enforce consistency with ANYARRAY and ANYELEMENT argument
-                * and return types, possibly modifying return type along the way
-                */
-               finaltype = enforce_generic_type_consistency(fnArgs,
-                                                                                                        true_oid_array_finalfn,
-                                                                                                        nargs_finalfn, rettype);
+               tup = SearchSysCache(PROCOID,
+                                                        ObjectIdGetDatum(finalfn),
+                                                        0, 0, 0);
+               if (!HeapTupleIsValid(tup))
+                       func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL);
+               proc = (Form_pg_proc) GETSTRUCT(tup);
+               finaltype = proc->prorettype;
+               ReleaseSysCache(tup);
        }
        else
        {
@@ -166,27 +126,6 @@ AggregateCreate(const char *aggName,
        }
        Assert(OidIsValid(finaltype));
 
-       /*
-        * special disallowed cases:
-        * 1)   if finaltype is polymorphic, basetype cannot be ANY
-        * 2)   if finaltype is polymorphic, both args to transfn must be
-        *              polymorphic
-        */
-       if (finaltype == ANYARRAYOID || finaltype == ANYELEMENTOID)
-       {
-               if (aggBaseType == ANYOID)
-                       elog(ERROR, "aggregate with base type ANY must have a " \
-                                               "non-polymorphic return type");
-
-               if (nargs_transfn > 1 && (
-                       (true_oid_array_transfn[0] != ANYARRAYOID &&
-                        true_oid_array_transfn[0] != ANYELEMENTOID) ||
-                       (true_oid_array_transfn[1] != ANYARRAYOID &&
-                        true_oid_array_transfn[1] != ANYELEMENTOID)))
-                       elog(ERROR, "aggregate with polymorphic return type requires " \
-                                               "state function with both arguments polymorphic");
-       }
-
        /*
         * Everything looks okay.  Try to create the pg_proc entry for the
         * aggregate.  (This could fail if there's already a conflicting
index 07b9862e41a56d56deb1e24927c081003600dd24..bee50e686f0446475d7488a2cc66d277264da6d0 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.6 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.7 2003/06/25 21:30:26 momjian Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -119,9 +119,7 @@ DefineAggregate(List *names, List *parameters)
                baseTypeId = typenameTypeId(baseType);
 
        transTypeId = typenameTypeId(transType);
-       if (get_typtype(transTypeId) == 'p' &&
-               transTypeId != ANYARRAYOID &&
-               transTypeId != ANYELEMENTOID)
+       if (get_typtype(transTypeId) == 'p')
                elog(ERROR, "Aggregate transition datatype cannot be %s",
                         format_type_be(transTypeId));
 
index e729344060e363c31254c8aaed9467b7208b86cf..6e0a46e0e7fbf696f91a469a5ad7a45b44db00cd 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.131 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.132 2003/06/25 21:30:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1528,17 +1528,17 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
                        {
                                /* Check other sub-arrays are compatible */
                                if (elem_ndims != ARR_NDIM(array))
-                                       elog(ERROR, "Multidimensional arrays must have array "
+                                       elog(ERROR, "Multiple dimension arrays must have array "
                                                 "expressions with matching number of dimensions");
 
                                if (memcmp(elem_dims, ARR_DIMS(array),
                                                   elem_ndims * sizeof(int)) != 0)
-                                       elog(ERROR, "Multidimensional arrays must have array "
+                                       elog(ERROR, "Multiple dimension arrays must have array "
                                                 "expressions with matching dimensions");
 
                                if (memcmp(elem_lbs, ARR_LBOUND(array),
                                                   elem_ndims * sizeof(int)) != 0)
-                                       elog(ERROR, "Multidimensional arrays must have array "
+                                       elog(ERROR, "Multiple dimension arrays must have array "
                                                 "expressions with matching dimensions");
                        }
 
index dc8c1554bb0f5e3d725352ca015ce718e4ac680c..04d656f05a93b1f034ac73a252a05bec146c5047 100644 (file)
@@ -45,7 +45,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.108 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.109 2003/06/25 21:30:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,6 @@
 #include "executor/executor.h"
 #include "executor/nodeAgg.h"
 #include "miscadmin.h"
-#include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
 #include "parser/parse_coerce.h"
 #include "parser/parse_expr.h"
@@ -213,7 +212,7 @@ static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
 static void agg_fill_hash_table(AggState *aggstate);
 static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
-static Oid resolve_type(Oid type_to_resolve, Oid context_type);
+
 
 /*
  * Initialize all aggregates for a new group of input values.
@@ -352,12 +351,14 @@ advance_transition_function(AggState *aggstate,
        fcinfo.context = NULL;
        fcinfo.resultinfo = NULL;
        fcinfo.isnull = false;
+
        fcinfo.flinfo = &peraggstate->transfn;
        fcinfo.nargs = 2;
        fcinfo.arg[0] = pergroupstate->transValue;
        fcinfo.argnull[0] = pergroupstate->transValueIsNull;
        fcinfo.arg[1] = newVal;
        fcinfo.argnull[1] = isNull;
+
        newVal = FunctionCallInvoke(&fcinfo);
 
        /*
@@ -1186,21 +1187,7 @@ ExecInitAgg(Agg *node, EState *estate)
                AclResult       aclresult;
                Oid                     transfn_oid,
                                        finalfn_oid;
-               FuncExpr   *transfnexpr,
-                                  *finalfnexpr;
                Datum           textInitVal;
-               List       *fargs;
-               Oid                     agg_rt_type;
-               Oid                *transfn_arg_types;
-               List       *transfn_args = NIL;
-               int                     transfn_nargs;
-               Oid                     transfn_ret_type;
-               Oid                *finalfn_arg_types = NULL;
-               List       *finalfn_args = NIL;
-               Oid                     finalfn_ret_type = InvalidOid;
-               int                     finalfn_nargs = 0;
-               Node       *arg0;
-               Node       *arg1;
                int                     i;
 
                /* Planner should have assigned aggregate to correct level */
@@ -1251,166 +1238,6 @@ ExecInitAgg(Agg *node, EState *estate)
                                                &peraggstate->transtypeLen,
                                                &peraggstate->transtypeByVal);
 
-               peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
-               peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
-
-               /* get the runtime aggregate argument type */
-               fargs = aggref->args;
-               agg_rt_type = exprType((Node *) nth(0, fargs));
-
-               /* get the transition function argument and return types */
-               transfn_ret_type = get_func_rettype(transfn_oid);
-               transfn_arg_types = get_func_argtypes(transfn_oid, &transfn_nargs);
-
-               /* resolve any polymorphic types */
-               if (transfn_nargs == 2)
-               /* base type was not ANY */
-               {
-                       if (transfn_arg_types[1] == ANYARRAYOID ||
-                               transfn_arg_types[1] == ANYELEMENTOID)
-                               transfn_arg_types[1] = agg_rt_type;
-
-                       transfn_arg_types[0] = resolve_type(transfn_arg_types[0],
-                                                                                                               agg_rt_type);
-
-                       /*
-                        * Build arg list to use on the transfn FuncExpr node. We really
-                        * only care that the node type is correct so that the transfn
-                        * can discover the actual argument types at runtime using 
-                        * get_fn_expr_argtype()
-                        */
-                       arg0 = (Node *) makeRelabelType((Expr *) NULL, transfn_arg_types[0],
-                                                                                                                       -1, COERCE_DONTCARE);
-                       arg1 = (Node *) makeRelabelType((Expr *) NULL, transfn_arg_types[1],
-                                                                                                                       -1, COERCE_DONTCARE);
-                       transfn_args = makeList2(arg0, arg1);
-
-                       /*
-                        * the state transition function always returns the same type
-                        * as its first argument
-                        */
-                       if (transfn_ret_type == ANYARRAYOID ||
-                               transfn_ret_type == ANYELEMENTOID)
-                               transfn_ret_type = transfn_arg_types[0];
-               }
-               else if (transfn_nargs == 1)
-               /*
-                * base type was ANY, therefore the aggregate return type should
-                * be non-polymorphic
-                */
-               {
-                       Oid     finaltype = get_func_rettype(aggref->aggfnoid);
-
-                       /*
-                        * this should have been prevented in AggregateCreate,
-                        * but check anyway
-                        */
-                       if (finaltype == ANYARRAYOID || finaltype == ANYELEMENTOID)
-                               elog(ERROR, "aggregate with base type ANY must have a " \
-                                                       "non-polymorphic return type");
-
-                       /* see if we have a final function */
-                       if (OidIsValid(finalfn_oid))
-                       {
-                               finalfn_arg_types = get_func_argtypes(finalfn_oid, &finalfn_nargs);
-                               if (finalfn_nargs != 1)
-                                       elog(ERROR, "final function takes unexpected number " \
-                                                               "of arguments: %d", finalfn_nargs);
-
-                               /*
-                                * final function argument is always the same as the state
-                                * function return type
-                                */
-                               if (finalfn_arg_types[0] != ANYARRAYOID &&
-                                       finalfn_arg_types[0] != ANYELEMENTOID)
-                               {
-                                       /* if it is not ambiguous, use it */
-                                       transfn_ret_type = finalfn_arg_types[0];
-                               }
-                               else
-                               {
-                                       /* if it is ambiguous, try to derive it */
-                                       finalfn_ret_type = finaltype;
-                                       finalfn_arg_types[0] = resolve_type(finalfn_arg_types[0],
-                                                                                                                       finalfn_ret_type);
-                                       transfn_ret_type = finalfn_arg_types[0];
-                               }
-                       }
-                       else
-                               transfn_ret_type = finaltype;
-
-                       transfn_arg_types[0] = resolve_type(transfn_arg_types[0],
-                                                                                                               transfn_ret_type);
-
-                       /*
-                        * Build arg list to use on the transfn FuncExpr node. We really
-                        * only care that the node type is correct so that the transfn
-                        * can discover the actual argument types at runtime using 
-                        * get_fn_expr_argtype()
-                        */
-                       arg0 = (Node *) makeRelabelType((Expr *) NULL, transfn_arg_types[0],
-                                                                                                                       -1, COERCE_DONTCARE);
-                       transfn_args = makeList1(arg0);
-               }
-               else
-                       elog(ERROR, "state transition function takes unexpected number " \
-                                               "of arguments: %d", transfn_nargs);
-
-               if (OidIsValid(finalfn_oid))
-               {
-                       /* get the final function argument and return types */
-                       if (finalfn_ret_type == InvalidOid)
-                               finalfn_ret_type = get_func_rettype(finalfn_oid);
-
-                       if (!finalfn_arg_types)
-                       {
-                               finalfn_arg_types = get_func_argtypes(finalfn_oid, &finalfn_nargs);
-                               if (finalfn_nargs != 1)
-                                       elog(ERROR, "final function takes unexpected number " \
-                                                               "of arguments: %d", finalfn_nargs);
-                       }
-
-                       /*
-                        * final function argument is always the same as the state
-                        * function return type, which by now should have been resolved
-                        */
-                       if (finalfn_arg_types[0] == ANYARRAYOID ||
-                               finalfn_arg_types[0] == ANYELEMENTOID)
-                               finalfn_arg_types[0] = transfn_ret_type;
-
-                       /*
-                        * Build arg list to use on the finalfn FuncExpr node. We really
-                        * only care that the node type is correct so that the finalfn
-                        * can discover the actual argument type at runtime using 
-                        * get_fn_expr_argtype()
-                        */
-                       arg0 = (Node *) makeRelabelType((Expr *) NULL, finalfn_arg_types[0],
-                                                                                                                       -1, COERCE_DONTCARE);
-                       finalfn_args = makeList1(arg0);
-
-                       finalfn_ret_type = resolve_type(finalfn_ret_type,
-                                                                                               finalfn_arg_types[0]);
-               }
-
-               fmgr_info(transfn_oid, &peraggstate->transfn);
-               transfnexpr = (FuncExpr *) make_funcclause(transfn_oid,
-                                                 transfn_ret_type,
-                                                 false,                        /* cannot be a set */
-                                                 COERCE_DONTCARE,      /* to match any user expr */
-                                                 transfn_args);
-               peraggstate->transfn.fn_expr = (Node *) transfnexpr;
-
-               if (OidIsValid(finalfn_oid))
-               {
-                       fmgr_info(finalfn_oid, &peraggstate->finalfn);
-                       finalfnexpr = (FuncExpr *) make_funcclause(finalfn_oid,
-                                                 finalfn_ret_type,
-                                                 false,                        /* cannot be a set */
-                                                 COERCE_DONTCARE,      /* to match any user expr */
-                                                 finalfn_args);
-                       peraggstate->finalfn.fn_expr = (Node *) finalfnexpr;
-               }
-
                /*
                 * initval is potentially null, so don't try to access it as a
                 * struct field. Must do it the hard way with SysCacheGetAttr.
@@ -1423,7 +1250,14 @@ ExecInitAgg(Agg *node, EState *estate)
                        peraggstate->initValue = (Datum) 0;
                else
                        peraggstate->initValue = GetAggInitVal(textInitVal,
-                                                                                                  transfn_arg_types[0]);
+                                                                                                  aggform->aggtranstype);
+
+               peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
+               peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
+
+               fmgr_info(transfn_oid, &peraggstate->transfn);
+               if (OidIsValid(finalfn_oid))
+                       fmgr_info(finalfn_oid, &peraggstate->finalfn);
 
                /*
                 * If the transfn is strict and the initval is NULL, make sure
@@ -1635,36 +1469,3 @@ aggregate_dummy(PG_FUNCTION_ARGS)
                 fcinfo->flinfo->fn_oid);
        return (Datum) 0;                       /* keep compiler quiet */
 }
-
-static Oid
-resolve_type(Oid type_to_resolve, Oid context_type)
-{
-       Oid             resolved_type;
-
-       if (context_type == ANYARRAYOID || context_type == ANYELEMENTOID)
-               resolved_type = type_to_resolve;
-       else if (type_to_resolve == ANYARRAYOID)
-       /* any array */
-       {
-               Oid             context_type_arraytype = get_array_type(context_type);
-
-               if (context_type_arraytype != InvalidOid)
-                       resolved_type = context_type_arraytype;
-               else
-                       resolved_type = context_type;
-       }
-       else if (type_to_resolve == ANYELEMENTOID)
-       /* any element */
-       {
-               Oid             context_type_elemtype = get_element_type(context_type);
-
-               if (context_type_elemtype != InvalidOid)
-                       resolved_type = context_type_elemtype;
-               else
-                       resolved_type = context_type;
-       }
-       else
-               resolved_type = type_to_resolve;
-
-       return resolved_type;
-}
index 62aaa7e8d439cdd3eee4cd9f1ef010a00b5bbe37..645673776841b340b941dcc4bf8a49b1063daca3 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.48 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.49 2003/06/25 21:30:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/datum.h"
 #include "utils/lsyscache.h"
 
+
+typedef struct ArrayBuildState
+{
+       MemoryContext mcontext;         /* where all the temp stuff is kept */
+       Datum      *dvalues;            /* array of accumulated Datums */
+       /*
+        * The allocated size of dvalues[] is always a multiple of
+        * ARRAY_ELEMS_CHUNKSIZE
+        */
+#define ARRAY_ELEMS_CHUNKSIZE  64
+       int                     nelems;                 /* number of valid Datums in dvalues[] */
+       Oid                     element_type;   /* data type of the Datums */
+       int16           typlen;                 /* needed info about datatype */
+       bool            typbyval;
+       char            typalign;
+} ArrayBuildState;
+
 static Datum ExecHashSubPlan(SubPlanState *node,
                                                         ExprContext *econtext,
                                                         bool *isNull);
@@ -37,6 +54,13 @@ static Datum ExecScanSubPlan(SubPlanState *node,
 static void buildSubPlanHash(SubPlanState *node);
 static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot);
 static bool tupleAllNulls(HeapTuple tuple);
+static ArrayBuildState *accumArrayResult(ArrayBuildState *astate,
+                                                                                Datum dvalue, bool disnull,
+                                                                                Oid element_type,
+                                                                                MemoryContext rcontext);
+static Datum makeArrayResult(ArrayBuildState *astate,
+                                                        MemoryContext rcontext);
+
 
 /* ----------------------------------------------------------------
  *             ExecSubPlan
@@ -200,7 +224,6 @@ ExecScanSubPlan(SubPlanState *node,
        PlanState  *planstate = node->planstate;
        SubLinkType subLinkType = subplan->subLinkType;
        bool            useOr = subplan->useOr;
-       bool            isExpr = subplan->isExpr;
        MemoryContext oldcontext;
        TupleTableSlot *slot;
        Datum           result;
@@ -271,11 +294,6 @@ ExecScanSubPlan(SubPlanState *node,
                bool            rownull = false;
                int                     col = 1;
                List       *plst;
-               int                     numelems;
-               int                     elemnum;
-               Datum           dvalue;
-               Datum      *dvalues = NULL;
-               bool            disnull;
 
                if (subLinkType == EXISTS_SUBLINK)
                {
@@ -313,6 +331,9 @@ ExecScanSubPlan(SubPlanState *node,
 
                if (subLinkType == ARRAY_SUBLINK)
                {
+                       Datum   dvalue;
+                       bool    disnull;
+
                        found = true;
                        /* stash away current value */
                        dvalue = heap_getattr(tup, 1, tdesc, &disnull);
@@ -330,164 +351,99 @@ ExecScanSubPlan(SubPlanState *node,
                found = true;
 
                /*
-                * When isExpr is true, we have either a scalar expression or an
-                * array. In the former case, this is no different than the !isExpr
-                * case. In the latter case, iterate over the elements as if they
-                * were from multiple input tuples.
+                * For ALL, ANY, and MULTIEXPR sublinks, iterate over combining
+                * operators for columns of tuple.
                 */
-               if (!isExpr)
-                       numelems = 1;
-               else
+               plst = subplan->paramIds;
+               foreach(lst, node->exprs)
                {
-                       Oid             expr_typeid = tdesc->attrs[0]->atttypid;
+                       ExprState  *exprstate = (ExprState *) lfirst(lst);
+                       int                     paramid = lfirsti(plst);
+                       ParamExecData *prmdata;
+                       Datum           expresult;
+                       bool            expnull;
 
-                       if (expr_typeid != subplan->exprtype)
-                       {
-                               subplan->exprtype = expr_typeid;
-                               subplan->elemtype = get_element_type(expr_typeid);
-
-                               if (subplan->elemtype != InvalidOid)
-                                       get_typlenbyvalalign(subplan->elemtype,
-                                                                                &subplan->elmlen,
-                                                                                &subplan->elmbyval,
-                                                                                &subplan->elmalign);
-                       }
+                       /*
+                        * Load up the Param representing this column of the sub-select.
+                        */
+                       prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
+                       Assert(prmdata->execPlan == NULL);
+                       prmdata->value = heap_getattr(tup, col, tdesc,
+                                                                                 &(prmdata->isnull));
 
-                       /* get current value */
-                       dvalue = heap_getattr(tup, 1, tdesc, &disnull);
+                       /*
+                        * Now we can eval the combining operator for this column.
+                        */
+                       expresult = ExecEvalExprSwitchContext(exprstate, econtext,
+                                                                                                 &expnull, NULL);
 
-                       /* XXX this will need work if/when arrays support NULL elements */
-                       if (!disnull)
+                       /*
+                        * Combine the result into the row result as appropriate.
+                        */
+                       if (col == 1)
                        {
-                               if (subplan->elemtype != InvalidOid)
-                               {
-                                       ArrayType   *v = DatumGetArrayTypeP(dvalue);
-
-                                       deconstruct_array(v, subplan->elemtype, subplan->elmlen,
-                                                                         subplan->elmbyval, subplan->elmalign,
-                                                                         &dvalues, &numelems);
-                               }
-                               else
+                               rowresult = expresult;
+                               rownull = expnull;
+                       }
+                       else if (useOr)
+                       {
+                               /* combine within row per OR semantics */
+                               if (expnull)
+                                       rownull = true;
+                               else if (DatumGetBool(expresult))
                                {
-                                       numelems = 1;
-                                       dvalues = (Datum *) palloc(numelems * sizeof(Datum));
-                                       dvalues[0] = dvalue;
+                                       rowresult = BoolGetDatum(true);
+                                       rownull = false;
+                                       break;          /* needn't look at any more columns */
                                }
                        }
                        else
                        {
-                               numelems = 1;
-                               dvalues = (Datum *) palloc(numelems * sizeof(Datum));
-                               dvalues[0] = (Datum) 0;
+                               /* combine within row per AND semantics */
+                               if (expnull)
+                                       rownull = true;
+                               else if (!DatumGetBool(expresult))
+                               {
+                                       rowresult = BoolGetDatum(false);
+                                       rownull = false;
+                                       break;          /* needn't look at any more columns */
+                               }
                        }
 
+                       plst = lnext(plst);
+                       col++;
                }
 
-               for (elemnum = 0; elemnum < numelems; elemnum++)
+               if (subLinkType == ANY_SUBLINK)
                {
-                       /*
-                        * For ALL, ANY, and MULTIEXPR sublinks, iterate over combining
-                        * operators for columns of tuple.
-                        */
-                       col = 1;
-                       plst = subplan->paramIds;
-                       foreach(lst, node->exprs)
+                       /* combine across rows per OR semantics */
+                       if (rownull)
+                               *isNull = true;
+                       else if (DatumGetBool(rowresult))
                        {
-                               ExprState  *exprstate = (ExprState *) lfirst(lst);
-                               int                     paramid = lfirsti(plst);
-                               ParamExecData *prmdata;
-                               Datum           expresult;
-                               bool            expnull;
-
-                               /*
-                                * Load up the Param representing this column of the sub-select.
-                                */
-                               prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
-                               Assert(prmdata->execPlan == NULL);
-
-                               if (!isExpr)
-                                       prmdata->value = heap_getattr(tup, col, tdesc,
-                                                                                                 &(prmdata->isnull));
-                               else
-                               {
-                                       prmdata->value = dvalues[elemnum];
-                                       prmdata->isnull = disnull;
-                               }
-
-                               /*
-                                * Now we can eval the combining operator for this column.
-                                */
-                               expresult = ExecEvalExprSwitchContext(exprstate, econtext,
-                                                                                                         &expnull, NULL);
-
-                               /*
-                                * Combine the result into the row result as appropriate.
-                                */
-                               if (col == 1)
-                               {
-                                       rowresult = expresult;
-                                       rownull = expnull;
-                               }
-                               else if (useOr)
-                               {
-                                       /* combine within row per OR semantics */
-                                       if (expnull)
-                                               rownull = true;
-                                       else if (DatumGetBool(expresult))
-                                       {
-                                               rowresult = BoolGetDatum(true);
-                                               rownull = false;
-                                               break;          /* needn't look at any more columns */
-                                       }
-                               }
-                               else
-                               {
-                                       /* combine within row per AND semantics */
-                                       if (expnull)
-                                               rownull = true;
-                                       else if (!DatumGetBool(expresult))
-                                       {
-                                               rowresult = BoolGetDatum(false);
-                                               rownull = false;
-                                               break;          /* needn't look at any more columns */
-                                       }
-                               }
-
-                               plst = lnext(plst);
-                               col++;
-                       }
-
-                       if (subLinkType == ANY_SUBLINK)
-                       {
-                               /* combine across rows per OR semantics */
-                               if (rownull)
-                                       *isNull = true;
-                               else if (DatumGetBool(rowresult))
-                               {
-                                       result = BoolGetDatum(true);
-                                       *isNull = false;
-                                       break;                  /* needn't look at any more rows */
-                               }
-                       }
-                       else if (subLinkType == ALL_SUBLINK)
-                       {
-                               /* combine across rows per AND semantics */
-                               if (rownull)
-                                       *isNull = true;
-                               else if (!DatumGetBool(rowresult))
-                               {
-                                       result = BoolGetDatum(false);
-                                       *isNull = false;
-                                       break;                  /* needn't look at any more rows */
-                               }
+                               result = BoolGetDatum(true);
+                               *isNull = false;
+                               break;                  /* needn't look at any more rows */
                        }
-                       else
+               }
+               else if (subLinkType == ALL_SUBLINK)
+               {
+                       /* combine across rows per AND semantics */
+                       if (rownull)
+                               *isNull = true;
+                       else if (!DatumGetBool(rowresult))
                        {
-                               /* must be MULTIEXPR_SUBLINK */
-                               result = rowresult;
-                               *isNull = rownull;
+                               result = BoolGetDatum(false);
+                               *isNull = false;
+                               break;                  /* needn't look at any more rows */
                        }
                }
+               else
+               {
+                       /* must be MULTIEXPR_SUBLINK */
+                       result = rowresult;
+                       *isNull = rownull;
+               }
        }
 
        if (!found)
@@ -524,7 +480,6 @@ static void
 buildSubPlanHash(SubPlanState *node)
 {
        SubPlan    *subplan = (SubPlan *) node->xprstate.expr;
-       bool            isExpr = subplan->isExpr;
        PlanState  *planstate = node->planstate;
        int                     ncols = length(node->exprs);
        ExprContext *innerecontext = node->innerecontext;
@@ -532,7 +487,6 @@ buildSubPlanHash(SubPlanState *node)
        MemoryContext oldcontext;
        int                     nbuckets;
        TupleTableSlot *slot;
-       TupleTableSlot *arrslot = NULL;
 
        Assert(subplan->subLinkType == ANY_SUBLINK);
        Assert(!subplan->useOr);
@@ -612,139 +566,43 @@ buildSubPlanHash(SubPlanState *node)
        {
                HeapTuple       tup = slot->val;
                TupleDesc       tdesc = slot->ttc_tupleDescriptor;
-               TupleDesc       arrtdesc = NULL;
+               int                     col = 1;
                List       *plst;
                bool            isnew;
-               int                     numelems;
-               int                     elemnum;
-               Datum           dvalue;
-               Datum      *dvalues = NULL;
-               bool            disnull;
 
                /*
-                * When isExpr is true, we have either a scalar expression or an
-                * array. In the former case, this is no different than the !isExpr
-                * case. In the latter case, iterate over the elements as if they
-                * were from multiple input tuples.
+                * Load up the Params representing the raw sub-select outputs,
+                * then form the projection tuple to store in the hashtable.
                 */
-               if (!isExpr)
-                       numelems = 1;
-               else
+               foreach(plst, subplan->paramIds)
                {
-                       Oid             expr_typeid = tdesc->attrs[0]->atttypid;
-
-                       if (expr_typeid != subplan->exprtype)
-                       {
-                               subplan->exprtype = expr_typeid;
-                               subplan->elemtype = get_element_type(expr_typeid);
-
-                               if (subplan->elemtype != InvalidOid)
-                                       get_typlenbyvalalign(subplan->elemtype,
-                                                                                &subplan->elmlen,
-                                                                                &subplan->elmbyval,
-                                                                                &subplan->elmalign);
-                       }
-
-                       /* get current value */
-                       dvalue = heap_getattr(tup, 1, tdesc, &disnull);
-
-                       if (subplan->elemtype != InvalidOid)
-                       {
-                               TupleTable      tupleTable;
-                               ArrayType   *v = DatumGetArrayTypeP(dvalue);
-
-                               arrtdesc = CreateTemplateTupleDesc(1, false);
-                               TupleDescInitEntry(arrtdesc, 1, "elem", subplan->elemtype,
-                                                                                                                       -1, 0, false);
-
-                               tupleTable = ExecCreateTupleTable(1);
-                               arrslot = ExecAllocTableSlot(tupleTable);
-                               ExecSetSlotDescriptor(arrslot, arrtdesc, true);
-
-                               /* XXX this will need work if/when arrays support NULL elements */
-                               if (!disnull)
-                               {
-                                       deconstruct_array(v, subplan->elemtype, subplan->elmlen,
-                                                                         subplan->elmbyval, subplan->elmalign,
-                                                                         &dvalues, &numelems);
-                               }
-                               else
-                               {
-                                       numelems = 1;
-                                       dvalues = (Datum *) palloc(numelems * sizeof(Datum));
-                                       dvalues[0] = (Datum) 0;
-                               }
-                       }
-                       else
-                       {
-                               numelems = 1;
-                               dvalues = (Datum *) palloc(numelems * sizeof(Datum));
-                               dvalues[0] = dvalue;
-                       }
-
+                       int                     paramid = lfirsti(plst);
+                       ParamExecData *prmdata;
+
+                       prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]);
+                       Assert(prmdata->execPlan == NULL);
+                       prmdata->value = heap_getattr(tup, col, tdesc,
+                                                                                 &(prmdata->isnull));
+                       col++;
                }
+               slot = ExecProject(node->projRight, NULL);
+               tup = slot->val;
 
-               for (elemnum = 0; elemnum < numelems; elemnum++)
+               /*
+                * If result contains any nulls, store separately or not at all.
+                * (Since we know the projection tuple has no junk columns, we
+                * can just look at the overall hasnull info bit, instead of
+                * groveling through the columns.)
+                */
+               if (HeapTupleNoNulls(tup))
                {
-                       int     col = 1;
-
-                       if (!isExpr || subplan->elemtype == InvalidOid)
-                       {
-                               /*
-                                * Load up the Params representing the raw sub-select outputs,
-                                * then form the projection tuple to store in the hashtable.
-                                */
-                               foreach(plst, subplan->paramIds)
-                               {
-                                       int                     paramid = lfirsti(plst);
-                                       ParamExecData *prmdata;
-
-                                       prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]);
-                                       Assert(prmdata->execPlan == NULL);
-
-                                       prmdata->value = heap_getattr(tup, col, tdesc,
-                                                                                                 &(prmdata->isnull));
-
-                                       col++;
-                               }
-                               slot = ExecProject(node->projRight, NULL);
-                               tup = slot->val;
-                       }
-                       else
-                       {
-                               /*
-                                * For array type expressions, we need to build up our own
-                                * tuple and slot
-                                */
-                               char            nullflag;
-
-                               nullflag = disnull ? 'n' : ' ';
-                               tup = heap_formtuple(arrtdesc, &dvalues[elemnum], &nullflag);
-                               arrslot = ExecStoreTuple(tup, arrslot, InvalidBuffer, true);
-                       }
-
-                       /*
-                        * If result contains any nulls, store separately or not at all.
-                        * (Since we know the projection tuple has no junk columns, we
-                        * can just look at the overall hasnull info bit, instead of
-                        * groveling through the columns.)
-                        */
-                       if (HeapTupleNoNulls(tup))
-                       {
-                               if (!isExpr)
-                                       (void) LookupTupleHashEntry(node->hashtable, slot, &isnew);
-                               else
-                                       (void) LookupTupleHashEntry(node->hashtable, arrslot, &isnew);
-                               node->havehashrows = true;
-                       }
-                       else if (node->hashnulls)
-                       {
-                               if (!isExpr)
-                                       (void) LookupTupleHashEntry(node->hashnulls, slot, &isnew);
-                               else
-                                       (void) LookupTupleHashEntry(node->hashnulls, arrslot, &isnew);
-                               node->havenullrows = true;
-                       }
+                       (void) LookupTupleHashEntry(node->hashtable, slot, &isnew);
+                       node->havehashrows = true;
+               }
+               else if (node->hashnulls)
+               {
+                       (void) LookupTupleHashEntry(node->hashnulls, slot, &isnew);
+                       node->havenullrows = true;
                }
 
                /*
@@ -761,8 +619,6 @@ buildSubPlanHash(SubPlanState *node)
         * have the potential for a double free attempt.
         */
        ExecClearTuple(node->projRight->pi_slot);
-       if (arrslot)
-               ExecClearTuple(arrslot);
 
        MemoryContextSwitchTo(oldcontext);
 }
@@ -1243,3 +1099,101 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
                parent->chgParam = bms_add_member(parent->chgParam, paramid);
        }
 }
+
+/*
+ * accumArrayResult - accumulate one (more) Datum for an ARRAY_SUBLINK
+ *
+ *     astate is working state (NULL on first call)
+ *     rcontext is where to keep working state
+ */
+static ArrayBuildState *
+accumArrayResult(ArrayBuildState *astate,
+                                Datum dvalue, bool disnull,
+                                Oid element_type,
+                                MemoryContext rcontext)
+{
+       MemoryContext arr_context,
+                                 oldcontext;
+
+       if (astate == NULL)
+       {
+               /* First time through --- initialize */
+
+               /* Make a temporary context to hold all the junk */
+               arr_context = AllocSetContextCreate(rcontext,
+                                                                                       "ARRAY_SUBLINK Result",
+                                                                                       ALLOCSET_DEFAULT_MINSIZE,
+                                                                                       ALLOCSET_DEFAULT_INITSIZE,
+                                                                                       ALLOCSET_DEFAULT_MAXSIZE);
+               oldcontext = MemoryContextSwitchTo(arr_context);
+               astate = (ArrayBuildState *) palloc(sizeof(ArrayBuildState));
+               astate->mcontext = arr_context;
+               astate->dvalues = (Datum *)
+                       palloc(ARRAY_ELEMS_CHUNKSIZE * sizeof(Datum));
+               astate->nelems = 0;
+               astate->element_type = element_type;
+               get_typlenbyvalalign(element_type,
+                                                        &astate->typlen,
+                                                        &astate->typbyval,
+                                                        &astate->typalign);
+       }
+       else
+       {
+               oldcontext = MemoryContextSwitchTo(astate->mcontext);
+               Assert(astate->element_type == element_type);
+               /* enlarge dvalues[] if needed */
+               if ((astate->nelems % ARRAY_ELEMS_CHUNKSIZE) == 0)
+                       astate->dvalues = (Datum *)
+                               repalloc(astate->dvalues,
+                                                (astate->nelems + ARRAY_ELEMS_CHUNKSIZE) * sizeof(Datum));
+       }
+
+       if (disnull)
+               elog(ERROR, "NULL elements not allowed in Arrays");
+
+       /* Use datumCopy to ensure pass-by-ref stuff is copied into mcontext */
+       astate->dvalues[astate->nelems++] =
+               datumCopy(dvalue, astate->typbyval, astate->typlen);
+
+       MemoryContextSwitchTo(oldcontext);
+
+       return astate;
+}
+
+/*
+ * makeArrayResult - produce final result of ARRAY_SUBLINK
+ *
+ *     astate is working state (not NULL)
+ *     rcontext is where to construct result
+ */
+static Datum
+makeArrayResult(ArrayBuildState *astate,
+                               MemoryContext rcontext)
+{
+       ArrayType  *result;
+       int                     dims[1];
+       int                     lbs[1];
+       MemoryContext oldcontext;
+
+       /* Build the final array result in rcontext */
+       oldcontext = MemoryContextSwitchTo(rcontext);
+
+       dims[0] = astate->nelems;
+       lbs[0] = 1;
+
+       result = construct_md_array(astate->dvalues,
+                                                               1,
+                                                               dims,
+                                                               lbs,
+                                                               astate->element_type,
+                                                               astate->typlen,
+                                                               astate->typbyval,
+                                                               astate->typalign);
+
+       MemoryContextSwitchTo(oldcontext);
+
+       /* Clean up all the junk */
+       MemoryContextDelete(astate->mcontext);
+
+       return PointerGetDatum(result);
+}
index 0cd199656c029ff44882db3e6dc4b6f5311aa04d..8f81f1953c7dc786eba9c5bddd172b9edd6e6aed 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.255 2003/06/25 04:19:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.256 2003/06/25 21:30:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -728,7 +728,6 @@ _copyAggref(Aggref *from)
        COPY_SCALAR_FIELD(agglevelsup);
        COPY_SCALAR_FIELD(aggstar);
        COPY_SCALAR_FIELD(aggdistinct);
-       COPY_NODE_FIELD(args);
 
        return newnode;
 }
@@ -827,7 +826,6 @@ _copySubLink(SubLink *from)
 
        COPY_SCALAR_FIELD(subLinkType);
        COPY_SCALAR_FIELD(useOr);
-       COPY_SCALAR_FIELD(isExpr);
        COPY_NODE_FIELD(lefthand);
        COPY_NODE_FIELD(operName);
        COPY_OIDLIST_FIELD(operOids);
@@ -846,12 +844,6 @@ _copySubPlan(SubPlan *from)
 
        COPY_SCALAR_FIELD(subLinkType);
        COPY_SCALAR_FIELD(useOr);
-       COPY_SCALAR_FIELD(isExpr);
-       COPY_SCALAR_FIELD(exprtype);
-       COPY_SCALAR_FIELD(elemtype);
-       COPY_SCALAR_FIELD(elmlen);
-       COPY_SCALAR_FIELD(elmbyval);
-       COPY_SCALAR_FIELD(elmalign);
        COPY_NODE_FIELD(exprs);
        COPY_INTLIST_FIELD(paramIds);
        COPY_NODE_FIELD(plan);
index 93f63c586c662b7c317c76efbdfa6b2ac8ff2a30..a56b01429e001b6e56f3a4736f1a84b4b77242d2 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.198 2003/06/25 04:19:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.199 2003/06/25 21:30:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -205,7 +205,6 @@ _equalAggref(Aggref *a, Aggref *b)
        COMPARE_SCALAR_FIELD(agglevelsup);
        COMPARE_SCALAR_FIELD(aggstar);
        COMPARE_SCALAR_FIELD(aggdistinct);
-       COMPARE_NODE_FIELD(args);
 
        return true;
 }
@@ -302,7 +301,6 @@ _equalSubLink(SubLink *a, SubLink *b)
 {
        COMPARE_SCALAR_FIELD(subLinkType);
        COMPARE_SCALAR_FIELD(useOr);
-       COMPARE_SCALAR_FIELD(isExpr);
        COMPARE_NODE_FIELD(lefthand);
        COMPARE_NODE_FIELD(operName);
        COMPARE_OIDLIST_FIELD(operOids);
@@ -316,12 +314,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
 {
        COMPARE_SCALAR_FIELD(subLinkType);
        COMPARE_SCALAR_FIELD(useOr);
-       COMPARE_SCALAR_FIELD(isExpr);
-       COMPARE_SCALAR_FIELD(exprtype);
-       COMPARE_SCALAR_FIELD(elemtype);
-       COMPARE_SCALAR_FIELD(elmlen);
-       COMPARE_SCALAR_FIELD(elmbyval);
-       COMPARE_SCALAR_FIELD(elmalign);
        COMPARE_NODE_FIELD(exprs);
        COMPARE_INTLIST_FIELD(paramIds);
        /* should compare plans, but have to settle for comparing plan IDs */
index cbd5784f563e92ba8c16c0aea00fb8ccb0f1cd8a..e2b8cb789d95f1320e9cb7c5933bd1acf1558beb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.209 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.210 2003/06/25 21:30:29 momjian Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -616,7 +616,6 @@ _outAggref(StringInfo str, Aggref *node)
        WRITE_UINT_FIELD(agglevelsup);
        WRITE_BOOL_FIELD(aggstar);
        WRITE_BOOL_FIELD(aggdistinct);
-       WRITE_NODE_FIELD(args);
 }
 
 static void
@@ -702,7 +701,6 @@ _outSubLink(StringInfo str, SubLink *node)
 
        WRITE_ENUM_FIELD(subLinkType, SubLinkType);
        WRITE_BOOL_FIELD(useOr);
-       WRITE_BOOL_FIELD(isExpr);
        WRITE_NODE_FIELD(lefthand);
        WRITE_NODE_FIELD(operName);
        WRITE_OIDLIST_FIELD(operOids);
@@ -716,12 +714,6 @@ _outSubPlan(StringInfo str, SubPlan *node)
 
        WRITE_ENUM_FIELD(subLinkType, SubLinkType);
        WRITE_BOOL_FIELD(useOr);
-       WRITE_BOOL_FIELD(isExpr);
-       WRITE_OID_FIELD(exprtype);
-       WRITE_OID_FIELD(elemtype);
-       WRITE_INT_FIELD(elmlen);
-       WRITE_BOOL_FIELD(elmbyval);
-       WRITE_CHAR_FIELD(elmalign);
        WRITE_NODE_FIELD(exprs);
        WRITE_INTLIST_FIELD(paramIds);
        WRITE_NODE_FIELD(plan);
index a661f9e8ad1776bf9d99ad7a3d0b6f2cef533bd1..1d2db3b37a9d3672e0bd16a3d0f68d07df9ad44b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.155 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.156 2003/06/25 21:30:30 momjian Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -416,7 +416,6 @@ _readAggref(void)
        READ_UINT_FIELD(agglevelsup);
        READ_BOOL_FIELD(aggstar);
        READ_BOOL_FIELD(aggdistinct);
-       READ_NODE_FIELD(args);
 
        READ_DONE();
 }
@@ -546,7 +545,6 @@ _readSubLink(void)
 
        READ_ENUM_FIELD(subLinkType, SubLinkType);
        READ_BOOL_FIELD(useOr);
-       READ_BOOL_FIELD(isExpr);
        READ_NODE_FIELD(lefthand);
        READ_NODE_FIELD(operName);
        READ_OIDLIST_FIELD(operOids);
index 138e7d80638ce1d80c7bfaa2ac5fb5d96fc931d8..aee5f4a1a145ef4ddcf4a18d87babece8a6b1ec6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.77 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.78 2003/06/25 21:30:30 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,7 +83,7 @@ typedef struct finalize_primnode_context
 
 static List *convert_sublink_opers(List *lefthand, List *operOids,
                                                                   List *targetlist, int rtindex,
-                                                                  bool isExpr, List **righthandIds);
+                                                                  List **righthandIds);
 static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
 static Node *replace_correlation_vars_mutator(Node *node, void *context);
 static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
@@ -299,12 +299,6 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
         */
        node->subLinkType = slink->subLinkType;
        node->useOr = slink->useOr;
-       node->isExpr = slink->isExpr;
-       node->exprtype = InvalidOid;
-       node->elemtype = InvalidOid;
-       node->elmlen = 0;
-       node->elmbyval = false;
-       node->elmalign = '\0';
        node->exprs = NIL;
        node->paramIds = NIL;
        node->useHashTable = false;
@@ -380,7 +374,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
                exprs = convert_sublink_opers(lefthand,
                                                                          slink->operOids,
                                                                          plan->targetlist,
-                                                                         0, node->isExpr,
+                                                                         0,
                                                                          &node->paramIds);
                node->setParam = listCopy(node->paramIds);
                PlannerInitPlan = lappend(PlannerInitPlan, node);
@@ -463,7 +457,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
                node->exprs = convert_sublink_opers(lefthand,
                                                                                        slink->operOids,
                                                                                        plan->targetlist,
-                                                                                       0, node->isExpr,
+                                                                                       0,
                                                                                        &node->paramIds);
 
                /*
@@ -505,7 +499,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
 static List *
 convert_sublink_opers(List *lefthand, List *operOids,
                                          List *targetlist, int rtindex,
-                                         bool isExpr, List **righthandIds)
+                                         List **righthandIds)
 {
        List       *result = NIL;
        List       *lst;
@@ -560,38 +554,13 @@ convert_sublink_opers(List *lefthand, List *operOids,
                 * are not expecting to have to resolve unknown Params, so
                 * it's okay to pass a null pstate.)
                 */
-               if (!isExpr)
-               {
-                       result = lappend(result,
-                                                        make_op_expr(NULL,
-                                                                                 tup,
-                                                                                 leftop,
-                                                                                 rightop,
-                                                                                 exprType(leftop),
-                                                                                 te->resdom->restype));
-               }
-               else
-               {
-                       Oid             exprtype = te->resdom->restype;
-                       Oid             elemtype = get_element_type(exprtype);
-
-                       if (elemtype != InvalidOid)
-                               result = lappend(result,
-                                                                make_op_expr(NULL,
-                                                                                         tup,
-                                                                                         leftop,
-                                                                                         rightop,
-                                                                                         exprType(leftop),
-                                                                                         elemtype));
-                       else
-                               result = lappend(result,
-                                                                make_op_expr(NULL,
-                                                                                         tup,
-                                                                                         leftop,
-                                                                                         rightop,
-                                                                                         exprType(leftop),
-                                                                                         exprtype));
-               }
+               result = lappend(result,
+                                                make_op_expr(NULL,
+                                                                         tup,
+                                                                         leftop,
+                                                                         rightop,
+                                                                         exprType(leftop),
+                                                                         te->resdom->restype));
 
                ReleaseSysCache(tup);
 
@@ -702,17 +671,13 @@ convert_IN_to_join(Query *parse, SubLink *sublink)
        /*
         * The sublink type must be "= ANY" --- that is, an IN operator.
         * (We require the operator name to be unqualified, which may be
-        * overly paranoid, or may not be.) It must not be an Expression
-        * sublink.
+        * overly paranoid, or may not be.)
         */
        if (sublink->subLinkType != ANY_SUBLINK)
                return NULL;
        if (length(sublink->operName) != 1 ||
                strcmp(strVal(lfirst(sublink->operName)), "=") != 0)
                return NULL;
-       if (sublink->isExpr)
-               return NULL;
-
        /*
         * The sub-select must not refer to any Vars of the parent query.
         * (Vars of higher levels should be okay, though.)
@@ -765,7 +730,7 @@ convert_IN_to_join(Query *parse, SubLink *sublink)
        exprs = convert_sublink_opers(sublink->lefthand,
                                                                  sublink->operOids,
                                                                  subselect->targetList,
-                                                                 rtindex, sublink->isExpr,
+                                                                 rtindex,
                                                                  &ininfo->sub_targetlist);
        return (Node *) make_ands_explicit(exprs);
 }
index 6b5014f90e1b630d693000dabe1cb3bb29bdfa0d..8b04066133c6eb7a86db4dad1ab613caac4d10ab 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.140 2003/06/24 23:14:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.141 2003/06/25 21:30:30 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -132,28 +132,6 @@ get_rightop(Expr *clause)
                return NULL;
 }
 
-/*****************************************************************************
- *              FUNCTION clause functions
- *****************************************************************************/
-
-/*
- * make_funcclause
- *             Creates a function clause given its function info and argument list.
- */
-Expr *
-make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset,
-                                                       CoercionForm funcformat, List *funcargs)
-{
-       FuncExpr   *expr = makeNode(FuncExpr);
-
-       expr->funcid = funcid;
-       expr->funcresulttype = funcresulttype;
-       expr->funcretset = funcretset;
-       expr->funcformat = funcformat;
-       expr->args = funcargs;
-       return (Expr *) expr;
-}
-
 /*****************************************************************************
  *             NOT clause functions
  *****************************************************************************/
index ed409c917155cdee97c8aee075ea803399e7262b..b24e00b9a54ffb9364e85427851a3adf444641c5 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.420 2003/06/25 04:19:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.421 2003/06/25 21:30:30 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -5505,7 +5505,6 @@ r_expr:  row IN_P select_with_parens
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = ANY_SUBLINK;
-                                       n->isExpr = false;
                                        n->lefthand = $1;
                                        n->operName = makeList1(makeString("="));
                                        n->subselect = $3;
@@ -5516,7 +5515,6 @@ r_expr:  row IN_P select_with_parens
                                        /* Make an IN node */
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = ANY_SUBLINK;
-                                       n->isExpr = false;
                                        n->lefthand = $1;
                                        n->operName = makeList1(makeString("="));
                                        n->subselect = $4;
@@ -5528,7 +5526,6 @@ r_expr:  row IN_P select_with_parens
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = $3;
-                                       n->isExpr = false;
                                        n->lefthand = $1;
                                        n->operName = $2;
                                        n->subselect = $4;
@@ -5539,7 +5536,6 @@ r_expr:  row IN_P select_with_parens
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = MULTIEXPR_SUBLINK;
-                                       n->isExpr = false;
                                        n->lefthand = $1;
                                        n->operName = $2;
                                        n->subselect = $3;
@@ -5923,7 +5919,6 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                        {
                                                        SubLink *n = (SubLink *)$3;
                                                        n->subLinkType = ANY_SUBLINK;
-                                                       n->isExpr = false;
                                                        n->lefthand = makeList1($1);
                                                        n->operName = makeList1(makeString("="));
                                                        $$ = (Node *)n;
@@ -5951,7 +5946,6 @@ a_expr:           c_expr                                                                  { $$ = $1; }
                                        {
                                                /* Make an IN node */
                                                SubLink *n = (SubLink *)$4;
-                                               n->isExpr = false;
                                                n->subLinkType = ANY_SUBLINK;
                                                n->lefthand = makeList1($1);
                                                n->operName = makeList1(makeString("="));
@@ -5978,38 +5972,11 @@ a_expr:         c_expr                                                                  { $$ = $1; }
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = $3;
-                                       n->isExpr = false;
                                        n->lefthand = makeList1($1);
                                        n->operName = $2;
                                        n->subselect = $4;
                                        $$ = (Node *)n;
                                }
-                       | a_expr qual_all_Op sub_type '(' a_expr ')' %prec Op
-                               {
-                                       SubLink *n = makeNode(SubLink);
-                                       SelectStmt *s = makeNode(SelectStmt);
-                                       ResTarget *r = makeNode(ResTarget);
-
-                                       r->name = NULL;
-                                       r->indirection = NIL;
-                                       r->val = (Node *)$5;
-
-                                       s->distinctClause = NIL;
-                                       s->targetList = makeList1(r);
-                                       s->into = NULL;
-                                       s->intoColNames = NIL;
-                                       s->fromClause = NIL;
-                                       s->whereClause = NULL;
-                                       s->groupClause = NIL;
-                                       s->havingClause = NULL;
-
-                                       n->subLinkType = $3;
-                                       n->isExpr = true;
-                                       n->lefthand = makeList1($1);
-                                       n->operName = $2;
-                                       n->subselect = (Node *) s;
-                                       $$ = (Node *)n;
-                               }
                        | UNIQUE select_with_parens %prec Op
                                {
                                        /* Not sure how to get rid of the parentheses
@@ -6586,7 +6553,6 @@ c_expr:           columnref                                                               { $$ = (Node *) $1; }
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = EXPR_SUBLINK;
-                                       n->isExpr = false;
                                        n->lefthand = NIL;
                                        n->operName = NIL;
                                        n->subselect = $1;
@@ -6596,7 +6562,6 @@ c_expr:           columnref                                                               { $$ = (Node *) $1; }
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = EXISTS_SUBLINK;
-                                       n->isExpr = false;
                                        n->lefthand = NIL;
                                        n->operName = NIL;
                                        n->subselect = $2;
@@ -6606,7 +6571,6 @@ c_expr:           columnref                                                               { $$ = (Node *) $1; }
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->subLinkType = ARRAY_SUBLINK;
-                                       n->isExpr = false;
                                        n->lefthand = NIL;
                                        n->operName = NIL;
                                        n->subselect = $2;
@@ -6781,7 +6745,6 @@ trim_list:        a_expr FROM expr_list                                   { $$ = lappend($3, $1); }
 in_expr:       select_with_parens
                                {
                                        SubLink *n = makeNode(SubLink);
-                                       n->isExpr = false;
                                        n->subselect = $1;
                                        /* other fields will be filled later */
                                        $$ = (Node *)n;
index 7fd831ca91648c694b07b34f746937f2ee4ee2ec..987d129027fc68602685a7774270b80ff38ce578 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.99 2003/06/25 04:32:03 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.100 2003/06/25 21:30:31 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -859,11 +859,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
        /* Get the element type based on the array type, if we have one */
        if (OidIsValid(array_typeid))
        {
-               if (array_typeid != ANYARRAYOID)
-                       array_typelem = get_element_type(array_typeid);
-               else
-                       array_typelem = ANYELEMENTOID;
-
+               array_typelem = get_element_type(array_typeid);
                if (!OidIsValid(array_typelem))
                        elog(ERROR, "Argument declared ANYARRAY is not an array: %s",
                                 format_type_be(array_typeid));
@@ -923,11 +919,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
        {
                if (!OidIsValid(array_typeid))
                {
-                       if (elem_typeid != ANYELEMENTOID)
-                               array_typeid = get_array_type(elem_typeid);
-                       else
-                               array_typeid = ANYARRAYOID;
-
+                       array_typeid = get_array_type(elem_typeid);
                        if (!OidIsValid(array_typeid))
                                elog(ERROR, "Cannot find array type for datatype %s",
                                         format_type_be(elem_typeid));
@@ -1178,11 +1170,6 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
        if (srctype == targettype)
                return true;
 
-       /* Last of the fast-paths: check for matching polymorphic arrays */
-       if (targettype == ANYARRAYOID)
-               if (get_element_type(srctype) != InvalidOid)
-                       return true;
-
        /* Else look in pg_cast */
        tuple = SearchSysCache(CASTSOURCETARGET,
                                                   ObjectIdGetDatum(srctype),
index 5234c22e4fbf8e15dee6a4e399c50bf7c4b524ab..1e655217103a0fe79e294c994940277315fc73b5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.149 2003/06/24 23:14:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.150 2003/06/25 21:30:31 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -436,7 +436,6 @@ transformExpr(ParseState *pstate, Node *expr)
                                        sublink->operName = NIL;
                                        sublink->operOids = NIL;
                                        sublink->useOr = FALSE;
-                                       sublink->isExpr = FALSE;
                                }
                                else if (sublink->subLinkType == EXPR_SUBLINK ||
                                                 sublink->subLinkType == ARRAY_SUBLINK)
@@ -464,7 +463,6 @@ transformExpr(ParseState *pstate, Node *expr)
                                        sublink->operName = NIL;
                                        sublink->operOids = NIL;
                                        sublink->useOr = FALSE;
-                                       sublink->isExpr = FALSE;
                                }
                                else
                                {
@@ -540,30 +538,10 @@ transformExpr(ParseState *pstate, Node *expr)
                                                 * here, because make_subplan() will insert type
                                                 * coercion calls if needed.
                                                 */
-                                               if (!sublink->isExpr)
-                                               {
-                                                       optup = oper(op,
-                                                                                exprType(lexpr),
-                                                                                exprType((Node *) tent->expr),
-                                                                                false);
-                                               }
-                                               else
-                                               {
-                                                       Oid             exprtype = exprType((Node *) tent->expr);
-                                                       Oid             elemtype = get_element_type(exprtype);
-
-                                                       if (elemtype != InvalidOid)
-                                                               optup = oper(op,
-                                                                                        exprType(lexpr),
-                                                                                        elemtype,
-                                                                                        false);
-                                                       else
-                                                               optup = oper(op,
-                                                                                        exprType(lexpr),
-                                                                                        exprtype,
-                                                                                        false);
-                                               }
-
+                                               optup = oper(op,
+                                                                        exprType(lexpr),
+                                                                        exprType((Node *) tent->expr),
+                                                                        false);
                                                opform = (Form_pg_operator) GETSTRUCT(optup);
 
                                                if (opform->oprresult != BOOLOID)
@@ -765,7 +743,7 @@ transformExpr(ParseState *pstate, Node *expr)
                                                ArrayExpr  *e = (ArrayExpr *) lfirst(element);
 
                                                if (!IsA(e, ArrayExpr))
-                                                       elog(ERROR, "Multidimensional ARRAY[] must be built from nested array expressions");
+                                                       elog(ERROR, "Multi-dimensional ARRAY[] must be built from nested array expressions");
                                                if (ndims == 0)
                                                        ndims = e->ndims;
                                                else if (e->ndims != ndims)
index 2b0e10e4ca1ff08680e6bd042508bd9d549f0ee6..806138a25a5201510dceb0911afc792a3361d734 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.151 2003/06/25 20:07:39 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.152 2003/06/25 21:30:31 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -336,7 +336,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
                aggref->target = lfirst(fargs);
                aggref->aggstar = agg_star;
                aggref->aggdistinct = agg_distinct;
-               aggref->args = fargs;
 
                /* parse_agg.c does additional aggregate-specific processing */
                transformAggregateCall(pstate, aggref);
index a6b66625be203e53ce2373e6b33131158664eed8..69edb4b85bd0ba144292070730dd7d44d3084141 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.65 2003/06/24 23:14:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.66 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -137,33 +137,6 @@ Operator
 equality_oper(Oid argtype, bool noError)
 {
        Operator        optup;
-       Oid                     elem_type = get_element_type(argtype);
-
-       if (OidIsValid(elem_type))
-       {
-               bool    found = false;
-               /*
-                * If the datatype is an array, look for an "=" operator for the
-                * element datatype.  We require it to be an exact or binary-compatible
-                * match, since most callers are not prepared to cope with adding any
-                * run-time type coercion steps.
-                */
-               optup = equality_oper(elem_type, true);
-               if (optup != NULL)
-               {
-                       found = true;
-                       ReleaseSysCache(optup);
-               }
-
-               if (!found)
-               {
-                       if (!noError)
-                               elog(ERROR, "Unable to identify an equality operator for " \
-                                                       "array type's element type %s",
-                                                        format_type_be(elem_type));
-                       return NULL;
-               }
-       }
 
        /*
         * Look for an "=" operator for the datatype.  We require it to be
@@ -202,33 +175,6 @@ Operator
 ordering_oper(Oid argtype, bool noError)
 {
        Operator        optup;
-       Oid                     elem_type = get_element_type(argtype);
-
-       if (OidIsValid(elem_type))
-       {
-               bool    found = false;
-               /*
-                * If the datatype is an array, find the array element type's equality
-                * operator, and use its lsortop (it *must* be mergejoinable).  We use
-                * this definition because for sorting and grouping purposes, it's
-                * important that the equality and ordering operators are consistent.
-                */
-               optup = ordering_oper(elem_type, true);
-               if (optup != NULL)
-               {
-                       found = true;
-                       ReleaseSysCache(optup);
-               }
-
-               if (!found)
-               {
-                       if (!noError)
-                               elog(ERROR, "Unable to identify an ordering operator for " \
-                                                       "array type's element type %s",
-                                                        format_type_be(elem_type));
-                       return NULL;
-               }
-       }
 
        /*
         * Find the type's equality operator, and use its lsortop (it *must*
@@ -274,21 +220,6 @@ equality_oper_funcid(Oid argtype)
        return result;
 }
 
-/*
- * ordering_oper_funcid - convenience routine for oprfuncid(ordering_oper())
- */
-Oid
-ordering_oper_funcid(Oid argtype)
-{
-       Operator        optup;
-       Oid                     result;
-
-       optup = ordering_oper(argtype, false);
-       result = oprfuncid(optup);
-       ReleaseSysCache(optup);
-       return result;
-}
-
 /*
  * ordering_oper_opid - convenience routine for oprid(ordering_oper())
  *
index cfef2db349d21c9b76fdaa5264e5a583b3297194..415a086b7dd180458322db64d97e18dbb422aa62 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.89 2003/06/24 23:14:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.90 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -427,15 +427,6 @@ aclitemeq(const AclItem *a1, const AclItem *a2)
                a1->ai_grantor == a2->ai_grantor;
 }
 
-/*
- * user-facing version of aclitemeq() for use as the
- * aclitem equality operator
- */
-Datum
-aclitem_eq(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_BOOL(aclitemeq(PG_GETARG_ACLITEM_P(0), PG_GETARG_ACLITEM_P(1)));
-}
 
 /*
  * acldefault()  --- create an ACL describing default access permissions
index f5e50771b1337aae7dab378367da51fd2696a05d..519ac8d1885a6e06de0cbfc36147107418771803 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.2 2003/06/24 23:14:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.3 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
+
+/*-----------------------------------------------------------------------------
+ * singleton_array :
+ *             Form a multi-dimensional array given one starting element.
+ *
+ * - first argument is the datum with which to build the array
+ * - second argument is the number of dimensions the array should have;
+ *     defaults to 1 if no second argument is provided
+ *----------------------------------------------------------------------------
+ */
+Datum
+singleton_array(PG_FUNCTION_ARGS)
+{
+       Oid                     elem_type = get_fn_expr_argtype(fcinfo, 0);
+       int                     ndims;
+
+       if (elem_type == InvalidOid)
+               elog(ERROR, "Cannot determine input datatype");
+
+       if (PG_NARGS() == 2)
+               ndims = PG_GETARG_INT32(1);
+       else
+               ndims = 1;
+
+       PG_RETURN_ARRAYTYPE_P(create_singleton_array(elem_type,
+                                                                                                PG_GETARG_DATUM(0),
+                                                                                                ndims));
+}
+
 /*-----------------------------------------------------------------------------
  * array_push :
  *             push an element onto either end of a one-dimensional array
@@ -41,7 +70,6 @@ array_push(PG_FUNCTION_ARGS)
        Oid                     arg1_typeid = get_fn_expr_argtype(fcinfo, 1);
        Oid                     arg0_elemid;
        Oid                     arg1_elemid;
-       ArrayMetaState *my_extra;
 
        if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid)
                elog(ERROR, "array_push: cannot determine input data types");
@@ -67,61 +95,28 @@ array_push(PG_FUNCTION_ARGS)
                PG_RETURN_NULL();               /* keep compiler quiet */
        }
 
-       if (ARR_NDIM(v) == 1)
-       {
-               lb = ARR_LBOUND(v);
-               dimv = ARR_DIMS(v);
-
-               if (arg0_elemid != InvalidOid)
-               {
-                       /* append newelem */
-                       int     ub = dimv[0] + lb[0] - 1;
-                       indx = ub + 1;
-               }
-               else
-               {
-                       /* prepend newelem */
-                       indx = lb[0] - 1;
-               }
-       }
-       else if (ARR_NDIM(v) == 0)
-               indx = 1;
-       else
-               elog(ERROR, "only empty and one-dimensional arrays are supported");
-
-
-       /*
-        * We arrange to look up info about element type only once per series
-        * of calls, assuming the element type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
+       /* Sanity check: do we have a one-dimensional array */
+       if (ARR_NDIM(v) != 1)
+               elog(ERROR, "Arrays greater than one-dimension are not supported");
 
-       if (my_extra->element_type != element_type)
+       lb = ARR_LBOUND(v);
+       dimv = ARR_DIMS(v);
+       if (arg0_elemid != InvalidOid)
        {
-               /* Get info about element type */
-               get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typalign = typalign;
+               /* append newelem */
+               int     ub = dimv[0] + lb[0] - 1;
+               indx = ub + 1;
        }
        else
        {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typalign = my_extra->typalign;
+               /* prepend newelem */
+               indx = lb[0] - 1;
        }
 
-       result = array_set(v, 1, &indx, newelem, -1, typlen, typbyval,
-                                                                                                typalign, &isNull);
+       get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
+
+       result = array_set(v, 1, &indx, newelem, -1,
+                                          typlen, typbyval, typalign, &isNull);
 
        PG_RETURN_ARRAYTYPE_P(result);
 }
@@ -150,28 +145,13 @@ array_cat(PG_FUNCTION_ARGS)
 
        /*
         * We must have one of the following combinations of inputs:
-        * 1) one empty array, and one non-empty array
-        * 2) both arrays empty
-        * 3) two arrays with ndims1 == ndims2
-        * 4) ndims1 == ndims2 - 1
-        * 5) ndims1 == ndims2 + 1
+        * 1) two arrays with ndims1 == ndims2
+        * 2) ndims1 == ndims2 - 1
+        * 3) ndims1 == ndims2 + 1
         */
        ndims1 = ARR_NDIM(v1);
        ndims2 = ARR_NDIM(v2);
 
-       /*
-        * short circuit - if one input array is empty, and the other is not,
-        * we return the non-empty one as the result
-        *
-        * if both are empty, return the first one
-        */
-       if (ndims1 == 0 && ndims2 > 0)
-               PG_RETURN_ARRAYTYPE_P(v2);
-
-       if (ndims2 == 0)
-               PG_RETURN_ARRAYTYPE_P(v1);
-
-       /* the rest fall into combo 2, 3, or 4 */
        if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1)
                elog(ERROR, "Cannot concatenate incompatible arrays of %d and "
                                        "%d dimensions", ndims1, ndims2);
@@ -286,15 +266,147 @@ array_cat(PG_FUNCTION_ARGS)
        PG_RETURN_ARRAYTYPE_P(result);
 }
 
+/*----------------------------------------------------------------------------
+ * array_accum :
+ *             accumulator to build a 1-D array from input values -- this can be used
+ *             to create custom aggregates.
+ *
+ * This function is not marked strict, so we have to be careful about nulls.
+ *----------------------------------------------------------------------------
+ */
+Datum
+array_accum(PG_FUNCTION_ARGS)
+{
+       /* return NULL if both arguments are NULL */
+       if (PG_ARGISNULL(0) && PG_ARGISNULL(1))
+               PG_RETURN_NULL();
+
+       /* create a new 1-D array from the new element if the array is NULL */
+       if (PG_ARGISNULL(0))
+       {
+               Oid                     tgt_type = get_fn_expr_rettype(fcinfo);
+               Oid                     tgt_elem_type;
+
+               if (tgt_type == InvalidOid)
+                       elog(ERROR, "Cannot determine target array type");
+               tgt_elem_type = get_element_type(tgt_type);
+               if (tgt_elem_type == InvalidOid)
+                       elog(ERROR, "Target type is not an array");
+
+               PG_RETURN_ARRAYTYPE_P(create_singleton_array(tgt_elem_type,
+                                                                                                        PG_GETARG_DATUM(1),
+                                                                                                        1));
+       }
+
+       /* return the array if the new element is NULL */
+       if (PG_ARGISNULL(1))
+               PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P_COPY(0));
+
+       /*
+        * Otherwise this is equivalent to array_push.  We hack the call a little
+        * so that array_push can see the fn_expr information.
+        */
+       return array_push(fcinfo);
+}
+
+/*-----------------------------------------------------------------------------
+ * array_assign :
+ *             assign an element of an array to a new value and return the
+ *             redefined array
+ *----------------------------------------------------------------------------
+ */
+Datum
+array_assign(PG_FUNCTION_ARGS)
+{
+       ArrayType  *v;
+       int                     idx_to_chg;
+       Datum           newelem;
+       int                *dimv,
+                          *lb, ub;
+       ArrayType  *result;
+       bool            isNull;
+       Oid                     element_type;
+       int16           typlen;
+       bool            typbyval;
+       char            typalign;
+
+       v = PG_GETARG_ARRAYTYPE_P(0);
+       idx_to_chg = PG_GETARG_INT32(1);
+       newelem = PG_GETARG_DATUM(2);
+
+       /* Sanity check: do we have a one-dimensional array */
+       if (ARR_NDIM(v) != 1)
+               elog(ERROR, "Arrays greater than one-dimension are not supported");
+
+       lb = ARR_LBOUND(v);
+       dimv = ARR_DIMS(v);
+       ub = dimv[0] + lb[0] - 1;
+       if (idx_to_chg < lb[0] || idx_to_chg > ub)
+               elog(ERROR, "Cannot alter nonexistent array element: %d", idx_to_chg);
+
+       element_type = ARR_ELEMTYPE(v);
+       /* Sanity check: do we have a non-zero element type */
+       if (element_type == 0)
+               elog(ERROR, "Invalid array element type: %u", element_type);
+
+       get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
+
+       result = array_set(v, 1, &idx_to_chg, newelem, -1,
+                                          typlen, typbyval, typalign, &isNull);
+
+       PG_RETURN_ARRAYTYPE_P(result);
+}
+
+/*-----------------------------------------------------------------------------
+ * array_subscript :
+ *             return specific element of an array
+ *----------------------------------------------------------------------------
+ */
+Datum
+array_subscript(PG_FUNCTION_ARGS)
+{
+       ArrayType  *v;
+       int                     idx;
+       int                *dimv,
+                          *lb, ub;
+       Datum           result;
+       bool            isNull;
+       Oid                     element_type;
+       int16           typlen;
+       bool            typbyval;
+       char            typalign;
+
+       v = PG_GETARG_ARRAYTYPE_P(0);
+       idx = PG_GETARG_INT32(1);
+
+       /* Sanity check: do we have a one-dimensional array */
+       if (ARR_NDIM(v) != 1)
+               elog(ERROR, "Arrays greater than one-dimension are not supported");
+
+       lb = ARR_LBOUND(v);
+       dimv = ARR_DIMS(v);
+       ub = dimv[0] + lb[0] - 1;
+       if (idx < lb[0] || idx > ub)
+               elog(ERROR, "Cannot return nonexistent array element: %d", idx);
+
+       element_type = ARR_ELEMTYPE(v);
+       /* Sanity check: do we have a non-zero element type */
+       if (element_type == 0)
+               elog(ERROR, "Invalid array element type: %u", element_type);
+
+       get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
+
+       result = array_ref(v, 1, &idx, -1, typlen, typbyval, typalign, &isNull);
+
+       PG_RETURN_DATUM(result);
+}
 
 /*
- * used by text_to_array() in varlena.c
+ * actually does the work for singleton_array(), and array_accum() if it is
+ * given a null input array.
  */
 ArrayType *
-create_singleton_array(FunctionCallInfo fcinfo,
-                                          Oid element_type,
-                                          Datum element,
-                                          int ndims)
+create_singleton_array(Oid element_type, Datum element, int ndims)
 {
        Datum   dvalues[1];
        int16   typlen;
@@ -303,7 +415,6 @@ create_singleton_array(FunctionCallInfo fcinfo,
        int             dims[MAXDIM];
        int             lbs[MAXDIM];
        int             i;
-       ArrayMetaState *my_extra;
 
        if (element_type == 0)
                elog(ERROR, "Invalid array element type: %u", element_type);
@@ -318,35 +429,7 @@ create_singleton_array(FunctionCallInfo fcinfo,
                lbs[i] = 1;
        }
 
-       /*
-        * We arrange to look up info about element type only once per series
-        * of calls, assuming the element type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
-
-       if (my_extra->element_type != element_type)
-       {
-               /* Get info about element type */
-               get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typalign = typalign;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typalign = my_extra->typalign;
-       }
+       get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
 
        return construct_md_array(dvalues, ndims, dims, lbs, element_type,
                                                          typlen, typbyval, typalign);
index 27a805d9b28dd6e3af4456a4589113a3ddb75821..c03d8c861d13fb64c82ae4d762ed9efc84361121 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.90 2003/06/24 23:14:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.91 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "catalog/pg_type.h"
 #include "libpq/pqformat.h"
 #include "parser/parse_coerce.h"
-#include "parser/parse_oper.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
-#include "utils/datum.h"
 #include "utils/memutils.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
 #define RETURN_NULL(type)  do { *isNull = true; return (type) 0; } while (0)
 
+/* I/O function selector for system_cache_lookup */
+typedef enum IOFuncSelector
+{
+       IOFunc_input,
+       IOFunc_output,
+       IOFunc_receive,
+       IOFunc_send
+} IOFuncSelector;
+
+
 static int     ArrayCount(char *str, int *dim, char typdelim);
 static Datum *ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,
                         FmgrInfo *inputproc, Oid typelem, int32 typmod,
@@ -85,6 +93,10 @@ static Datum *ReadArrayBinary(StringInfo buf, int nitems,
 static void CopyArrayEls(char *p, Datum *values, int nitems,
                         int typlen, bool typbyval, char typalign,
                         bool freedata);
+static void system_cache_lookup(Oid element_type, IOFuncSelector which_func,
+                                                               int *typlen, bool *typbyval,
+                                                               char *typdelim, Oid *typelem,
+                                                               Oid *proc, char *typalign);
 static Datum ArrayCast(char *value, bool byval, int len);
 static int ArrayCastAndSet(Datum src,
                                int typlen, bool typbyval, char typalign,
@@ -107,7 +119,7 @@ static void array_insert_slice(int ndim, int *dim, int *lb,
                                   char *destPtr,
                                   int *st, int *endp, char *srcPtr,
                                   int typlen, bool typbyval, char typalign);
-static int array_cmp(FunctionCallInfo fcinfo);
+
 
 /*---------------------------------------------------------------------
  * array_in :
@@ -142,49 +154,12 @@ array_in(PG_FUNCTION_ARGS)
                                dim[MAXDIM],
                                lBound[MAXDIM];
        char            typalign;
-       ArrayMetaState *my_extra;
-
-       /*
-        * We arrange to look up info about element type, including its input
-        * conversion proc only once per series of calls, assuming the element
-        * type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
 
-       if (my_extra->element_type != element_type)
-       {
-               /* Get info about element type, including its input conversion proc */
-               get_type_metadata(element_type, IOFunc_input,
-                                                       &typlen, &typbyval, &typdelim,
-                                                       &typelem, &typinput, &typalign);
-               fmgr_info(typinput, &inputproc);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typdelim = typdelim;
-               my_extra->typelem = typelem;
-               my_extra->typiofunc = typinput;
-               my_extra->typalign = typalign;
-               my_extra->proc = inputproc;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typdelim = my_extra->typdelim;
-               typelem = my_extra->typelem;
-               typinput = my_extra->typiofunc;
-               typalign = my_extra->typalign;
-               inputproc = my_extra->proc;
-       }
+       /* Get info about element type, including its input conversion proc */
+       system_cache_lookup(element_type, IOFunc_input,
+                                               &typlen, &typbyval, &typdelim,
+                                               &typelem, &typinput, &typalign);
+       fmgr_info(typinput, &inputproc);
 
        /* Make a modifiable copy of the input */
        /* XXX why are we allocating an extra 2 bytes here? */
@@ -661,51 +636,12 @@ array_out(PG_FUNCTION_ARGS)
                                indx[MAXDIM];
        int                     ndim,
                           *dim;
-       ArrayMetaState *my_extra;
 
        element_type = ARR_ELEMTYPE(v);
-
-       /*
-        * We arrange to look up info about element type, including its input
-        * conversion proc only once per series of calls, assuming the element
-        * type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
-
-       if (my_extra->element_type != element_type)
-       {
-               /* Get info about element type, including its output conversion proc */
-               get_type_metadata(element_type, IOFunc_output,
-                                                       &typlen, &typbyval, &typdelim,
-                                                       &typelem, &typoutput, &typalign);
-               fmgr_info(typoutput, &outputproc);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typdelim = typdelim;
-               my_extra->typelem = typelem;
-               my_extra->typiofunc = typoutput;
-               my_extra->typalign = typalign;
-               my_extra->proc = outputproc;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typdelim = my_extra->typdelim;
-               typelem = my_extra->typelem;
-               typoutput = my_extra->typiofunc;
-               typalign = my_extra->typalign;
-               outputproc = my_extra->proc;
-       }
+       system_cache_lookup(element_type, IOFunc_output,
+                                               &typlen, &typbyval, &typdelim,
+                                               &typelem, &typoutput, &typalign);
+       fmgr_info(typoutput, &outputproc);
 
        ndim = ARR_NDIM(v);
        dim = ARR_DIMS(v);
@@ -864,7 +800,6 @@ array_recv(PG_FUNCTION_ARGS)
                                dim[MAXDIM],
                                lBound[MAXDIM];
        char            typalign;
-       ArrayMetaState *my_extra;
 
        /* Get the array header information */
        ndim = pq_getmsgint(buf, 4);
@@ -896,50 +831,14 @@ array_recv(PG_FUNCTION_ARGS)
                PG_RETURN_ARRAYTYPE_P(retval);
        }
 
-       /*
-        * We arrange to look up info about element type, including its receive
-        * conversion proc only once per series of calls, assuming the element
-        * type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
-
-       if (my_extra->element_type != element_type)
-       {
-               /* Get info about element type, including its receive conversion proc */
-               get_type_metadata(element_type, IOFunc_receive,
-                                                       &typlen, &typbyval, &typdelim,
-                                                       &typelem, &typreceive, &typalign);
-               if (!OidIsValid(typreceive))
-                       elog(ERROR, "No binary input function available for type %s",
-                                format_type_be(element_type));
-               fmgr_info(typreceive, &receiveproc);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typdelim = typdelim;
-               my_extra->typelem = typelem;
-               my_extra->typiofunc = typreceive;
-               my_extra->typalign = typalign;
-               my_extra->proc = receiveproc;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typdelim = my_extra->typdelim;
-               typelem = my_extra->typelem;
-               typreceive = my_extra->typiofunc;
-               typalign = my_extra->typalign;
-               receiveproc = my_extra->proc;
-       }
+       /* Get info about element type, including its receive conversion proc */
+       system_cache_lookup(element_type, IOFunc_receive,
+                                               &typlen, &typbyval, &typdelim,
+                                               &typelem, &typreceive, &typalign);
+       if (!OidIsValid(typreceive))
+               elog(ERROR, "No binary input function available for type %s",
+                        format_type_be(element_type));
+       fmgr_info(typreceive, &receiveproc);
 
        dataPtr = ReadArrayBinary(buf, nitems, &receiveproc, typelem,
                                                          typlen, typbyval, typalign,
@@ -1077,54 +976,15 @@ array_send(PG_FUNCTION_ARGS)
        int                     ndim,
                           *dim;
        StringInfoData buf;
-       ArrayMetaState *my_extra;
 
        /* Get information about the element type and the array dimensions */
        element_type = ARR_ELEMTYPE(v);
-
-       /*
-        * We arrange to look up info about element type, including its send
-        * proc only once per series of calls, assuming the element
-        * type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
-
-       if (my_extra->element_type != element_type)
-       {
-               /* Get info about element type, including its send proc */
-               get_type_metadata(element_type, IOFunc_send, &typlen, &typbyval,
-                                                       &typdelim, &typelem, &typsend, &typalign);
-               if (!OidIsValid(typsend))
-                       elog(ERROR, "No binary output function available for type %s",
-                                format_type_be(element_type));
-               fmgr_info(typsend, &sendproc);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typdelim = typdelim;
-               my_extra->typelem = typelem;
-               my_extra->typiofunc = typsend;
-               my_extra->typalign = typalign;
-               my_extra->proc = sendproc;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typdelim = my_extra->typdelim;
-               typelem = my_extra->typelem;
-               typsend = my_extra->typiofunc;
-               typalign = my_extra->typalign;
-               sendproc = my_extra->proc;
-       }
+       system_cache_lookup(element_type, IOFunc_send, &typlen, &typbyval,
+                                               &typdelim, &typelem, &typsend, &typalign);
+       if (!OidIsValid(typsend))
+               elog(ERROR, "No binary output function available for type %s",
+                        format_type_be(element_type));
+       fmgr_info(typsend, &sendproc);
 
        ndim = ARR_NDIM(v);
        dim = ARR_DIMS(v);
@@ -1616,26 +1476,6 @@ array_set(ArrayType *array,
        array = DatumGetArrayTypeP(PointerGetDatum(array));
 
        ndim = ARR_NDIM(array);
-
-       /*
-        * if number of dims is zero, i.e. an empty array, create an array
-        * with nSubscripts dimensions, and set the lower bounds to the supplied
-        * subscripts
-        */
-       if (ndim == 0)
-       {
-               Oid             elmtype = ARR_ELEMTYPE(array);
-
-               for (i = 0; i < nSubscripts; i++)
-               {
-                       dim[i] = 1;
-                       lb[i] = indx[i];
-               }
-
-               return construct_md_array(&dataValue, nSubscripts, dim, lb, elmtype,
-                                                                                               elmlen, elmbyval, elmalign);
-       }
-
        if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
                elog(ERROR, "Invalid array subscripts");
 
@@ -1792,31 +1632,6 @@ array_set_slice(ArrayType *array,
        /* note: we assume srcArray contains no toasted elements */
 
        ndim = ARR_NDIM(array);
-
-       /*
-        * if number of dims is zero, i.e. an empty array, create an array
-        * with nSubscripts dimensions, and set the upper and lower bounds
-        * to the supplied subscripts
-        */
-       if (ndim == 0)
-       {
-               Datum  *dvalues;
-               int             nelems;
-               Oid             elmtype = ARR_ELEMTYPE(array);
-
-               deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign,
-                                                                                                               &dvalues, &nelems);
-
-               for (i = 0; i < nSubscripts; i++)
-               {
-                       dim[i] = 1 + upperIndx[i] - lowerIndx[i];
-                       lb[i] = lowerIndx[i];
-               }
-
-               return construct_md_array(dvalues, nSubscripts, dim, lb, elmtype,
-                                                                                                elmlen, elmbyval, elmalign);
-       }
-
        if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
                elog(ERROR, "Invalid array subscripts");
 
@@ -1996,13 +1811,6 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
        Oid                     typelem;
        Oid                     proc;
        char       *s;
-       typedef struct {
-               ArrayMetaState *inp_extra;
-               ArrayMetaState *ret_extra;
-       } am_extra;
-       am_extra  *my_extra;
-       ArrayMetaState *inp_extra;
-       ArrayMetaState *ret_extra;
 
        /* Get input array */
        if (fcinfo->nargs < 1)
@@ -2021,81 +1829,11 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
        if (nitems <= 0)
                PG_RETURN_ARRAYTYPE_P(v);
 
-       /*
-        * We arrange to look up info about input and return element types only
-        * once per series of calls, assuming the element type doesn't change
-        * underneath us.
-        */
-       my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(am_extra));
-               my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
-
-               my_extra->inp_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               inp_extra = my_extra->inp_extra;
-               inp_extra->element_type = InvalidOid;
-
-               my_extra->ret_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               ret_extra = my_extra->ret_extra;
-               ret_extra->element_type = InvalidOid;
-       }
-       else
-       {
-               inp_extra = my_extra->inp_extra;
-               ret_extra = my_extra->ret_extra;
-       }
-
-       if (inp_extra->element_type != inpType)
-       {
-               /* Lookup source and result types. Unneeded variables are reused. */
-               get_type_metadata(inpType, IOFunc_input, &inp_typlen, &inp_typbyval,
-                                                       &typdelim, &typelem, &proc, &inp_typalign);
-
-               inp_extra->element_type = inpType;
-               inp_extra->typlen = inp_typlen;
-               inp_extra->typbyval = inp_typbyval;
-               inp_extra->typdelim = typdelim;
-               inp_extra->typelem = typelem;
-               inp_extra->typiofunc = proc;
-               inp_extra->typalign = inp_typalign;
-       }
-       else
-       {
-               inp_typlen = inp_extra->typlen;
-               inp_typbyval = inp_extra->typbyval;
-               typdelim = inp_extra->typdelim;
-               typelem = inp_extra->typelem;
-               proc = inp_extra->typiofunc;
-               inp_typalign = inp_extra->typalign;
-       }
-
-       if (ret_extra->element_type != retType)
-       {
-               /* Lookup source and result types. Unneeded variables are reused. */
-               get_type_metadata(retType, IOFunc_input, &typlen, &typbyval,
-                                                       &typdelim, &typelem, &proc, &typalign);
-
-               ret_extra->element_type = retType;
-               ret_extra->typlen = typlen;
-               ret_extra->typbyval = typbyval;
-               ret_extra->typdelim = typdelim;
-               ret_extra->typelem = typelem;
-               ret_extra->typiofunc = proc;
-               ret_extra->typalign = typalign;
-       }
-       else
-       {
-               typlen = ret_extra->typlen;
-               typbyval = ret_extra->typbyval;
-               typdelim = ret_extra->typdelim;
-               typelem = ret_extra->typelem;
-               proc = ret_extra->typiofunc;
-               typalign = ret_extra->typalign;
-       }
+       /* Lookup source and result types. Unneeded variables are reused. */
+       system_cache_lookup(inpType, IOFunc_input, &inp_typlen, &inp_typbyval,
+                                               &typdelim, &typelem, &proc, &inp_typalign);
+       system_cache_lookup(retType, IOFunc_input, &typlen, &typbyval,
+                                               &typdelim, &typelem, &proc, &typalign);
 
        /* Allocate temporary array for new values */
        values = (Datum *) palloc(nitems * sizeof(Datum));
@@ -2311,6 +2049,8 @@ deconstruct_array(ArrayType *array,
  *               compares two arrays for equality
  * result :
  *               returns true if the arrays are equal, false otherwise.
+ *
+ * XXX bitwise equality is pretty bogus ...
  *-----------------------------------------------------------------------------
  */
 Datum
@@ -2318,118 +2058,12 @@ array_eq(PG_FUNCTION_ARGS)
 {
        ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
        ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
-       char       *p1 = (char *) ARR_DATA_PTR(array1);
-       char       *p2 = (char *) ARR_DATA_PTR(array2);
-       int                     ndims1 = ARR_NDIM(array1);
-       int                     ndims2 = ARR_NDIM(array2);
-       int                *dims1 = ARR_DIMS(array1);
-       int                *dims2 = ARR_DIMS(array2);
-       int                     nitems1 = ArrayGetNItems(ndims1, dims1);
-       int                     nitems2 = ArrayGetNItems(ndims2, dims2);
-       Oid                     element_type = ARR_ELEMTYPE(array1);
-       FmgrInfo   *ae_fmgr_info = fcinfo->flinfo;
        bool            result = true;
-       int                     typlen;
-       bool            typbyval;
-       char            typdelim;
-       Oid                     typelem;
-       char            typalign;
-       Oid                     typiofunc;
-       int                     i;
-       ArrayMetaState *my_extra;
-       FunctionCallInfoData locfcinfo;
 
-       /* fast path if the arrays do not have the same number of elements */
-       if (nitems1 != nitems2)
+       if (ARR_SIZE(array1) != ARR_SIZE(array2))
+               result = false;
+       else if (memcmp(array1, array2, ARR_SIZE(array1)) != 0)
                result = false;
-       else
-       {
-               /*
-                * We arrange to look up the equality function only once per series of
-                * calls, assuming the element type doesn't change underneath us.
-                */
-               my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra;
-               if (my_extra == NULL)
-               {
-                       ae_fmgr_info->fn_extra = MemoryContextAlloc(ae_fmgr_info->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-                       my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra;
-                       my_extra->element_type = InvalidOid;
-               }
-
-               if (my_extra->element_type != element_type)
-               {
-                       Oid             opfuncid = equality_oper_funcid(element_type);
-
-                       if (OidIsValid(opfuncid))
-                               fmgr_info_cxt(opfuncid, &my_extra->proc, ae_fmgr_info->fn_mcxt);
-                       else
-                               elog(ERROR,
-                                        "array_eq: cannot find equality operator for type: %u",
-                                        element_type);
-
-                       get_type_metadata(element_type, IOFunc_output,
-                                                         &typlen, &typbyval, &typdelim,
-                                                         &typelem, &typiofunc, &typalign);
-                       
-                       my_extra->element_type = element_type;
-                       my_extra->typlen = typlen;
-                       my_extra->typbyval = typbyval;
-                       my_extra->typdelim = typdelim;
-                       my_extra->typelem = typelem;
-                       my_extra->typiofunc = typiofunc;
-                       my_extra->typalign = typalign;
-               }
-               else
-               {
-                       typlen = my_extra->typlen;
-                       typbyval = my_extra->typbyval;
-                       typdelim = my_extra->typdelim;
-                       typelem = my_extra->typelem;
-                       typiofunc = my_extra->typiofunc;
-                       typalign = my_extra->typalign;
-               }
-
-               /*
-                * apply the operator to each pair of array elements.
-                */
-               MemSet(&locfcinfo, 0, sizeof(locfcinfo));
-               locfcinfo.flinfo = &my_extra->proc;
-               locfcinfo.nargs = 2;
-
-               /* Loop over source data */
-               for (i = 0; i < nitems1; i++)
-               {
-                       Datum   elt1;
-                       Datum   elt2;
-                       bool    oprresult;
-
-                       /* Get element pair */
-                       elt1 = fetch_att(p1, typbyval, typlen);
-                       elt2 = fetch_att(p2, typbyval, typlen);
-
-                       p1 = att_addlength(p1, typlen, PointerGetDatum(p1));
-                       p1 = (char *) att_align(p1, typalign);
-
-                       p2 = att_addlength(p2, typlen, PointerGetDatum(p2));
-                       p2 = (char *) att_align(p2, typalign);
-
-                       /*
-                        * Apply the operator to the element pair
-                        */
-                       locfcinfo.arg[0] = elt1;
-                       locfcinfo.arg[1] = elt2;
-                       locfcinfo.argnull[0] = false;
-                       locfcinfo.argnull[1] = false;
-                       locfcinfo.isnull = false;
-                       oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
-                       if (!oprresult)
-                       {
-                               result = false;
-                               break;
-                       }
-               }
-       }
 
        /* Avoid leaking memory when handed toasted input. */
        PG_FREE_IF_COPY(array1, 0);
@@ -2439,190 +2073,53 @@ array_eq(PG_FUNCTION_ARGS)
 }
 
 
-/*-----------------------------------------------------------------------------
- * array-array bool operators:
- *             Given two arrays, iterate comparison operators
- *             over the array. Uses logic similar to text comparison
- *             functions, except element-by-element instead of
- *             character-by-character.
- *----------------------------------------------------------------------------
- */
-Datum
-array_ne(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_BOOL(!DatumGetBool(array_eq(fcinfo)));
-}
-
-Datum
-array_lt(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
-}
-
-Datum
-array_gt(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
-}
-
-Datum
-array_le(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
-}
-
-Datum
-array_ge(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
-}
-
-Datum
-btarraycmp(PG_FUNCTION_ARGS)
-{
-       PG_RETURN_INT32(array_cmp(fcinfo));
-}
-
-/*
- * array_cmp()
- * Internal comparison function for arrays.
- *
- * Returns -1, 0 or 1
- */
-static int
-array_cmp(FunctionCallInfo fcinfo)
-{
-       ArrayType  *array1 = PG_GETARG_ARRAYTYPE_P(0);
-       ArrayType  *array2 = PG_GETARG_ARRAYTYPE_P(1);
-       FmgrInfo   *ac_fmgr_info = fcinfo->flinfo;
-       Datum           opresult;
-       int                     result = 0;
-       Oid                     element_type = InvalidOid;
-       int                     typlen;
-       bool            typbyval;
-       char            typdelim;
-       Oid                     typelem;
-       char            typalign;
-       Oid                     typiofunc;
-       Datum      *dvalues1;
-       int                     nelems1;
-       Datum      *dvalues2;
-       int                     nelems2;
-       int                     min_nelems;
-       int                     i;
-       typedef struct
-       {
-               Oid                             element_type;
-               int                             typlen;
-               bool                    typbyval;
-               char                    typdelim;
-               Oid                             typelem;
-               Oid                             typiofunc;
-               char                    typalign;
-               FmgrInfo                eqproc;
-               FmgrInfo                ordproc;
-       } ac_extra;
-       ac_extra *my_extra;
-
-       element_type = ARR_ELEMTYPE(array1);
-
-       /*
-        * We arrange to look up the element type operator function only once
-        * per series of calls, assuming the element type and opname don't
-        * change underneath us.
-        */
-       my_extra = (ac_extra *) ac_fmgr_info->fn_extra;
-       if (my_extra == NULL)
-       {
-               ac_fmgr_info->fn_extra = MemoryContextAlloc(ac_fmgr_info->fn_mcxt,
-                                                                                                                sizeof(ac_extra));
-               my_extra = (ac_extra *) ac_fmgr_info->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
-
-       if (my_extra->element_type != element_type)
-       {
-               Oid             eqfuncid = equality_oper_funcid(element_type);
-               Oid             ordfuncid = ordering_oper_funcid(element_type);
-
-               fmgr_info_cxt(eqfuncid, &my_extra->eqproc, ac_fmgr_info->fn_mcxt);
-               fmgr_info_cxt(ordfuncid, &my_extra->ordproc, ac_fmgr_info->fn_mcxt);
-
-               if (my_extra->eqproc.fn_nargs != 2)
-                       elog(ERROR, "Equality operator does not take 2 arguments: %u",
-                                                                                                                                eqfuncid);
-               if (my_extra->ordproc.fn_nargs != 2)
-                       elog(ERROR, "Ordering operator does not take 2 arguments: %u",
-                                                                                                                                ordfuncid);
-
-               get_type_metadata(element_type, IOFunc_output,
-                                                 &typlen, &typbyval, &typdelim,
-                                                 &typelem, &typiofunc, &typalign);
-               
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typdelim = typdelim;
-               my_extra->typelem = typelem;
-               my_extra->typiofunc = InvalidOid;
-               my_extra->typalign = typalign;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typalign = my_extra->typalign;
-       }
-
-       /* extract a C array of arg array datums */
-       deconstruct_array(array1, element_type, typlen, typbyval, typalign,
-                                                                                                       &dvalues1, &nelems1);
-
-       deconstruct_array(array2, element_type, typlen, typbyval, typalign,
-                                                                                                       &dvalues2, &nelems2);
-
-       min_nelems = Min(nelems1, nelems2);
-       for (i = 0; i < min_nelems; i++)
-       {
-               /* are they equal */
-               opresult = FunctionCall2(&my_extra->eqproc,
-                                                                dvalues1[i], dvalues2[i]);
-
-               if (!DatumGetBool(opresult))
-               {
-                       /* nope, see if arg1 is less than arg2 */
-                       opresult = FunctionCall2(&my_extra->ordproc,
-                                                                        dvalues1[i], dvalues2[i]);
-                       if (DatumGetBool(opresult))
-                       {
-                               /* arg1 is less than arg2 */
-                               result = -1;
-                               break;
-                       }
-                       else
-                       {
-                               /* arg1 is greater than arg2 */
-                               result = 1;
-                               break;
-                       }
-               }
-       }
-
-       if ((result == 0) && (nelems1 != nelems2))
-               result = (nelems1 < nelems2) ? -1 : 1;
-
-       /* Avoid leaking memory when handed toasted input. */
-       PG_FREE_IF_COPY(array1, 0);
-       PG_FREE_IF_COPY(array2, 1);
-
-       return result;
-}
-
-
 /***************************************************************************/
 /******************|             Support  Routines                       |*****************/
 /***************************************************************************/
 
+static void
+system_cache_lookup(Oid element_type,
+                                       IOFuncSelector which_func,
+                                       int *typlen,
+                                       bool *typbyval,
+                                       char *typdelim,
+                                       Oid *typelem,
+                                       Oid *proc,
+                                       char *typalign)
+{
+       HeapTuple       typeTuple;
+       Form_pg_type typeStruct;
+
+       typeTuple = SearchSysCache(TYPEOID,
+                                                          ObjectIdGetDatum(element_type),
+                                                          0, 0, 0);
+       if (!HeapTupleIsValid(typeTuple))
+               elog(ERROR, "cache lookup failed for type %u", element_type);
+       typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
+
+       *typlen = typeStruct->typlen;
+       *typbyval = typeStruct->typbyval;
+       *typdelim = typeStruct->typdelim;
+       *typelem = typeStruct->typelem;
+       *typalign = typeStruct->typalign;
+       switch (which_func)
+       {
+               case IOFunc_input:
+                       *proc = typeStruct->typinput;
+                       break;
+               case IOFunc_output:
+                       *proc = typeStruct->typoutput;
+                       break;
+               case IOFunc_receive:
+                       *proc = typeStruct->typreceive;
+                       break;
+               case IOFunc_send:
+                       *proc = typeStruct->typsend;
+                       break;
+       }
+       ReleaseSysCache(typeTuple);
+}
+
 /*
  * Fetch array element at pointer, converted correctly to a Datum
  */
@@ -2926,18 +2423,6 @@ array_type_coerce(PG_FUNCTION_ARGS)
                if (tgt_elem_type == InvalidOid)
                        elog(ERROR, "Target type is not an array");
 
-               /*
-                * We don't deal with domain constraints yet, so bail out.
-                * This isn't currently a problem, because we also don't
-                * support arrays of domain type elements either. But in the
-                * future we might. At that point consideration should be given
-                * to removing the check below and adding a domain constraints
-                * check to the coercion.
-                */
-               if (getBaseType(tgt_elem_type) != tgt_elem_type)
-                       elog(ERROR, "array coercion to domain type elements not " \
-                                               "currently supported");
-
                if (!find_coercion_pathway(tgt_elem_type, src_elem_type,
                                                                   COERCION_EXPLICIT, &funcId))
                {
@@ -2954,16 +2439,10 @@ array_type_coerce(PG_FUNCTION_ARGS)
        }
 
        /*
-        * If it's binary-compatible, modify the element type in the array header,
-        * but otherwise leave the array as we received it.
+        * If it's binary-compatible, return the array unmodified.
         */
        if (my_extra->coerce_finfo.fn_oid == InvalidOid)
-       {
-               ArrayType  *result = DatumGetArrayTypePCopy(PG_GETARG_DATUM(0));
-               
-               ARR_ELEMTYPE(result) = my_extra->desttype;
-               PG_RETURN_ARRAYTYPE_P(result);
-       }
+               PG_RETURN_ARRAYTYPE_P(src);
 
        /*
         * Use array_map to apply the function to each array element.
@@ -2975,118 +2454,3 @@ array_type_coerce(PG_FUNCTION_ARGS)
 
        return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype);
 }
-
-/*
- * accumArrayResult - accumulate one (more) Datum for an ARRAY_SUBLINK
- *
- *     astate is working state (NULL on first call)
- *     rcontext is where to keep working state
- */
-ArrayBuildState *
-accumArrayResult(ArrayBuildState *astate,
-                                Datum dvalue, bool disnull,
-                                Oid element_type,
-                                MemoryContext rcontext)
-{
-       MemoryContext arr_context,
-                                 oldcontext;
-
-       if (astate == NULL)
-       {
-               /* First time through --- initialize */
-
-               /* Make a temporary context to hold all the junk */
-               arr_context = AllocSetContextCreate(rcontext,
-                                                                                       "accumArrayResult",
-                                                                                       ALLOCSET_DEFAULT_MINSIZE,
-                                                                                       ALLOCSET_DEFAULT_INITSIZE,
-                                                                                       ALLOCSET_DEFAULT_MAXSIZE);
-               oldcontext = MemoryContextSwitchTo(arr_context);
-               astate = (ArrayBuildState *) palloc(sizeof(ArrayBuildState));
-               astate->mcontext = arr_context;
-               astate->dvalues = (Datum *)
-                       palloc(ARRAY_ELEMS_CHUNKSIZE * sizeof(Datum));
-               astate->nelems = 0;
-               astate->element_type = element_type;
-               get_typlenbyvalalign(element_type,
-                                                        &astate->typlen,
-                                                        &astate->typbyval,
-                                                        &astate->typalign);
-       }
-       else
-       {
-               oldcontext = MemoryContextSwitchTo(astate->mcontext);
-               Assert(astate->element_type == element_type);
-               /* enlarge dvalues[] if needed */
-               if ((astate->nelems % ARRAY_ELEMS_CHUNKSIZE) == 0)
-                       astate->dvalues = (Datum *)
-                               repalloc(astate->dvalues,
-                                                (astate->nelems + ARRAY_ELEMS_CHUNKSIZE) * sizeof(Datum));
-       }
-
-       if (disnull)
-               elog(ERROR, "NULL elements not allowed in Arrays");
-
-       /* Use datumCopy to ensure pass-by-ref stuff is copied into mcontext */
-       astate->dvalues[astate->nelems++] =
-               datumCopy(dvalue, astate->typbyval, astate->typlen);
-
-       MemoryContextSwitchTo(oldcontext);
-
-       return astate;
-}
-
-/*
- * makeArrayResult - produce final result of accumArrayResult
- *
- *     astate is working state (not NULL)
- *     rcontext is where to construct result
- */
-Datum
-makeArrayResult(ArrayBuildState *astate,
-                               MemoryContext rcontext)
-{
-       int                     dims[1];
-       int                     lbs[1];
-
-       dims[0] = astate->nelems;
-       lbs[0] = 1;
-
-       return makeMdArrayResult(astate, 1, dims, lbs, rcontext);
-}
-
-/*
- * makeMdArrayResult - produce md final result of accumArrayResult
- *
- *     astate is working state (not NULL)
- *     rcontext is where to construct result
- */
-Datum
-makeMdArrayResult(ArrayBuildState *astate,
-                               int ndims,
-                               int *dims,
-                               int *lbs,
-                               MemoryContext rcontext)
-{
-       ArrayType  *result;
-       MemoryContext oldcontext;
-
-       /* Build the final array result in rcontext */
-       oldcontext = MemoryContextSwitchTo(rcontext);
-
-       result = construct_md_array(astate->dvalues,
-                                                               ndims,
-                                                               dims,
-                                                               lbs,
-                                                               astate->element_type,
-                                                               astate->typlen,
-                                                               astate->typbyval,
-                                                               astate->typalign);
-
-       MemoryContextSwitchTo(oldcontext);
-
-       /* Clean up all the junk */
-       MemoryContextDelete(astate->mcontext);
-
-       return PointerGetDatum(result);
-}
index aca19d17e89feea74746848e413f2755b85187e4..ce6443647e2240c5df6cd666c4e2781796a4b718 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.99 2003/06/24 23:14:46 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.100 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "access/tuptoaster.h"
-#include "catalog/pg_type.h"
 #include "lib/stringinfo.h"
 #include "libpq/crypt.h"
 #include "libpq/pqformat.h"
-#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/pg_locale.h"
-#include "utils/lsyscache.h"
 
 
 typedef struct varlena unknown;
@@ -1986,7 +1983,8 @@ split_text(PG_FUNCTION_ARGS)
                if (fldnum == 1)                /* first field - just return the input
                                                                 * string */
                        PG_RETURN_TEXT_P(inputstring);
-               else                                    /* otherwise return an empty string */
+               else
+/* otherwise return an empty string */
                        PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
        }
 
@@ -2006,7 +2004,8 @@ split_text(PG_FUNCTION_ARGS)
                if (fldnum == 1)                /* first field - just return the input
                                                                 * string */
                        PG_RETURN_TEXT_P(inputstring);
-               else                                    /* otherwise return an empty string */
+               else
+/* otherwise return an empty string */
                        PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
        }
        else if ((start_posn != 0) && (end_posn == 0))
@@ -2029,191 +2028,6 @@ split_text(PG_FUNCTION_ARGS)
        }
 }
 
-/*
- * text_to_array
- * parse input string
- * return text array of elements
- * based on provided field separator
- */
-Datum
-text_to_array(PG_FUNCTION_ARGS)
-{
-       text       *inputstring = PG_GETARG_TEXT_P(0);
-       int                     inputstring_len = TEXTLEN(inputstring);
-       text       *fldsep = PG_GETARG_TEXT_P(1);
-       int                     fldsep_len = TEXTLEN(fldsep);
-       int                     fldnum;
-       int                     start_posn = 0;
-       int                     end_posn = 0;
-       text       *result_text = NULL;
-       ArrayBuildState *astate = NULL;
-       MemoryContext oldcontext = CurrentMemoryContext;
-
-       /* return NULL for empty input string */
-       if (inputstring_len < 1)
-               PG_RETURN_NULL();
-
-       /* empty field separator
-        * return one element, 1D, array using the input string */
-       if (fldsep_len < 1)
-               PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
-                                                         CStringGetDatum(inputstring), 1));
-
-       /* start with end position holding the initial start position */
-       end_posn = 0;
-       for (fldnum=1;;fldnum++)        /* field number is 1 based */
-       {
-               Datum   dvalue;
-               bool    disnull = false;
-
-               start_posn = end_posn;
-               end_posn = text_position(PointerGetDatum(inputstring),
-                                                                PointerGetDatum(fldsep),
-                                                                fldnum);
-
-               if ((start_posn == 0) && (end_posn == 0))       /* fldsep not found */
-               {
-                       if (fldnum == 1)
-                       {
-                               /* first element
-                                * return one element, 1D, array using the input string */
-                               PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
-                                                                         CStringGetDatum(inputstring), 1));
-                       }
-                       else
-                       {
-                               /* otherwise create array and exit */
-                               PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, oldcontext));
-                       }
-               }
-               else if ((start_posn != 0) && (end_posn == 0))
-               {
-                       /* last field requested */
-                       result_text = text_substring(PointerGetDatum(inputstring), start_posn + fldsep_len, -1, true);
-               }
-               else if ((start_posn == 0) && (end_posn != 0))
-               {
-                       /* first field requested */
-                       result_text = LEFT(inputstring, fldsep);
-               }
-               else
-               {
-                       /* prior to last field requested */
-                       result_text = text_substring(PointerGetDatum(inputstring), start_posn + fldsep_len, end_posn - start_posn - fldsep_len, false);
-               }
-
-               /* stash away current value */
-               dvalue = PointerGetDatum(result_text);
-               astate = accumArrayResult(astate, dvalue,
-                                                                 disnull, TEXTOID, oldcontext);
-
-       }
-
-       /* never reached -- keep compiler quiet */
-       PG_RETURN_NULL();
-}
-
-/*
- * array_to_text
- * concatenate Cstring representation of input array elements
- * using provided field separator
- */
-Datum
-array_to_text(PG_FUNCTION_ARGS)
-{
-       ArrayType  *v = PG_GETARG_ARRAYTYPE_P(0);
-       char       *fldsep = PG_TEXTARG_GET_STR(1);
-       int                     nitems, *dims, ndims;
-       char       *p;
-       Oid                     element_type;
-       int                     typlen;
-       bool            typbyval;
-       char            typdelim;
-       Oid                     typoutput,
-                               typelem;
-       FmgrInfo        outputproc;
-       char            typalign;
-       StringInfo      result_str = makeStringInfo();
-       int                     i;
-       ArrayMetaState *my_extra;
-
-       p = ARR_DATA_PTR(v);
-       ndims = ARR_NDIM(v);
-       dims = ARR_DIMS(v);
-       nitems = ArrayGetNItems(ndims, dims);
-
-       /* if there are no elements, return an empty string */
-       if (nitems == 0)
-               PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
-
-       element_type = ARR_ELEMTYPE(v);
-
-       /*
-        * We arrange to look up info about element type, including its output
-        * conversion proc only once per series of calls, assuming the element
-        * type doesn't change underneath us.
-        */
-       my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-       if (my_extra == NULL)
-       {
-               fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-                                                                                                        sizeof(ArrayMetaState));
-               my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
-               my_extra->element_type = InvalidOid;
-       }
-
-       if (my_extra->element_type != element_type)
-       {
-               /* Get info about element type, including its output conversion proc */
-               get_type_metadata(element_type, IOFunc_output,
-                                                       &typlen, &typbyval, &typdelim,
-                                                       &typelem, &typoutput, &typalign);
-               fmgr_info(typoutput, &outputproc);
-
-               my_extra->element_type = element_type;
-               my_extra->typlen = typlen;
-               my_extra->typbyval = typbyval;
-               my_extra->typdelim = typdelim;
-               my_extra->typelem = typelem;
-               my_extra->typiofunc = typoutput;
-               my_extra->typalign = typalign;
-               my_extra->proc = outputproc;
-       }
-       else
-       {
-               typlen = my_extra->typlen;
-               typbyval = my_extra->typbyval;
-               typdelim = my_extra->typdelim;
-               typelem = my_extra->typelem;
-               typoutput = my_extra->typiofunc;
-               typalign = my_extra->typalign;
-               outputproc = my_extra->proc;
-       }
-
-       for (i = 0; i < nitems; i++)
-       {
-               Datum           itemvalue;
-               char       *value;
-
-               itemvalue = fetch_att(p, typbyval, typlen);
-
-               value = DatumGetCString(FunctionCall3(&outputproc,
-                                                                                         itemvalue,
-                                                                                         ObjectIdGetDatum(typelem),
-                                                                                         Int32GetDatum(-1)));
-
-               if (i > 0)
-                       appendStringInfo(result_str, "%s%s", fldsep, value);
-               else
-                       appendStringInfo(result_str, "%s", value);
-
-               p = att_addlength(p, typlen, PointerGetDatum(p));
-               p = (char *) att_align(p, typalign);
-       }
-
-       PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));
-}
-
 #define HEXBASE 16
 /*
  * Convert a int32 to a string containing a base 16 (hex) representation of
index 2c0c6457918ab1a8dda1da4bf883ff8b72d05dbd..479f23090fb7ecd20896ef1e60343b20d243b214 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.98 2003/06/25 03:56:31 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.99 2003/06/25 21:30:32 momjian Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -718,40 +718,6 @@ get_func_rettype(Oid funcid)
        return result;
 }
 
-/*
- * get_func_argtypes
- *             Given procedure id, return the function's argument types.
- *             Also pass back the number of arguments.
- */
-Oid *
-get_func_argtypes(Oid funcid, int *nargs)
-{
-       HeapTuple               tp;
-       Form_pg_proc    procstruct;
-       Oid                        *result = NULL;
-       int                             i;
-
-       tp = SearchSysCache(PROCOID,
-                                               ObjectIdGetDatum(funcid),
-                                               0, 0, 0);
-       if (!HeapTupleIsValid(tp))
-               elog(ERROR, "Function OID %u does not exist", funcid);
-
-       procstruct = (Form_pg_proc) GETSTRUCT(tp);
-       *nargs = (int) procstruct->pronargs;
-
-       if (*nargs > 0)
-       {
-               result = (Oid *) palloc(*nargs * sizeof(Oid));
-
-               for (i = 0; i < *nargs; i++)
-                       result[i] = procstruct->proargtypes[i];
-       }
-
-       ReleaseSysCache(tp);
-       return result;
-}
-
 /*
  * get_func_retset
  *             Given procedure id, return the function's proretset flag.
@@ -1124,56 +1090,6 @@ get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
        ReleaseSysCache(tp);
 }
 
-/*
- * get_type_metadata
- *
- *             A six-fer:      given the type OID, return typlen, typbyval, typalign,
- *                                     typdelim, typelem, IO function Oid. The IO function
- *                                     returned is controlled by IOFuncSelector
- */
-void
-get_type_metadata(Oid element_type,
-                                       IOFuncSelector which_func,
-                                       int *typlen,
-                                       bool *typbyval,
-                                       char *typdelim,
-                                       Oid *typelem,
-                                       Oid *proc,
-                                       char *typalign)
-{
-       HeapTuple       typeTuple;
-       Form_pg_type typeStruct;
-
-       typeTuple = SearchSysCache(TYPEOID,
-                                                          ObjectIdGetDatum(element_type),
-                                                          0, 0, 0);
-       if (!HeapTupleIsValid(typeTuple))
-               elog(ERROR, "cache lookup failed for type %u", element_type);
-       typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
-
-       *typlen = typeStruct->typlen;
-       *typbyval = typeStruct->typbyval;
-       *typdelim = typeStruct->typdelim;
-       *typelem = typeStruct->typelem;
-       *typalign = typeStruct->typalign;
-       switch (which_func)
-       {
-               case IOFunc_input:
-                       *proc = typeStruct->typinput;
-                       break;
-               case IOFunc_output:
-                       *proc = typeStruct->typoutput;
-                       break;
-               case IOFunc_receive:
-                       *proc = typeStruct->typreceive;
-                       break;
-               case IOFunc_send:
-                       *proc = typeStruct->typsend;
-                       break;
-       }
-       ReleaseSysCache(typeTuple);
-}
-
 #ifdef NOT_USED
 char
 get_typalign(Oid typid)
index d772a0a06cedf6aa2efa60c0c06c456061e53a6e..e161bd1e59365f2292d0ac14d2085ee8e5d91c08 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.69 2003/06/24 23:14:46 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.70 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1673,29 +1673,3 @@ get_fn_expr_argtype(FunctionCallInfo fcinfo, int argnum)
 
        return exprType((Node *) nth(argnum, args));
 }
-
-/*
- * Get the OID of the function or operator
- *
- * Returns InvalidOid if information is not available
- */
-Oid
-get_fn_expr_functype(FunctionCallInfo fcinfo)
-{
-       Node   *expr;
-
-       /*
-        * can't return anything useful if we have no FmgrInfo or if
-        * its fn_expr node has not been initialized
-        */
-       if (!fcinfo || !fcinfo->flinfo || !fcinfo->flinfo->fn_expr)
-               return InvalidOid;
-
-       expr = fcinfo->flinfo->fn_expr;
-       if (IsA(expr, FuncExpr))
-               return ((FuncExpr *) expr)->funcid;
-       else if (IsA(expr, OpExpr))
-               return ((OpExpr *) expr)->opno;
-       else
-               return InvalidOid;
-}
index 43672f716f2d41ed4c78e9b9a310dfc69a9b8b46..4b6107ce53e89c86f862e78afca2732ab29b56a3 100644 (file)
@@ -16,7 +16,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amop.h,v 1.51 2003/06/24 23:14:46 momjian Exp $
+ * $Id: pg_amop.h,v 1.52 2003/06/25 21:30:32 momjian Exp $
  *
  * NOTES
  *      the genbki.sh script reads this file and generates .bki
@@ -418,15 +418,6 @@ DATA(insert (      2098 3 f 2334 ));
 DATA(insert (  2098 4 f 2335 ));
 DATA(insert (  2098 5 f 2336 ));
 
-/*
- *     btree array_ops
- */
-
-DATA(insert (   397 1 f 1072 ));
-DATA(insert (   397 2 f 1074 ));
-DATA(insert (   397 3 f 1070 ));
-DATA(insert (   397 4 f 1075 ));
-DATA(insert (   397 5 f 1073 ));
 
 /*
  *     hash index _ops
index 87553a49807cd3a197c084149b692d491182f3b4..6febdecffcd62d6b7510c6708687f8abbf047ff9 100644 (file)
@@ -14,7 +14,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amproc.h,v 1.39 2003/06/24 23:14:46 momjian Exp $
+ * $Id: pg_amproc.h,v 1.40 2003/06/25 21:30:32 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -78,7 +78,6 @@ DATA(insert ( 1993 3  199 ));
 
 
 /* btree */
-DATA(insert (   397 1  382 ));
 DATA(insert (   421 1  357 ));
 DATA(insert (   423 1 1596 ));
 DATA(insert (   424 1 1693 ));
index 828afe5aa8c4000a1efb3ff423ab76361174b1a8..88d2aac1a7da4abfdc57d55a41d01bc63c82961e 100644 (file)
@@ -26,7 +26,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_opclass.h,v 1.52 2003/06/24 23:14:46 momjian Exp $
+ * $Id: pg_opclass.h,v 1.53 2003/06/25 21:30:32 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -87,8 +87,6 @@ typedef FormData_pg_opclass *Form_pg_opclass;
  */
 
 DATA(insert OID =  421 (       403             abstime_ops             PGNSP PGUID  702 t 0 ));
-DATA(insert OID =  397 (       403             array_ops               PGNSP PGUID 2277 t 0 ));
-#define ARRAY_BTREE_OPS_OID 397
 DATA(insert OID =  422 (       402             bigbox_ops              PGNSP PGUID  603 f 0 ));
 DATA(insert OID =  423 (       403             bit_ops                 PGNSP PGUID 1560 t 0 ));
 DATA(insert OID =  424 (       403             bool_ops                PGNSP PGUID   16 t 0 ));
index 3a7b143c9f59eb8b174ea1918b4f77215f40a4d2..2bbef276c00f938cc143a53647e6d0b14f3c57ae 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_operator.h,v 1.116 2003/06/24 23:14:46 momjian Exp $
+ * $Id: pg_operator.h,v 1.117 2003/06/25 21:30:32 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -116,15 +116,10 @@ DATA(insert OID =  96 ( "="                  PGNSP PGUID b t      23      23      16      96 518  97      97      97 521 int
 DATA(insert OID =  97 ( "<"               PGNSP PGUID b f      23      23      16 521 525       0       0       0       0 int4lt scalarltsel scalarltjoinsel ));
 DATA(insert OID =  98 ( "="               PGNSP PGUID b t      25      25      16      98 531 664 664 664 666 texteq eqsel eqjoinsel ));
 
-DATA(insert OID = 1070 (  "="     PGNSP PGUID b f 2277 2277 16 1070 1071  1072 1072 1072 1073 array_eq eqsel eqjoinsel ));
-DATA(insert OID = 1071 (  "<>"    PGNSP PGUID b f 2277 2277 16 1071 1070  0 0 0 0 array_ne neqsel neqjoinsel ));
-DATA(insert OID = 1072 (  "<"     PGNSP PGUID b f 2277 2277 16 1073 1075  0 0 0 0 array_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1073 (  ">"     PGNSP PGUID b f 2277 2277 16 1072 1074  0 0 0 0 array_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1074 (  "<="    PGNSP PGUID b f 2277 2277 16 1075 1073  0 0 0 0 array_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1075 (  ">="    PGNSP PGUID b f 2277 2277 16 1074 1072  0 0 0 0 array_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 349 (  "||"     PGNSP PGUID b f 2277 2283 2277 0 0  0 0 0 0 array_append   -       -     ));
-DATA(insert OID = 374 (  "||"     PGNSP PGUID b f 2283 2277 2277 0 0  0 0 0 0 array_prepend  -       -     ));
-DATA(insert OID = 375 (  "||"     PGNSP PGUID b f 2277 2277 2277 0 0  0 0 0 0 array_cat      -       -     ));
+DATA(insert OID = 329 (  "="      PGNSP PGUID b f 2277 2277 16   329 0 0 0     0 0 array_eq     eqsel eqjoinsel ));
+DATA(insert OID = 349 (  "||"     PGNSP PGUID b f 2277 2283 2277   0 0 0 0     0 0 array_append   -       -     ));
+DATA(insert OID = 374 (  "||"     PGNSP PGUID b f 2283 2277 2277   0 0 0 0     0 0 array_prepend  -       -     ));
+DATA(insert OID = 375 (  "||"     PGNSP PGUID b f 2277 2277 2277   0 0 0 0     0 0 array_cat      -       -     ));
 
 DATA(insert OID = 352 (  "="      PGNSP PGUID b t      28      28      16 352   0       0       0       0       0 xideq eqsel eqjoinsel ));
 DATA(insert OID = 353 (  "="      PGNSP PGUID b f      28      23      16       0       0       0       0       0       0 xideqint4 eqsel eqjoinsel ));
@@ -430,7 +425,6 @@ DATA(insert OID = 965 (  "^"           PGNSP PGUID b f      701  701        701 0 0 0 0 0 0 dpow -
 DATA(insert OID = 966 (  "+"      PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclinsert - - ));
 DATA(insert OID = 967 (  "-"      PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclremove - - ));
 DATA(insert OID = 968 (  "~"      PGNSP PGUID b f 1034 1033     16 0 0 0 0 0 0 aclcontains - - ));
-DATA(insert OID = 974 (  "="      PGNSP PGUID b f 1033 1033     16 0 0 0 0 0 0 aclitemeq eqsel eqjoinsel ));
 
 /* additional geometric operators - thomas 1997-07-09 */
 DATA(insert OID =  969 (  "@@"    PGNSP PGUID l f      0  601  600    0  0 0 0 0 0 lseg_center - - ));
index d4c2f64cb7e9cf01c4288cf5ac3ff66b5f289344..bae6f644fc577cb6163b27fb37784227420c1eaf 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.306 2003/06/24 23:14:47 momjian Exp $
+ * $Id: pg_proc.h,v 1.307 2003/06/25 21:30:32 momjian Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -758,8 +758,6 @@ DATA(insert OID = 359 (  btnamecmp             PGNSP PGUID 12 f f t f i 2 23 "19 19"        btn
 DESCR("btree less-equal-greater");
 DATA(insert OID = 360 (  bttextcmp                PGNSP PGUID 12 f f t f i 2 23 "25 25"        bttextcmp - _null_ ));
 DESCR("btree less-equal-greater");
-DATA(insert OID = 382 (  btarraycmp               PGNSP PGUID 12 f f t f i 2 23 "2277 2277"    btarraycmp - _null_ ));
-DESCR("btree less-equal-greater");
 
 DATA(insert OID = 361 (  lseg_distance    PGNSP PGUID 12 f f t f i 2 701 "601 601"  lseg_distance - _null_ ));
 DESCR("distance between");
@@ -990,23 +988,14 @@ DESCR("greater-than");
 DATA(insert OID = 743 (  text_ge                  PGNSP PGUID 12 f f t f i 2 16 "25 25"        text_ge - _null_ ));
 DESCR("greater-than-or-equal");
 
+DATA(insert OID = 744 (  array_eq                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_eq - _null_ ));
+DESCR("array equal");
+
 DATA(insert OID = 745 (  current_user     PGNSP PGUID 12 f f t f s 0 19 "" current_user - _null_ ));
 DESCR("current user name");
 DATA(insert OID = 746 (  session_user     PGNSP PGUID 12 f f t f s 0 19 "" session_user - _null_ ));
 DESCR("session user name");
 
-DATA(insert OID = 744 (  array_eq                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_eq - _null_ ));
-DESCR("array equal");
-DATA(insert OID = 390 (  array_ne                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_ne - _null_ ));
-DESCR("array not equal");
-DATA(insert OID = 391 (  array_lt                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_lt - _null_ ));
-DESCR("array less than");
-DATA(insert OID = 392 (  array_gt                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_gt - _null_ ));
-DESCR("array greater than");
-DATA(insert OID = 393 (  array_le                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_le - _null_ ));
-DESCR("array less than or equal");
-DATA(insert OID = 396 (  array_ge                 PGNSP PGUID 12 f f t f i 2 16 "2277 2277" array_ge - _null_ ));
-DESCR("array greater than or equal");
 DATA(insert OID = 747 (  array_dims               PGNSP PGUID 12 f f t f i 1 25 "2277" array_dims - _null_ ));
 DESCR("array dimensions");
 DATA(insert OID = 750 (  array_in                 PGNSP PGUID 12 f f t f s 3 2277 "2275 26 23"  array_in - _null_ ));
@@ -1017,18 +1006,22 @@ DATA(insert OID = 2091 (  array_lower      PGNSP PGUID 12 f f t f i 2 23 "2277 23"
 DESCR("array lower dimension");
 DATA(insert OID = 2092 (  array_upper     PGNSP PGUID 12 f f t f i 2 23 "2277 23" array_upper - _null_ ));
 DESCR("array upper dimension");
+DATA(insert OID = 377 (  singleton_array  PGNSP PGUID 12 f f t f i 1 2277 "2283" singleton_array - _null_ ));
+DESCR("create array from single element");
 DATA(insert OID = 378 (  array_append     PGNSP PGUID 12 f f t f i 2 2277 "2277 2283" array_push - _null_ ));
 DESCR("append element onto end of array");
 DATA(insert OID = 379 (  array_prepend    PGNSP PGUID 12 f f t f i 2 2277 "2283 2277" array_push - _null_ ));
 DESCR("prepend element onto front of array");
+DATA(insert OID = 380 (  array_accum      PGNSP PGUID 12 f f f f i 2 2277 "2277 2283" array_accum - _null_ ));
+DESCR("push element onto end of array, creating array if needed");
+DATA(insert OID = 381 (  array_assign     PGNSP PGUID 12 f f t f i 3 2277 "2277 23 2283" array_assign - _null_ ));
+DESCR("assign specific array element");
+DATA(insert OID = 382 (  array_subscript  PGNSP PGUID 12 f f t f i 2 2283 "2277 23" array_subscript - _null_ ));
+DESCR("return specific array element");
 DATA(insert OID = 383 (  array_cat            PGNSP PGUID 12 f f t f i 2 2277 "2277 2277" array_cat - _null_ ));
 DESCR("concatenate two arrays");
 DATA(insert OID = 384  (  array_coerce    PGNSP PGUID 12 f f t f i 1 2277 "2277" array_type_coerce - _null_ ));
 DESCR("coerce array type to another array type");
-DATA(insert OID = 394 (  string_to_array   PGNSP PGUID 12 f f t f i 2 1009 "25 25" text_to_array - _null_ ));
-DESCR("split delimited text into text[]");
-DATA(insert OID = 395 (  array_to_string   PGNSP PGUID 12 f f t f i 2 25 "2277 25" array_to_text - _null_ ));
-DESCR("concatenate array elements, using delimiter, into text");
 
 DATA(insert OID = 760 (  smgrin                           PGNSP PGUID 12 f f t f s 1 210 "2275"  smgrin - _null_ ));
 DESCR("I/O");
@@ -1329,8 +1322,6 @@ DATA(insert OID = 1036 (  aclremove                  PGNSP PGUID 12 f f t f s 2 1034 "1034 10
 DESCR("remove ACL item");
 DATA(insert OID = 1037 (  aclcontains     PGNSP PGUID 12 f f t f s 2 16 "1034 1033"    aclcontains - _null_ ));
 DESCR("does ACL contain item?");
-DATA(insert OID = 1062 (  aclitemeq           PGNSP PGUID 12 f f t f s 2 16 "1033 1033"        aclitem_eq - _null_ ));
-DESCR("equality operator for ACL items");
 DATA(insert OID = 1365 (  makeaclitem     PGNSP PGUID 12 f f t f s 5 1033 "23 23 23 25 16"     makeaclitem - _null_ ));
 DESCR("make ACL item");
 DATA(insert OID = 1038 (  seteval                 PGNSP PGUID 12 f f t t v 1 23 "26"  seteval - _null_ ));
index 784b50885ea257cfece5f6d5db74e5a6a4f862bd..51844eac38bb794a2f6badd70c00b1b7bf707ad0 100644 (file)
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fmgr.h,v 1.28 2003/06/24 23:14:46 momjian Exp $
+ * $Id: fmgr.h,v 1.29 2003/06/25 21:30:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef FMGR_H
 #define FMGR_H
 
-#include "nodes/nodes.h"
 
 /*
  * All functions that can be called directly by fmgr must have this signature.
@@ -373,14 +372,14 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
                                 Datum arg6, Datum arg7, Datum arg8,
                                 Datum arg9);
 
+
 /*
  * Routines in fmgr.c
  */
 extern Pg_finfo_record *fetch_finfo_record(void *filehandle, char *funcname);
-extern Oid fmgr_internal_function(const char *proname);
-extern Oid get_fn_expr_rettype(FunctionCallInfo fcinfo);
-extern Oid get_fn_expr_argtype(FunctionCallInfo fcinfo, int argnum);
-extern Oid get_fn_expr_functype(FunctionCallInfo fcinfo);
+extern Oid     fmgr_internal_function(const char *proname);
+extern Oid     get_fn_expr_rettype(FunctionCallInfo fcinfo);
+extern Oid     get_fn_expr_argtype(FunctionCallInfo fcinfo, int argnum);
 
 /*
  * Routines in dfmgr.c
index 3756e443ff7e3e836f956178be372c961e31881a..23dff8ed622e06307ba507280b1c42a6445f0c43 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.84 2003/06/24 23:14:48 momjian Exp $
+ * $Id: primnodes.h,v 1.85 2003/06/25 21:30:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -226,7 +226,6 @@ typedef struct Aggref
        Index           agglevelsup;    /* > 0 if agg belongs to outer query */
        bool            aggstar;                /* TRUE if argument was really '*' */
        bool            aggdistinct;    /* TRUE if it's agg(DISTINCT ...) */
-       List       *args;                       /* arguments to the aggregate */
 } Aggref;
 
 /* ----------------
@@ -359,19 +358,15 @@ typedef struct BoolExpr
 /* ----------------
  * SubLink
  *
- * A SubLink represents a subselect, or an expression, appearing in an
- * expression, and in some cases also the combining operator(s) just above
- * it. The subLinkType indicates the form of the expression represented:
+ * A SubLink represents a subselect appearing in an expression, and in some
+ * cases also the combining operator(s) just above it. The subLinkType
+ * indicates the form of the expression represented:
  *     EXISTS_SUBLINK          EXISTS(SELECT ...)
  *     ALL_SUBLINK                     (lefthand) op ALL (SELECT ...)
  *     ANY_SUBLINK                     (lefthand) op ANY (SELECT ...)
  *     MULTIEXPR_SUBLINK       (lefthand) op (SELECT ...)
  *     EXPR_SUBLINK            (SELECT with single targetlist item ...)
  *     ARRAY_SUBLINK           ARRAY(SELECT with single targetlist item ...)
- * If an expression is used in place of the subselect, it is transformed
- * into a simple "(SELECT expr)" in gram.y. This is to allow arrays to be
- * used as if they were the result of a single column subselect. If the
- * expression is scalar, it is treated as a one element array.
  * For ALL, ANY, and MULTIEXPR, the lefthand is a list of expressions of the
  * same length as the subselect's targetlist.  MULTIEXPR will *always* have
  * a list with more than one entry; if the subselect has just one target
@@ -420,8 +415,6 @@ typedef struct SubLink
        SubLinkType subLinkType;        /* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
        bool            useOr;                  /* TRUE to combine column results with
                                                                 * "OR" not "AND" */
-       bool            isExpr;                 /* TRUE if the subselect is really derived
-                                                                * from a single expression */
        List       *lefthand;           /* list of outer-query expressions on the
                                                                 * left */
        List       *operName;           /* originally specified operator name */
@@ -463,15 +456,6 @@ typedef struct SubPlan
        SubLinkType subLinkType;        /* EXISTS, ALL, ANY, MULTIEXPR, EXPR */
        bool            useOr;                  /* TRUE to combine column results with
                                                                 * "OR" not "AND" */
-       bool            isExpr;                 /* TRUE if the subselect is really derived
-                                                                * from a single expression */
-       /* runtime cache for single array expressions */
-       Oid                     exprtype;               /* array and element type, and other info
-                                                                * needed deconstruct the array */
-       Oid                     elemtype;
-       int16           elmlen;
-       bool            elmbyval;
-       char            elmalign;
        /* The combining operators, transformed to executable expressions: */
        List       *exprs;                      /* list of OpExpr expression trees */
        List       *paramIds;           /* IDs of Params embedded in the above */
index 946fc68c463e0fafa0e6f31c82bb677db474e86e..04add3c6f63ad04afb7acaa864776fffa606b75d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: clauses.h,v 1.64 2003/06/24 23:14:49 momjian Exp $
+ * $Id: clauses.h,v 1.65 2003/06/25 21:30:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,9 +28,6 @@ extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
 extern Node *get_leftop(Expr *clause);
 extern Node *get_rightop(Expr *clause);
 
-extern Expr *make_funcclause(Oid funcid, Oid funcresulttype, bool funcretset,
-                                                                       CoercionForm funcformat, List *funcargs);
-
 extern bool not_clause(Node *clause);
 extern Expr *make_notclause(Expr *notclause);
 extern Expr *get_notclausearg(Expr *notclause);
index e7c8bdb56cbeec47a9818dbeb727dfda4ec1d27c..13642f5a348026dcf2c1176eda5915a4cbe716c7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_oper.h,v 1.26 2003/06/24 23:14:49 momjian Exp $
+ * $Id: parse_oper.h,v 1.27 2003/06/25 21:30:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,7 +44,6 @@ extern Operator ordering_oper(Oid argtype, bool noError);
 /* Convenience routines for common calls on the above */
 extern Oid     compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
 extern Oid     equality_oper_funcid(Oid argtype);
-extern Oid  ordering_oper_funcid(Oid argtype);
 extern Oid     ordering_oper_opid(Oid argtype);
 
 /* Extract operator OID or underlying-function OID from an Operator tuple */
index 0d7761190196cf15d728a1349af40b55c2182ea2..9cf35618ad74f0ca1a5a25ec3df63c0c7575a10a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: acl.h,v 1.53 2003/06/24 23:14:49 momjian Exp $
+ * $Id: acl.h,v 1.54 2003/06/25 21:30:33 momjian Exp $
  *
  * NOTES
  *       For backward-compatibility purposes we have to allow there
@@ -192,7 +192,6 @@ extern Datum aclinsert(PG_FUNCTION_ARGS);
 extern Datum aclremove(PG_FUNCTION_ARGS);
 extern Datum aclcontains(PG_FUNCTION_ARGS);
 extern Datum makeaclitem(PG_FUNCTION_ARGS);
-extern Datum aclitem_eq(PG_FUNCTION_ARGS);
 
 /*
  * prototypes for functions in aclchk.c
index 5df86b1827f3bdc4eafbb509eddb78e08a9dc206..23a32d3459e909e471634d0a32d946e9aa3dd1f1 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: array.h,v 1.39 2003/06/24 23:14:49 momjian Exp $
+ * $Id: array.h,v 1.40 2003/06/25 21:30:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,37 +32,6 @@ typedef struct
        Oid                     elemtype;               /* element type OID */
 } ArrayType;
 
-typedef struct ArrayBuildState
-{
-       MemoryContext mcontext;         /* where all the temp stuff is kept */
-       Datum      *dvalues;            /* array of accumulated Datums */
-       /*
-        * The allocated size of dvalues[] is always a multiple of
-        * ARRAY_ELEMS_CHUNKSIZE
-        */
-#define ARRAY_ELEMS_CHUNKSIZE  64
-       int                     nelems;                 /* number of valid Datums in dvalues[] */
-       Oid                     element_type;   /* data type of the Datums */
-       int16           typlen;                 /* needed info about datatype */
-       bool            typbyval;
-       char            typalign;
-} ArrayBuildState;
-
-/*
- * structure to cache type metadata needed for array manipulation
- */
-typedef struct ArrayMetaState
-{
-       Oid                             element_type;
-       int                             typlen;
-       bool                    typbyval;
-       char                    typdelim;
-       Oid                             typelem;
-       Oid                             typiofunc;
-       char                    typalign;
-       FmgrInfo                proc;
-} ArrayMetaState;
-
 /*
  * fmgr macros for array objects
  */
@@ -117,15 +86,11 @@ extern Datum array_recv(PG_FUNCTION_ARGS);
 extern Datum array_send(PG_FUNCTION_ARGS);
 extern Datum array_length_coerce(PG_FUNCTION_ARGS);
 extern Datum array_eq(PG_FUNCTION_ARGS);
-extern Datum array_ne(PG_FUNCTION_ARGS);
-extern Datum array_lt(PG_FUNCTION_ARGS);
-extern Datum array_gt(PG_FUNCTION_ARGS);
-extern Datum array_le(PG_FUNCTION_ARGS);
-extern Datum array_ge(PG_FUNCTION_ARGS);
-extern Datum btarraycmp(PG_FUNCTION_ARGS);
 extern Datum array_dims(PG_FUNCTION_ARGS);
 extern Datum array_lower(PG_FUNCTION_ARGS);
 extern Datum array_upper(PG_FUNCTION_ARGS);
+extern Datum array_assign(PG_FUNCTION_ARGS);
+extern Datum array_subscript(PG_FUNCTION_ARGS);
 extern Datum array_type_coerce(PG_FUNCTION_ARGS);
 
 extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
@@ -159,14 +124,7 @@ extern void deconstruct_array(ArrayType *array,
                                  Oid elmtype,
                                  int elmlen, bool elmbyval, char elmalign,
                                  Datum **elemsp, int *nelemsp);
-extern ArrayBuildState *accumArrayResult(ArrayBuildState *astate,
-                                                                                Datum dvalue, bool disnull,
-                                                                                Oid element_type,
-                                                                                MemoryContext rcontext);
-extern Datum makeArrayResult(ArrayBuildState *astate,
-                                                        MemoryContext rcontext);
-extern Datum makeMdArrayResult(ArrayBuildState *astate, int ndims,
-                                                          int *dims, int *lbs, MemoryContext rcontext);
+
 
 /*
  * prototypes for functions defined in arrayutils.c
@@ -183,11 +141,12 @@ extern int        mda_next_tuple(int n, int *curr, int *span);
 /*
  * prototypes for functions defined in array_userfuncs.c
  */
+extern Datum singleton_array(PG_FUNCTION_ARGS);
 extern Datum array_push(PG_FUNCTION_ARGS);
+extern Datum array_accum(PG_FUNCTION_ARGS);
 extern Datum array_cat(PG_FUNCTION_ARGS);
 
-extern ArrayType *create_singleton_array(FunctionCallInfo fcinfo,
-                                                                                Oid element_type,
+extern ArrayType *create_singleton_array(Oid element_type,
                                                                                 Datum element,
                                                                                 int ndims);
 
index 43e174722b3e6ccca4fc2bc44aae3ffeb95fc367..958021eb1f0df4072280d526937ce117db7db38e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.221 2003/06/24 23:14:49 momjian Exp $
+ * $Id: builtins.h,v 1.222 2003/06/25 21:30:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -530,8 +530,6 @@ extern bool SplitIdentifierString(char *rawstring, char separator,
                                          List **namelist);
 extern Datum replace_text(PG_FUNCTION_ARGS);
 extern Datum split_text(PG_FUNCTION_ARGS);
-extern Datum text_to_array(PG_FUNCTION_ARGS);
-extern Datum array_to_text(PG_FUNCTION_ARGS);
 extern Datum to_hex32(PG_FUNCTION_ARGS);
 extern Datum to_hex64(PG_FUNCTION_ARGS);
 extern Datum md5_text(PG_FUNCTION_ARGS);
index e9de9f02c3f3229e56df3e95ce2016994bd64eba..d7d3bba9d977218e780b7656744e1796400c7d85 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.73 2003/06/25 03:56:31 momjian Exp $
+ * $Id: lsyscache.h,v 1.74 2003/06/25 21:30:33 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "access/htup.h"
 
-/* I/O function selector for system_cache_lookup */
-typedef enum IOFuncSelector
-{
-       IOFunc_input,
-       IOFunc_output,
-       IOFunc_receive,
-       IOFunc_send
-} IOFuncSelector;
-
 extern bool op_in_opclass(Oid opno, Oid opclass);
 extern bool op_requires_recheck(Oid opno, Oid opclass);
 extern Oid     get_opclass_member(Oid opclass, int16 strategy);
@@ -50,7 +41,6 @@ extern RegProcedure get_oprrest(Oid opno);
 extern RegProcedure get_oprjoin(Oid opno);
 extern char *get_func_name(Oid funcid);
 extern Oid     get_func_rettype(Oid funcid);
-extern Oid *get_func_argtypes(Oid funcid, int *nargs);
 extern bool get_func_retset(Oid funcid);
 extern bool func_strict(Oid funcid);
 extern char func_volatile(Oid funcid);
@@ -66,14 +56,6 @@ extern bool get_typbyval(Oid typid);
 extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
 extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
                                         char *typalign);
-extern void get_type_metadata(Oid element_type,
-                                                               IOFuncSelector which_func,
-                                                               int *typlen,
-                                                               bool *typbyval,
-                                                               char *typdelim,
-                                                               Oid *typelem,
-                                                               Oid *proc,
-                                                               char *typalign);
 extern char get_typstorage(Oid typid);
 extern int32 get_typtypmod(Oid typid);
 extern Node *get_typdefault(Oid typid);
index ff175700cf4b41a9388b87955dd86557dccfef02..ffa849045a83d1ed94a8f4341be9782b30c3f954 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.238 2003/06/25 10:44:21 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.239 2003/06/25 21:30:33 momjian Exp $ */
 
 /* Copyright comment */
 %{
@@ -4599,7 +4599,7 @@ type_declaration: S_TYPEDEF
                            $3.type_enum != ECPGt_char &&
                            $3.type_enum != ECPGt_unsigned_char &&
                            atoi(this->type->type_index) >= 0)
-                               mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
+                               mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
 
                        types = this;
                }
@@ -5419,7 +5419,7 @@ ECPGTypedef: TYPE_P
                                        $5.type_enum != ECPGt_char &&
                                        $5.type_enum != ECPGt_unsigned_char &&
                                        atoi(this->type->type_index) >= 0)
-                                       mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
+                                       mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
 
                                types = this;
                        }
@@ -5486,7 +5486,7 @@ ECPGVar: SQL_VAR
 
                                        default:
                                                if (atoi(length) >= 0)
-                                                       mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
+                                                       mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
 
                                                if (atoi(dimension) < 0)
                                                        type = ECPGmake_simple_type($5.type_enum, make_str("1"));
index 80406bbccc5124115b194c0d5c71098e104dcb05..5f2dd86bb55f15fedccc6e005aa36cd255b2118a 100644 (file)
@@ -504,7 +504,7 @@ ECPGfree_type(struct ECPGtype * type)
                                switch (type->u.element->type)
                                {
                                        case ECPGt_array:
-                                               yyerror("internal error, found multidimensional array\n");
+                                               yyerror("internal error, found multi-dimensional array\n");
                                                break;
                                        case ECPGt_struct:
                                        case ECPGt_union:
index 9fa2ec8a6c9a3756975e9f8d93fb1c6cdcc295a6..be96e18c0c5488d38bc3fe5ba0eafb644d39436c 100644 (file)
@@ -436,7 +436,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
        if (atoi(type_index) >= 0)
        {
                if (atoi(*length) >= 0)
-                       mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support");
+                       mmerror(PARSE_ERROR, ET_FATAL, "No multi-dimensional array support");
 
                *length = type_index;
        }
@@ -444,7 +444,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
        if (atoi(type_dimension) >= 0)
        {
                if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
-                       mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support");
+                       mmerror(PARSE_ERROR, ET_FATAL, "No multi-dimensional array support");
 
                if (atoi(*dimension) >= 0)
                        *length = *dimension;
@@ -463,10 +463,10 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
                mmerror(PARSE_ERROR, ET_FATAL, "No pointer to pointer supported for this type");
 
        if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
-               mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support");
+               mmerror(PARSE_ERROR, ET_FATAL, "No multi-dimensional array support");
 
        if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
-               mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support");
+               mmerror(PARSE_ERROR, ET_FATAL, "No multi-dimensional array support");
 
        switch (type_enum)
        {
@@ -480,7 +480,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
                        }
 
                        if (atoi(*length) >= 0)
-                               mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support for structures");
+                               mmerror(PARSE_ERROR, ET_FATAL, "No multi-dimensional array support for structures");
 
                        break;
                case ECPGt_varchar:
@@ -525,7 +525,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
                        }
 
                        if (atoi(*length) >= 0)
-                               mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support for simple data types");
+                               mmerror(PARSE_ERROR, ET_FATAL, "No multi-dimensional array support for simple data types");
 
                        break;
        }
index c5f638bd4653e23c9e98ac7cbb0d4614e7c3cfa6..617cf09a9a00a1f6b36339e019a60a7c3c317443 100644 (file)
@@ -178,13 +178,19 @@ SELECT ARRAY(select f2 from arrtest_f order by f2) AS "ARRAY";
 (1 row)
 
 -- functions
-SELECT array_append(array[42], 6) AS "{42,6}";
+SELECT singleton_array(42) AS "{42}";
+ {42} 
+------
+ {42}
+(1 row)
+
+SELECT array_append(singleton_array(42), 6) AS "{42,6}";
  {42,6} 
 --------
  {42,6}
 (1 row)
 
-SELECT array_prepend(6, array[42]) AS "{6,42}";
+SELECT array_prepend(6, singleton_array(42)) AS "{6,42}";
  {6,42} 
 --------
  {6,42}
@@ -208,6 +214,24 @@ SELECT array_cat(ARRAY[[3,4],[5,6]], ARRAY[1,2]) AS "{{3,4},{5,6},{1,2}}";
  {{3,4},{5,6},{1,2}}
 (1 row)
 
+SELECT array_subscript(n, 2) AS "1.2" FROM arrtest2;
+ 1.2 
+-----
+ 1.2
+(1 row)
+
+SELECT array_assign(n, 2, 9.99) AS "{1.1,9.99,1.3}" FROM arrtest2;
+ {1.1,9.99,1.3} 
+----------------
+ {1.1,9.99,1.3}
+(1 row)
+
+SELECT array_subscript(array_assign(n, 2, 9.99), 2) AS "9.99" FROM arrtest2;
+ 9.99 
+------
+ 9.99
+(1 row)
+
 -- operators
 SELECT a FROM arrtest WHERE b = ARRAY[[[113,142],[1,147]]];
        a       
index e39044e40acabe1ba64f02c0be6b0ffd4219b5fc..82eff24125df262f27466880cf96b500991134d1 100644 (file)
@@ -130,11 +130,15 @@ SELECT ARRAY[ARRAY['hello'],ARRAY['world']];
 SELECT ARRAY(select f2 from arrtest_f order by f2) AS "ARRAY";
 
 -- functions
-SELECT array_append(array[42], 6) AS "{42,6}";
-SELECT array_prepend(6, array[42]) AS "{6,42}";
+SELECT singleton_array(42) AS "{42}";
+SELECT array_append(singleton_array(42), 6) AS "{42,6}";
+SELECT array_prepend(6, singleton_array(42)) AS "{6,42}";
 SELECT array_cat(ARRAY[1,2], ARRAY[3,4]) AS "{{1,2},{3,4}}";
 SELECT array_cat(ARRAY[1,2], ARRAY[[3,4],[5,6]]) AS "{{1,2},{3,4},{5,6}}";
 SELECT array_cat(ARRAY[[3,4],[5,6]], ARRAY[1,2]) AS "{{3,4},{5,6},{1,2}}";
+SELECT array_subscript(n, 2) AS "1.2" FROM arrtest2;
+SELECT array_assign(n, 2, 9.99) AS "{1.1,9.99,1.3}" FROM arrtest2;
+SELECT array_subscript(array_assign(n, 2, 9.99), 2) AS "9.99" FROM arrtest2;
 
 -- operators
 SELECT a FROM arrtest WHERE b = ARRAY[[[113,142],[1,147]]];