Restructure representation of aggregate functions so that they have pg_proc

entries, per pghackers discussion.  This fixes aggregates to live in
namespaces, and also simplifies/speeds up lookup in parse_func.c.
Also, add a 'proimplicit' flag to pg_proc that controls whether a type
coercion function may be invoked implicitly, or only explicitly.  The
current settings of these flags are more permissive than I would like,
but we will need to debate and refine the behavior; for now, I avoided
breaking regression tests as much as I could.
This commit is contained in:
Tom Lane 2002-04-11 20:00:18 +00:00
parent 3f6299df6c
commit 902a6a0a4b
63 changed files with 2530 additions and 2440 deletions

View File

@ -1,6 +1,6 @@
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.40 2002/04/05 00:31:22 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.41 2002/04/11 19:59:54 tgl Exp $
-->
<chapter id="catalogs">
@ -183,7 +183,11 @@
that matches a query condition) and returns a single value computed
from all these values. Typical aggregate functions are
<function>sum</function>, <function>count</function>, and
<function>max</function>.
<function>max</function>. Each entry in
<structname>pg_aggregate</structname> is an extension of an entry
in <structname>pg_proc</structname>. The <structname>pg_proc</structname>
entry carries the aggregate's name, input and output datatypes, and
other information that is similar to ordinary functions.
</para>
<table>
@ -200,47 +204,29 @@
</thead>
<tbody>
<row>
<entry>aggname</entry>
<entry><type>name</type></entry>
<entry></entry>
<entry>Name of the aggregate function</entry>
</row>
<row>
<entry>aggowner</entry>
<entry><type>int4</type></entry>
<entry>pg_shadow.usesysid</entry>
<entry>Owner (creator) of the aggregate function</entry>
<entry>aggfnoid</entry>
<entry><type>regproc</type></entry>
<entry>pg_proc.oid</entry>
<entry>pg_proc OID of the aggregate function</entry>
</row>
<row>
<entry>aggtransfn</entry>
<entry><type>regproc</type> (function)</entry>
<entry><type>regproc</type></entry>
<entry>pg_proc.oid</entry>
<entry>Transition function</entry>
</row>
<row>
<entry>aggfinalfn</entry>
<entry><type>regproc</type> (function)</entry>
<entry><type>regproc</type></entry>
<entry>pg_proc.oid</entry>
<entry>Final function</entry>
</row>
<row>
<entry>aggbasetype</entry>
<entry><type>oid</type></entry>
<entry>pg_type.oid</entry>
<entry>The input data type for this aggregate function</entry>
</row>
<row>
<entry>aggtranstype</entry>
<entry><type>oid</type></entry>
<entry>pg_type.oid</entry>
<entry>The type of the aggregate function's internal transition (state) data</entry>
</row>
<row>
<entry>aggfinaltype</entry>
<entry><type>oid</type></entry>
<entry>pg_type.oid</entry>
<entry>The type of the result</entry>
</row>
<row>
<entry>agginitval</entry>
<entry><type>text</type></entry>
@ -263,12 +249,6 @@
functions and the meaning of the transition functions, etc.
</para>
<para>
An aggregate function is identified through name
<emphasis>and</emphasis> argument type. Hence aggname and aggbasetype
are the composite primary key.
</para>
</sect1>
@ -1632,6 +1612,12 @@
about the meaning of some fields.
</para>
<para>
The table contains data for aggregate functions as well as plain functions.
If <structfield>proisagg</structfield> is true, there should be a matching
row in <structname>pg_aggregate</structname>.
</para>
<table>
<title>pg_proc Columns</title>
@ -1677,10 +1663,10 @@
</row>
<row>
<entry>proisinh</entry>
<entry>proisagg</entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>unused</entry>
<entry>Function is an aggregate function</entry>
</row>
<row>
@ -1690,6 +1676,13 @@
<entry>not functional</entry>
</row>
<row>
<entry>proimplicit</entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>Function may be invoked as an implicit type coercion</entry>
</row>
<row>
<entry>proisstrict</entry>
<entry><type>bool</type></entry>
@ -1702,6 +1695,14 @@
</entry>
</row>
<row>
<entry>proretset</entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>Function returns a set (ie, multiple values of the specified
data type)</entry>
</row>
<row>
<entry>provolatile</entry>
<entry><type>char</type></entry>
@ -1728,14 +1729,6 @@
<entry>Number of arguments</entry>
</row>
<row>
<entry>proretset</entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>Function returns a set (ie, multiple values of the specified
data type)</entry>
</row>
<row>
<entry>prorettype</entry>
<entry><type>oid</type></entry>

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.16 2001/12/08 03:24:34 thomas Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.17 2002/04/11 19:59:55 tgl Exp $
PostgreSQL documentation
-->
@ -168,8 +168,9 @@ CREATE
<para>
An aggregate function is identified by its name and input data type.
Two aggregates can have the same name if they operate on different
input types. To avoid confusion, do not make an ordinary function
of the same name and input data type as an aggregate.
input types. The
name and input data type of an aggregate must also be distinct from
the name and input data type of every ordinary function.
</para>
<para>
An aggregate function is made from one or two ordinary

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.35 2002/04/05 00:31:24 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.36 2002/04/11 19:59:55 tgl Exp $
-->
<refentry id="SQL-CREATEFUNCTION">
@ -214,6 +214,18 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>implicitCoercion</term>
<listitem>
<para>
<option>implicitCoercion</option> indicates that the function
may be used for implicit type conversions.
See <xref linkend="coercion-functions"
endterm="coercion-functions-title"> for more detail.
</para>
</listitem>
</varlistentry>
</variablelist>
Attribute names are not case-sensitive.
@ -311,6 +323,54 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
</para>
</refsect1>
<refsect1 id="COERCION-FUNCTIONS">
<refsect1info>
<date>2002-04-11</date>
</refsect1info>
<title id="coercion-functions-title">
Type Coercion Functions
</title>
<para>
A function that has one parameter and is named the same as its output
datatype is considered to be a <firstterm>type coercion function</>:
it can be invoked to convert a value of its input datatype into a value
of its output datatype. For example,
<programlisting>
SELECT CAST(42 AS text);
</programlisting>
converts the integer constant 42 to text by invoking a function
<literal>text(int4)</>, if such a function exists and returns type
text. (If no suitable conversion function can be found, the cast fails.)
</para>
<para>
If a potential coercion function is marked <literal>implicitCoercion</>,
then it can be invoked in any context where the conversion it defines
is required. Coercion functions not so marked can be invoked only by
explicit <literal>CAST</>,
<replaceable>x</><literal>::</><replaceable>typename</>,
or <replaceable>typename</>(<replaceable>x</>) constructs.
For example, supposing that foo.f1 is a column of type text, then
<programlisting>
INSERT INTO foo(f1) VALUES(42);
</programlisting>
will be allowed if <literal>text(int4)</> is marked
<literal>implicitCoercion</>, otherwise not.
</para>
<para>
It is wise to be conservative about marking coercion functions as
implicit coercions. An overabundance of implicit coercion paths
can cause <productname>PostgreSQL</productname> to choose surprising
interpretations of commands,
or to be unable to resolve commands at all because there are multiple
possible interpretations. A good rule of thumb is to make coercions
implicitly invokable only for information-preserving transformations
between types in the same general type category. For example, int2
to int4 coercion can reasonably be implicit, but be wary of marking
int4 to text or float8 to int4 as implicit coercions.
</para>
</refsect1>
<refsect1 id="sql-createfunction-examples">
<title>Examples</title>
@ -356,8 +416,8 @@ CREATE TABLE product (
</para>
<para>
This example creates a function that does type conversion between the
user-defined type complex, and the internal type point. The
This example creates a function that does type conversion from the
user-defined type complex to the built-in type point. The
function is implemented by a dynamically loaded object that was
compiled from C source (we illustrate the now-deprecated alternative
of specifying the absolute file name to the shared object file).

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.63 2002/04/11 05:32:02 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.64 2002/04/11 19:59:56 tgl Exp $
*
* NOTES
* See acl.h.
@ -733,7 +733,7 @@ pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode)
Acl *acl;
/*
* Validate userid, find out if he is superuser
* Validate userid, find out if he is superuser, also get usecatupd
*/
tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid),
@ -1035,29 +1035,3 @@ pg_proc_ownercheck(Oid proc_oid, Oid userid)
return userid == owner_id;
}
/*
* Ownership check for an aggregate function (specified by OID).
*/
bool
pg_aggr_ownercheck(Oid aggr_oid, Oid userid)
{
HeapTuple tuple;
AclId owner_id;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid))
return true;
tuple = SearchSysCache(AGGOID,
ObjectIdGetDatum(aggr_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_aggr_ownercheck: aggregate %u not found", aggr_oid);
owner_id = ((Form_pg_aggregate) GETSTRUCT(tuple))->aggowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.194 2002/03/31 06:26:29 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.195 2002/04/11 19:59:56 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -1791,7 +1791,7 @@ cookDefault(ParseState *pstate,
if (type_id != atttypid)
{
if (CoerceTargetExpr(pstate, expr, type_id,
atttypid, atttypmod) == NULL)
atttypid, atttypmod, false) == NULL)
elog(ERROR, "Column \"%s\" is of type %s"
" but default expression is of type %s"
"\n\tYou will need to rewrite or cast the expression",

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.87 2002/04/05 00:31:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.88 2002/04/11 19:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -32,7 +32,7 @@
*/
char *Name_pg_aggregate_indices[Num_pg_aggregate_indices] =
{AggregateNameTypeIndex, AggregateOidIndex};
{AggregateFnoidIndex};
char *Name_pg_am_indices[Num_pg_am_indices] =
{AmNameIndex, AmOidIndex};
char *Name_pg_amop_indices[Num_pg_amop_indices] =

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.43 2002/04/09 20:35:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.44 2002/04/11 19:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,15 +19,16 @@
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "parser/parse_coerce.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
/*
* AggregateCreate
*/
@ -50,7 +51,7 @@ AggregateCreate(const char *aggName,
Oid finaltype;
Oid fnArgs[FUNC_MAX_ARGS];
int nargs;
NameData aname;
Oid procOid;
TupleDesc tupDesc;
int i;
@ -61,15 +62,6 @@ AggregateCreate(const char *aggName,
if (!aggtransfnName)
elog(ERROR, "aggregate must have a transition function");
/* make sure there is no existing agg of same name and base type */
if (SearchSysCacheExists(AGGNAME,
PointerGetDatum(aggName),
ObjectIdGetDatum(aggBaseType),
0, 0))
elog(ERROR,
"aggregate function \"%s\" with base type %s already exists",
aggName, typeidTypeName(aggBaseType));
/* handle transfn */
MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid));
fnArgs[0] = aggTransType;
@ -109,8 +101,8 @@ AggregateCreate(const char *aggName,
/* handle finalfn, if supplied */
if (aggfinalfnName)
{
MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid));
fnArgs[0] = aggTransType;
fnArgs[1] = 0;
finalfn = LookupFuncName(aggfinalfnName, 1, fnArgs);
if (!OidIsValid(finalfn))
func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL);
@ -132,21 +124,47 @@ AggregateCreate(const char *aggName,
}
Assert(OidIsValid(finaltype));
/*
* Everything looks okay. Try to create the pg_proc entry for the
* aggregate. (This could fail if there's already a conflicting entry.)
*/
MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid));
fnArgs[0] = aggBaseType;
procOid = ProcedureCreate(aggName,
aggNamespace,
false, /* no replacement */
false, /* doesn't return a set */
finaltype, /* returnType */
INTERNALlanguageId, /* languageObjectId */
"aggregate_dummy", /* placeholder proc */
"-", /* probin */
true, /* isAgg */
true, /* (obsolete "trusted") */
false, /* isImplicit */
false, /* isStrict (not needed for agg) */
PROVOLATILE_IMMUTABLE, /* volatility (not needed for agg) */
BYTE_PCT, /* default cost values */
PERBYTE_CPU,
PERCALL_CPU,
OUTIN_RATIO,
1, /* parameterCount */
fnArgs); /* parameterTypes */
/*
* Okay to create the pg_aggregate entry.
*/
/* initialize nulls and values */
for (i = 0; i < Natts_pg_aggregate; i++)
{
nulls[i] = ' ';
values[i] = (Datum) NULL;
}
namestrcpy(&aname, aggName);
values[Anum_pg_aggregate_aggname - 1] = NameGetDatum(&aname);
values[Anum_pg_aggregate_aggowner - 1] = Int32GetDatum(GetUserId());
values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
values[Anum_pg_aggregate_aggbasetype - 1] = ObjectIdGetDatum(aggBaseType);
values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
values[Anum_pg_aggregate_aggfinaltype - 1] = ObjectIdGetDatum(finaltype);
if (agginitval)
values[Anum_pg_aggregate_agginitval - 1] =
DirectFunctionCall1(textin, CStringGetDatum(agginitval));
@ -155,12 +173,9 @@ AggregateCreate(const char *aggName,
aggdesc = heap_openr(AggregateRelationName, RowExclusiveLock);
tupDesc = aggdesc->rd_att;
if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
values,
nulls)))
elog(ERROR, "AggregateCreate: heap_formtuple failed");
if (!OidIsValid(heap_insert(aggdesc, tup)))
elog(ERROR, "AggregateCreate: heap_insert failed");
tup = heap_formtuple(tupDesc, values, nulls);
heap_insert(aggdesc, tup);
if (RelationGetForm(aggdesc)->relhasindex)
{
@ -173,62 +188,3 @@ AggregateCreate(const char *aggName,
heap_close(aggdesc, RowExclusiveLock);
}
Datum
AggNameGetInitVal(char *aggName, Oid basetype, bool *isNull)
{
HeapTuple tup;
Oid transtype,
typinput,
typelem;
Datum textInitVal;
char *strInitVal;
Datum initVal;
Assert(PointerIsValid(aggName));
Assert(PointerIsValid(isNull));
tup = SearchSysCache(AGGNAME,
PointerGetDatum(aggName),
ObjectIdGetDatum(basetype),
0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "AggNameGetInitVal: cache lookup failed for aggregate '%s'",
aggName);
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype;
/*
* initval is potentially null, so don't try to access it as a struct
* field. Must do it the hard way with SysCacheGetAttr.
*/
textInitVal = SysCacheGetAttr(AGGNAME, tup,
Anum_pg_aggregate_agginitval,
isNull);
if (*isNull)
{
ReleaseSysCache(tup);
return (Datum) 0;
}
strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
ReleaseSysCache(tup);
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(transtype),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type %u", transtype);
typinput = ((Form_pg_type) GETSTRUCT(tup))->typinput;
typelem = ((Form_pg_type) GETSTRUCT(tup))->typelem;
ReleaseSysCache(tup);
initVal = OidFunctionCall3(typinput,
CStringGetDatum(strInitVal),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1));
pfree(strInitVal);
return initVal;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.69 2002/04/09 20:35:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.70 2002/04/11 19:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,7 +19,6 @@
#include "catalog/indexing.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "parser/parse_coerce.h"
@ -48,24 +47,25 @@ ProcedureCreate(const char *procedureName,
Oid languageObjectId,
const char *prosrc,
const char *probin,
bool isAgg,
bool trusted,
bool isImplicit,
bool isStrict,
char volatility,
int32 byte_pct,
int32 perbyte_cpu,
int32 percall_cpu,
int32 outin_ratio,
List *argList)
int parameterCount,
const Oid *parameterTypes)
{
int i;
Relation rel;
HeapTuple tup;
HeapTuple oldtup;
uint16 parameterCount;
char nulls[Natts_pg_proc];
Datum values[Natts_pg_proc];
char replaces[Natts_pg_proc];
List *x;
List *querytree_list;
Oid typev[FUNC_MAX_ARGS];
Oid relid;
@ -79,43 +79,14 @@ ProcedureCreate(const char *procedureName,
Assert(PointerIsValid(prosrc));
Assert(PointerIsValid(probin));
parameterCount = 0;
if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS)
elog(ERROR, "functions cannot have more than %d arguments",
FUNC_MAX_ARGS);
/* Make sure we have a zero-padded param type array */
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
foreach(x, argList)
{
TypeName *t = (TypeName *) lfirst(x);
Oid toid;
if (parameterCount >= FUNC_MAX_ARGS)
elog(ERROR, "functions cannot have more than %d arguments",
FUNC_MAX_ARGS);
toid = LookupTypeName(t);
if (OidIsValid(toid))
{
if (!get_typisdefined(toid))
elog(WARNING, "Argument type \"%s\" is only a shell",
TypeNameToString(t));
}
else
{
char *typnam = TypeNameToString(t);
if (strcmp(typnam, "opaque") == 0)
{
if (languageObjectId == SQLlanguageId)
elog(ERROR, "SQL functions cannot have arguments of type \"opaque\"");
toid = InvalidOid;
}
else
elog(ERROR, "Type \"%s\" does not exist", typnam);
}
if (t->setof)
elog(ERROR, "functions cannot accept set arguments");
typev[parameterCount++] = toid;
}
if (parameterCount > 0)
memcpy(typev, parameterTypes, parameterCount * sizeof(Oid));
if (languageObjectId == SQLlanguageId)
{
@ -248,12 +219,13 @@ ProcedureCreate(const char *procedureName,
values[i++] = ObjectIdGetDatum(procNamespace); /* pronamespace */
values[i++] = Int32GetDatum(GetUserId()); /* proowner */
values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
values[i++] = BoolGetDatum(false); /* proisinh (unused) */
values[i++] = BoolGetDatum(isAgg); /* proisagg */
values[i++] = BoolGetDatum(trusted); /* proistrusted */
values[i++] = BoolGetDatum(isImplicit); /* proimplicit */
values[i++] = BoolGetDatum(isStrict); /* proisstrict */
values[i++] = BoolGetDatum(returnsSet); /* proretset */
values[i++] = CharGetDatum(volatility); /* provolatile */
values[i++] = UInt16GetDatum(parameterCount); /* pronargs */
values[i++] = BoolGetDatum(returnsSet); /* proretset */
values[i++] = ObjectIdGetDatum(returnType); /* prorettype */
values[i++] = PointerGetDatum(typev); /* proargtypes */
values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
@ -298,6 +270,17 @@ ProcedureCreate(const char *procedureName,
elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
"\n\tUse DROP FUNCTION first.");
/* Can't change aggregate status, either */
if (oldproc->proisagg != isAgg)
{
if (oldproc->proisagg)
elog(ERROR, "function %s is an aggregate",
procedureName);
else
elog(ERROR, "function %s is not an aggregate",
procedureName);
}
/* do not change existing permissions, either */
replaces[Anum_pg_proc_proacl-1] = ' ';

View File

@ -7,7 +7,7 @@
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.39 2002/04/09 20:35:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.40 2002/04/11 19:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -25,15 +25,11 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_agg.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "parser/parse.h"
#include "rewrite/rewriteRemove.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
@ -573,7 +569,6 @@ CommentAggregate(List *aggregate, List *arguments, char *comment)
TypeName *aggtype = (TypeName *) lfirst(arguments);
Oid baseoid,
oid;
Oid classoid;
/* First, attempt to determine the base aggregate oid */
if (aggtype)
@ -581,18 +576,13 @@ CommentAggregate(List *aggregate, List *arguments, char *comment)
else
baseoid = InvalidOid;
/* Now, attempt to find the actual tuple in pg_aggregate */
/* Now, attempt to find the actual tuple in pg_proc */
oid = GetSysCacheOid(AGGNAME,
PointerGetDatum(strVal(lfirst(aggregate))), /* XXX */
ObjectIdGetDatum(baseoid),
0, 0);
if (!OidIsValid(oid))
agg_error("CommentAggregate", aggregate, baseoid);
oid = find_aggregate_func("CommentAggregate", aggregate, baseoid);
/* Next, validate the user's attempt to comment */
if (!pg_aggr_ownercheck(oid, GetUserId()))
if (!pg_proc_ownercheck(oid, GetUserId()))
{
if (baseoid == InvalidOid)
elog(ERROR, "you are not permitted to comment on aggregate %s for all types",
@ -602,14 +592,9 @@ CommentAggregate(List *aggregate, List *arguments, char *comment)
NameListToString(aggregate), format_type_be(baseoid));
}
/* pg_aggregate doesn't have a hard-coded OID, so must look it up */
classoid = get_relname_relid(AggregateRelationName, PG_CATALOG_NAMESPACE);
Assert(OidIsValid(classoid));
/* Call CreateComments() to create/drop the comments */
CreateComments(oid, classoid, 0, comment);
CreateComments(oid, RelOid_pg_proc, 0, comment);
}
/*

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.74 2002/04/09 20:35:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.75 2002/04/11 19:59:57 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@ -141,13 +141,56 @@ compute_return_type(TypeName *returnType, Oid languageOid,
*returnsSet_p = returnType->setof;
}
static void
compute_full_attributes(List *parameters,
int32 *byte_pct_p, int32 *perbyte_cpu_p,
int32 *percall_cpu_p, int32 *outin_ratio_p,
bool *isStrict_p, char *volatility_p)
/*
* Interpret the argument-types list of the CREATE FUNCTION statement.
*/
static int
compute_parameter_types(List *argTypes, Oid languageOid,
Oid *parameterTypes)
{
int parameterCount = 0;
List *x;
MemSet(parameterTypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
foreach(x, argTypes)
{
TypeName *t = (TypeName *) lfirst(x);
Oid toid;
if (parameterCount >= FUNC_MAX_ARGS)
elog(ERROR, "functions cannot have more than %d arguments",
FUNC_MAX_ARGS);
toid = LookupTypeName(t);
if (OidIsValid(toid))
{
if (!get_typisdefined(toid))
elog(WARNING, "Argument type \"%s\" is only a shell",
TypeNameToString(t));
}
else
{
char *typnam = TypeNameToString(t);
if (strcmp(typnam, "opaque") == 0)
{
if (languageOid == SQLlanguageId)
elog(ERROR, "SQL functions cannot have arguments of type \"opaque\"");
toid = InvalidOid;
}
else
elog(ERROR, "Type \"%s\" does not exist", typnam);
}
if (t->setof)
elog(ERROR, "functions cannot accept set arguments");
parameterTypes[parameterCount++] = toid;
}
return parameterCount;
}
/*-------------
* Interpret the parameters *parameters and return their contents as
* *byte_pct_p, etc.
@ -155,7 +198,10 @@ compute_full_attributes(List *parameters,
* These parameters supply optional information about a function.
* All have defaults if not specified.
*
* Note: currently, only two of these parameters actually do anything:
* Note: currently, only three of these parameters actually do anything:
*
* * isImplicit means the function may be used as an implicit type
* coercion.
*
* * isStrict means the function should not be called when any NULL
* inputs are present; instead a NULL result value should be assumed.
@ -168,6 +214,13 @@ compute_full_attributes(List *parameters,
* for a long time.
*------------
*/
static void
compute_full_attributes(List *parameters,
int32 *byte_pct_p, int32 *perbyte_cpu_p,
int32 *percall_cpu_p, int32 *outin_ratio_p,
bool *isImplicit_p, bool *isStrict_p,
char *volatility_p)
{
List *pl;
/* the defaults */
@ -175,6 +228,7 @@ compute_full_attributes(List *parameters,
*perbyte_cpu_p = PERBYTE_CPU;
*percall_cpu_p = PERCALL_CPU;
*outin_ratio_p = OUTIN_RATIO;
*isImplicit_p = false;
*isStrict_p = false;
*volatility_p = PROVOLATILE_VOLATILE;
@ -182,7 +236,9 @@ compute_full_attributes(List *parameters,
{
DefElem *param = (DefElem *) lfirst(pl);
if (strcasecmp(param->defname, "isstrict") == 0)
if (strcasecmp(param->defname, "implicitcoercion") == 0)
*isImplicit_p = true;
else if (strcasecmp(param->defname, "isstrict") == 0)
*isStrict_p = true;
else if (strcasecmp(param->defname, "isimmutable") == 0)
*volatility_p = PROVOLATILE_IMMUTABLE;
@ -276,11 +332,14 @@ CreateFunction(ProcedureStmt *stmt)
Oid languageOid;
char *funcname;
Oid namespaceId;
int parameterCount;
Oid parameterTypes[FUNC_MAX_ARGS];
int32 byte_pct,
perbyte_cpu,
percall_cpu,
outin_ratio;
bool isStrict;
bool isImplicit,
isStrict;
char volatility;
HeapTuple languageTuple;
Form_pg_language languageStruct;
@ -316,9 +375,13 @@ CreateFunction(ProcedureStmt *stmt)
compute_return_type(stmt->returnType, languageOid,
&prorettype, &returnsSet);
parameterCount = compute_parameter_types(stmt->argTypes, languageOid,
parameterTypes);
compute_full_attributes(stmt->withClause,
&byte_pct, &perbyte_cpu, &percall_cpu,
&outin_ratio, &isStrict, &volatility);
&outin_ratio, &isImplicit, &isStrict,
&volatility);
interpret_AS_clause(languageOid, languageName, stmt->as,
&prosrc_str, &probin_str);
@ -335,18 +398,20 @@ CreateFunction(ProcedureStmt *stmt)
languageOid,
prosrc_str, /* converted to text later */
probin_str, /* converted to text later */
false, /* not an aggregate */
true, /* (obsolete "trusted") */
isImplicit,
isStrict,
volatility,
byte_pct,
perbyte_cpu,
percall_cpu,
outin_ratio,
stmt->argTypes);
parameterCount,
parameterTypes);
}
/*
* DefineOperator
* this function extracts all the information from the

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.68 2002/04/09 20:35:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.69 2002/04/11 19:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -303,7 +303,9 @@ FuncIndexArgs(IndexInfo *indexInfo,
&true_typeids);
if (fdresult != FUNCDETAIL_NORMAL)
{
if (fdresult == FUNCDETAIL_COERCION)
if (fdresult == FUNCDETAIL_AGGREGATE)
elog(ERROR, "DefineIndex: functional index may not use an aggregate function");
else if (fdresult == FUNCDETAIL_COERCION)
elog(ERROR, "DefineIndex: functional index must use a real function, not a type coercion"
"\n\tTry specifying the index opclass you want to use, instead");
else

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.73 2002/04/09 20:35:48 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.74 2002/04/11 19:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -24,7 +24,6 @@
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
@ -381,6 +380,11 @@ RemoveFunction(List *functionName, /* function name to be removed */
elog(ERROR, "RemoveFunction: function '%s': permission denied",
NameListToString(functionName));
if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
elog(ERROR, "RemoveFunction: function '%s' is an aggregate"
"\n\tUse DROP AGGREGATE to remove it",
NameListToString(functionName));
if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
{
/* "Helpful" WARNING when removing a builtin function ... */
@ -404,6 +408,7 @@ RemoveAggregate(List *aggName, TypeName *aggType)
Relation relation;
HeapTuple tup;
Oid basetypeID;
Oid procOid;
/*
* if a basetype is passed in, then attempt to find an aggregate for
@ -413,23 +418,16 @@ RemoveAggregate(List *aggName, TypeName *aggType)
* a basetype of zero. This is valid. It means that the aggregate is
* to apply to all basetypes (eg, COUNT).
*/
if (aggType)
basetypeID = typenameTypeId(aggType);
else
basetypeID = InvalidOid;
relation = heap_openr(AggregateRelationName, RowExclusiveLock);
procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID);
tup = SearchSysCache(AGGNAME,
PointerGetDatum(strVal(llast(aggName))),
ObjectIdGetDatum(basetypeID),
0, 0);
/* Permission check */
if (!HeapTupleIsValid(tup))
agg_error("RemoveAggregate", aggName, basetypeID);
if (!pg_aggr_ownercheck(tup->t_data->t_oid, GetUserId()))
if (!pg_proc_ownercheck(procOid, GetUserId()))
{
if (basetypeID == InvalidOid)
elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied",
@ -439,8 +437,36 @@ RemoveAggregate(List *aggName, TypeName *aggType)
NameListToString(aggName), format_type_be(basetypeID));
}
/* Remove any comments related to this aggregate */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
/* Remove the pg_proc tuple */
relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
tup = SearchSysCache(PROCOID,
ObjectIdGetDatum(procOid),
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s",
NameListToString(aggName));
/* Delete any comments associated with this function */
DeleteComments(procOid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self);
ReleaseSysCache(tup);
heap_close(relation, RowExclusiveLock);
/* Remove the pg_aggregate tuple */
relation = heap_openr(AggregateRelationName, RowExclusiveLock);
tup = SearchSysCache(AGGFNOID,
ObjectIdGetDatum(procOid),
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "RemoveAggregate: couldn't find pg_aggregate tuple for %s",
NameListToString(aggName));
simple_heap_delete(relation, &tup->t_self);

View File

@ -46,7 +46,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.80 2002/03/20 19:43:54 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.81 2002/04/11 19:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -63,11 +63,13 @@
#include "parser/parse_expr.h"
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/tuplesort.h"
#include "utils/datum.h"
/*
* AggStatePerAggData - per-aggregate working state for the Agg scan
*/
@ -160,6 +162,7 @@ static void process_sorted_aggregate(AggState *aggstate,
AggStatePerAgg peraggstate);
static void finalize_aggregate(AggStatePerAgg peraggstate,
Datum *resultVal, bool *resultIsNull);
static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
/*
@ -244,7 +247,7 @@ advance_transition_function(AggStatePerAgg peraggstate,
* transValue has not been initialized. This is the first
* non-NULL input value. We use it as the initial value for
* transValue. (We already checked that the agg's input type
* is binary- compatible with its transtype, so straight copy
* is binary-compatible with its transtype, so straight copy
* here is OK.)
*
* We had better copy the datum if it is pass-by-ref, since the
@ -838,11 +841,11 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
{
Aggref *aggref = (Aggref *) lfirst(alist);
AggStatePerAgg peraggstate = &peragg[++aggno];
char *aggname = aggref->aggname;
HeapTuple aggTuple;
Form_pg_aggregate aggform;
Oid transfn_oid,
finalfn_oid;
Datum textInitVal;
/* Mark Aggref node with its associated index in the result array */
aggref->aggno = aggno;
@ -850,28 +853,34 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
/* Fill in the peraggstate data */
peraggstate->aggref = aggref;
aggTuple = SearchSysCache(AGGNAME,
PointerGetDatum(aggname),
ObjectIdGetDatum(aggref->basetype),
0, 0);
aggTuple = SearchSysCache(AGGFNOID,
ObjectIdGetDatum(aggref->aggfnoid),
0, 0, 0);
if (!HeapTupleIsValid(aggTuple))
elog(ERROR, "ExecAgg: cache lookup failed for aggregate %s(%s)",
aggname,
aggref->basetype ?
typeidTypeName(aggref->basetype) : (char *) "");
elog(ERROR, "ExecAgg: cache lookup failed for aggregate %u",
aggref->aggfnoid);
aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
get_typlenbyval(aggform->aggfinaltype,
get_typlenbyval(aggref->aggtype,
&peraggstate->resulttypeLen,
&peraggstate->resulttypeByVal);
get_typlenbyval(aggform->aggtranstype,
&peraggstate->transtypeLen,
&peraggstate->transtypeByVal);
peraggstate->initValue =
AggNameGetInitVal(aggname,
aggform->aggbasetype,
&peraggstate->initValueIsNull);
/*
* initval is potentially null, so don't try to access it as a struct
* field. Must do it the hard way with SysCacheGetAttr.
*/
textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
Anum_pg_aggregate_agginitval,
&peraggstate->initValueIsNull);
if (peraggstate->initValueIsNull)
peraggstate->initValue = (Datum) 0;
else
peraggstate->initValue = GetAggInitVal(textInitVal,
aggform->aggtranstype);
peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
@ -891,21 +900,21 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
{
/*
* Note: use the type from the input expression here, not
* aggform->aggbasetype, because the latter might be 0.
* from pg_proc.proargtypes, because the latter might be 0.
* (Consider COUNT(*).)
*/
Oid inputType = exprType(aggref->target);
if (!IsBinaryCompatible(inputType, aggform->aggtranstype))
elog(ERROR, "Aggregate %s needs to have compatible input type and transition type",
aggname);
elog(ERROR, "Aggregate %u needs to have compatible input type and transition type",
aggref->aggfnoid);
}
if (aggref->aggdistinct)
{
/*
* Note: use the type from the input expression here, not
* aggform->aggbasetype, because the latter might be 0.
* from pg_proc.proargtypes, because the latter might be 0.
* (Consider COUNT(*).)
*/
Oid inputType = exprType(aggref->target);
@ -932,6 +941,36 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
return TRUE;
}
static Datum
GetAggInitVal(Datum textInitVal, Oid transtype)
{
char *strInitVal;
HeapTuple tup;
Oid typinput,
typelem;
Datum initVal;
strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(transtype),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "GetAggInitVal: cache lookup failed on aggregate transition function return type %u", transtype);
typinput = ((Form_pg_type) GETSTRUCT(tup))->typinput;
typelem = ((Form_pg_type) GETSTRUCT(tup))->typelem;
ReleaseSysCache(tup);
initVal = OidFunctionCall3(typinput,
CStringGetDatum(strInitVal),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1));
pfree(strInitVal);
return initVal;
}
int
ExecCountSlotsAgg(Agg *node)
{
@ -985,3 +1024,21 @@ ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent)
if (((Plan *) node)->lefttree->chgParam == NULL)
ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
}
/*
* aggregate_dummy - dummy execution routine for aggregate functions
*
* This function is listed as the implementation (prosrc field) of pg_proc
* entries for aggregate functions. Its only purpose is to throw an error
* if someone mistakenly executes such a function in the normal way.
*
* Perhaps someday we could assign real meaning to the prosrc field of
* an aggregate?
*/
Datum
aggregate_dummy(PG_FUNCTION_ARGS)
{
elog(ERROR, "Aggregate function %u called as normal function",
fcinfo->flinfo->fn_oid);
return (Datum) 0; /* keep compiler quiet */
}

View 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.176 2002/04/09 20:35:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.177 2002/04/11 19:59:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -852,11 +852,7 @@ _copyAggref(Aggref *from)
{
Aggref *newnode = makeNode(Aggref);
/*
* copy remainder of node
*/
newnode->aggname = pstrdup(from->aggname);
newnode->basetype = from->basetype;
newnode->aggfnoid = from->aggfnoid;
newnode->aggtype = from->aggtype;
Node_Copy(from, newnode, target);
newnode->aggstar = from->aggstar;

View File

@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.124 2002/04/09 20:35:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.125 2002/04/11 19:59:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -220,9 +220,7 @@ _equalFunc(Func *a, Func *b)
static bool
_equalAggref(Aggref *a, Aggref *b)
{
if (strcmp(a->aggname, b->aggname) != 0)
return false;
if (a->basetype != b->basetype)
if (a->aggfnoid != b->aggfnoid)
return false;
if (a->aggtype != b->aggtype)
return false;

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.153 2002/04/09 20:35:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.154 2002/04/11 19:59:59 tgl Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
@ -785,10 +785,8 @@ _outConst(StringInfo str, Const *node)
static void
_outAggref(StringInfo str, Aggref *node)
{
appendStringInfo(str, " AGGREG :aggname ");
_outToken(str, node->aggname);
appendStringInfo(str, " :basetype %u :aggtype %u :target ",
node->basetype, node->aggtype);
appendStringInfo(str, " AGGREG :aggfnoid %u :aggtype %u :target ",
node->aggfnoid, node->aggtype);
_outNode(str, node->target);
appendStringInfo(str, " :aggstar %s :aggdistinct %s ",

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.118 2002/03/22 02:56:32 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.119 2002/04/11 20:00:00 tgl Exp $
*
* NOTES
* Most of the read functions for plan nodes are tested. (In fact, they
@ -1159,13 +1159,9 @@ _readAggref(void)
local_node = makeNode(Aggref);
token = pg_strtok(&length); /* eat :aggname */
token = pg_strtok(&length); /* get aggname */
local_node->aggname = debackslash(token, length);
token = pg_strtok(&length); /* eat :basetype */
token = pg_strtok(&length); /* get basetype */
local_node->basetype = atooid(token);
token = pg_strtok(&length); /* eat :aggfnoid */
token = pg_strtok(&length); /* get aggfnoid */
local_node->aggfnoid = atooid(token);
token = pg_strtok(&length); /* eat :aggtype */
token = pg_strtok(&length); /* get aggtype */

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.34 2002/03/12 00:51:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.35 2002/04/11 20:00:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -485,7 +485,7 @@ flatten_join_alias_var(Var *var, Query *root, int expandRTI)
if (subtype != vartype)
{
l_var = coerce_type(NULL, l_var, subtype,
vartype, vartypmod);
vartype, vartypmod, false);
l_var = coerce_type_typmod(NULL, l_var,
vartype, vartypmod);
}
@ -504,7 +504,7 @@ flatten_join_alias_var(Var *var, Query *root, int expandRTI)
if (subtype != vartype)
{
r_var = coerce_type(NULL, r_var, subtype,
vartype, vartypmod);
vartype, vartypmod, false);
r_var = coerce_type_typmod(NULL, r_var,
vartype, vartypmod);
}

View File

@ -8,24 +8,17 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.48 2002/04/09 20:35:52 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.49 2002/04/11 20:00:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
#include "parser/parse_agg.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "parser/parsetree.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
typedef struct
{
@ -185,70 +178,3 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual)
/* Release the list storage (but not the pointed-to expressions!) */
freeList(groupClauses);
}
Aggref *
ParseAgg(ParseState *pstate, List *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct)
{
HeapTuple aggtuple;
Form_pg_aggregate aggform;
Aggref *aggref;
aggtuple = SearchSysCache(AGGNAME,
PointerGetDatum(strVal(llast(aggname))),
ObjectIdGetDatum(basetype),
0, 0);
/* shouldn't happen --- caller should have checked already */
if (!HeapTupleIsValid(aggtuple))
agg_error("ParseAgg", aggname, basetype);
aggform = (Form_pg_aggregate) GETSTRUCT(aggtuple);
/*
* There used to be a really ugly hack for count(*) here.
*
* It's gone. Now, the grammar transforms count(*) into count(1), which
* does the right thing. (It didn't use to do the right thing,
* because the optimizer had the wrong ideas about semantics of
* queries without explicit variables. Fixed as of Oct 1999 --- tgl.)
*/
/*
* We assume caller has already checked that given args are compatible
* with the agg's basetype.
*/
aggref = makeNode(Aggref);
aggref->aggname = pstrdup(strVal(llast(aggname)));
aggref->basetype = aggform->aggbasetype;
aggref->aggtype = aggform->aggfinaltype;
aggref->target = lfirst(args);
aggref->aggstar = agg_star;
aggref->aggdistinct = agg_distinct;
ReleaseSysCache(aggtuple);
pstate->p_hasAggs = true;
return aggref;
}
/*
* Error message when aggregate lookup fails that gives details of the
* basetype
*/
void
agg_error(const char *caller, List *aggname, Oid basetypeID)
{
/*
* basetypeID that is Invalid (zero) means aggregate over all types.
* (count)
*/
if (basetypeID == InvalidOid)
elog(ERROR, "%s: aggregate '%s' for all types does not exist",
caller, NameListToString(aggname));
else
elog(ERROR, "%s: aggregate '%s' for type %s does not exist",
caller, NameListToString(aggname), format_type_be(basetypeID));
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.69 2002/04/09 20:35:52 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.70 2002/04/11 20:00:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -32,7 +32,7 @@ Oid PromoteTypeToNext(Oid inType);
static Oid PreferredType(CATEGORY category, Oid type);
static Node *build_func_call(Oid funcid, Oid rettype, List *args);
static Oid find_coercion_function(Oid targetTypeId, Oid inputTypeId,
Oid secondArgType);
Oid secondArgType, bool isExplicit);
/* coerce_type()
@ -40,7 +40,7 @@ static Oid find_coercion_function(Oid targetTypeId, Oid inputTypeId,
*/
Node *
coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
Oid targetTypeId, int32 atttypmod)
Oid targetTypeId, int32 atttypmod, bool isExplicit)
{
Node *result;
@ -131,7 +131,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
funcId = find_coercion_function(baseTypeId,
getBaseType(inputTypeId),
InvalidOid);
InvalidOid,
isExplicit);
if (!OidIsValid(funcId))
elog(ERROR, "coerce_type: no conversion function from %s to %s",
format_type_be(inputTypeId), format_type_be(targetTypeId));
@ -171,13 +172,18 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
*
* There are a few types which are known apriori to be convertible.
* We will check for those cases first, and then look for possible
* conversion functions.
* conversion functions.
*
* We must be told whether this is an implicit or explicit coercion
* (explicit being a CAST construct, explicit function call, etc).
* We will accept a wider set of coercion cases for an explicit coercion.
*
* Notes:
* This uses the same mechanism as the CAST() SQL construct in gram.y.
*/
bool
can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
bool isExplicit)
{
int i;
@ -230,7 +236,7 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
return false;
/*
* Else, try for explicit conversion using functions: look for a
* Else, try for run-time conversion using functions: look for a
* single-argument function named with the target type name and
* accepting the source type.
*
@ -238,7 +244,8 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
*/
funcId = find_coercion_function(getBaseType(targetTypeId),
getBaseType(inputTypeId),
InvalidOid);
InvalidOid,
isExplicit);
if (!OidIsValid(funcId))
return false;
}
@ -279,7 +286,8 @@ coerce_type_typmod(ParseState *pstate, Node *node,
/* If given type is a domain, use base type instead */
baseTypeId = getBaseType(targetTypeId);
funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID);
/* Note this is always implicit coercion */
funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID, false);
if (OidIsValid(funcId))
{
@ -321,9 +329,10 @@ coerce_to_boolean(ParseState *pstate, Node **pnode)
if (inputTypeId == BOOLOID)
return true; /* no work */
targetTypeId = BOOLOID;
if (!can_coerce_type(1, &inputTypeId, &targetTypeId))
if (!can_coerce_type(1, &inputTypeId, &targetTypeId, false))
return false; /* fail, but let caller choose error msg */
*pnode = coerce_type(pstate, *pnode, inputTypeId, targetTypeId, -1);
*pnode = coerce_type(pstate, *pnode, inputTypeId, targetTypeId, -1,
false);
return true;
}
@ -378,7 +387,7 @@ select_common_type(List *typeids, const char *context)
}
else if (IsPreferredType(pcategory, ntype)
&& !IsPreferredType(pcategory, ptype)
&& can_coerce_type(1, &ptype, &ntype))
&& can_coerce_type(1, &ptype, &ntype, false))
{
/*
* new one is preferred and can convert? then take it...
@ -424,8 +433,9 @@ coerce_to_common_type(ParseState *pstate, Node *node,
if (inputTypeId == targetTypeId)
return node; /* no work */
if (can_coerce_type(1, &inputTypeId, &targetTypeId))
node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1);
if (can_coerce_type(1, &inputTypeId, &targetTypeId, false))
node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
false);
else
{
elog(ERROR, "%s unable to convert to type \"%s\"",
@ -659,6 +669,9 @@ PreferredType(CATEGORY category, Oid type)
* A coercion function must be named after (the internal name of) its
* result type, and must accept exactly the specified input type. We
* also require it to be defined in the same namespace as its result type.
* Furthermore, unless we are doing explicit coercion the function must
* be marked as usable for implicit coercion --- this allows coercion
* functions to be provided that aren't implicitly invokable.
*
* This routine is also used to look for length-coercion functions, which
* are similar but accept a second argument. secondArgType is the type
@ -668,16 +681,16 @@ PreferredType(CATEGORY category, Oid type)
* If a function is found, return its pg_proc OID; else return InvalidOid.
*/
static Oid
find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType)
find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType,
bool isExplicit)
{
Oid funcid = InvalidOid;
Type targetType;
char *typname;
Oid typnamespace;
Oid oid_array[FUNC_MAX_ARGS];
int nargs;
HeapTuple ftup;
Form_pg_proc pform;
Oid funcid;
targetType = typeidType(targetTypeId);
typname = NameStr(((Form_pg_type) GETSTRUCT(targetType))->typname);
@ -698,21 +711,24 @@ find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType)
Int16GetDatum(nargs),
PointerGetDatum(oid_array),
ObjectIdGetDatum(typnamespace));
if (!HeapTupleIsValid(ftup))
{
ReleaseSysCache(targetType);
return InvalidOid;
}
/* Make sure the function's result type is as expected, too */
pform = (Form_pg_proc) GETSTRUCT(ftup);
if (pform->prorettype != targetTypeId)
if (HeapTupleIsValid(ftup))
{
Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
/* Make sure the function's result type is as expected */
if (pform->prorettype == targetTypeId && !pform->proretset &&
!pform->proisagg)
{
/* If needed, make sure it can be invoked implicitly */
if (isExplicit || pform->proimplicit)
{
/* Okay to use it */
funcid = ftup->t_data->t_oid;
}
}
ReleaseSysCache(ftup);
ReleaseSysCache(targetType);
return InvalidOid;
}
funcid = ftup->t_data->t_oid;
ReleaseSysCache(ftup);
ReleaseSysCache(targetType);
return funcid;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.113 2002/04/09 20:35:52 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.114 2002/04/11 20:00:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1174,7 +1174,8 @@ parser_typecast_expression(ParseState *pstate,
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
targetType, typename->typmod);
targetType, typename->typmod,
true); /* explicit coercion */
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),

View File

@ -8,23 +8,18 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.125 2002/04/09 20:35:53 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.126 2002/04/11 20:00:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "nodes/makefuncs.h"
#include "parser/parse_agg.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
@ -35,6 +30,7 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
static Node *ParseComplexProjection(ParseState *pstate,
char *funcname,
Node *first_arg);
@ -54,9 +50,6 @@ static int match_argtypes(int nargs,
static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
static FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids,
FuncCandidateList candidates);
static int agg_get_candidates(List *aggname, Oid typeId,
FuncCandidateList *candidates);
static Oid agg_select_candidate(Oid typeid, FuncCandidateList candidates);
/*
@ -89,14 +82,10 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
char *refname;
int nargs = length(fargs);
int argn;
Func *funcnode;
Oid oid_array[FUNC_MAX_ARGS];
Oid *true_oid_array;
Node *retval;
bool retset;
bool must_be_agg = agg_star || agg_distinct;
bool could_be_agg;
Expr *expr;
FuncDetailCode fdresult;
/*
@ -123,7 +112,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
* then the "function call" could be a projection. We also check
* that there wasn't any aggregate decoration.
*/
if (nargs == 1 && !must_be_agg && length(funcname) == 1)
if (nargs == 1 && !agg_star && !agg_distinct && length(funcname) == 1)
{
char *cname = strVal(lfirst(funcname));
@ -151,84 +140,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
}
}
/*
* See if it's an aggregate.
*/
if (must_be_agg)
{
/* We don't presently cope with, eg, foo(DISTINCT x,y) */
if (nargs != 1)
elog(ERROR, "Aggregate functions may only have one parameter");
/* Agg's argument can't be a relation name, either */
if (IsA(first_arg, RangeVar))
elog(ERROR, "Aggregate functions cannot be applied to relation names");
could_be_agg = true;
}
else
{
/* Try to parse as an aggregate if above-mentioned checks are OK */
could_be_agg = (nargs == 1) && !(IsA(first_arg, RangeVar));
}
if (could_be_agg)
{
Oid basetype = exprType(lfirst(fargs));
int ncandidates;
FuncCandidateList candidates;
/* try for exact match first... */
if (SearchSysCacheExists(AGGNAME,
PointerGetDatum(strVal(llast(funcname))),
ObjectIdGetDatum(basetype),
0, 0))
return (Node *) ParseAgg(pstate, funcname, basetype,
fargs, agg_star, agg_distinct);
/* check for aggregate-that-accepts-any-type (eg, COUNT) */
if (SearchSysCacheExists(AGGNAME,
PointerGetDatum(strVal(llast(funcname))),
ObjectIdGetDatum(0),
0, 0))
return (Node *) ParseAgg(pstate, funcname, 0,
fargs, agg_star, agg_distinct);
/*
* No exact match yet, so see if there is another entry in the
* aggregate table that is compatible. - thomas 1998-12-05
*/
ncandidates = agg_get_candidates(funcname, basetype, &candidates);
if (ncandidates > 0)
{
Oid type;
type = agg_select_candidate(basetype, candidates);
if (OidIsValid(type))
{
lfirst(fargs) = coerce_type(pstate, lfirst(fargs),
basetype, type, -1);
basetype = type;
return (Node *) ParseAgg(pstate, funcname, basetype,
fargs, agg_star, agg_distinct);
}
else
{
/* Multiple possible matches --- give up */
elog(ERROR, "Unable to select an aggregate function %s(%s)",
NameListToString(funcname), format_type_be(basetype));
}
}
if (must_be_agg)
{
/*
* No matching agg, but we had '*' or DISTINCT, so a plain
* function could not have been meant.
*/
elog(ERROR, "There is no aggregate function %s(%s)",
NameListToString(funcname), format_type_be(basetype));
}
}
/*
* Okay, it's not a column projection, so it must really be a function.
* Extract arg type info and transform RangeVar arguments into varnodes
@ -321,9 +232,22 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
* these cases, so why duplicate code...
*/
return coerce_type(pstate, lfirst(fargs),
oid_array[0], rettype, -1);
oid_array[0], rettype, -1, true);
}
if (fdresult != FUNCDETAIL_NORMAL)
else if (fdresult == FUNCDETAIL_NORMAL)
{
/*
* Normal function found; was there anything indicating it must be
* an aggregate?
*/
if (agg_star)
elog(ERROR, "%s(*) specified, but %s is not an aggregate function",
NameListToString(funcname), NameListToString(funcname));
if (agg_distinct)
elog(ERROR, "DISTINCT specified, but %s is not an aggregate function",
NameListToString(funcname));
}
else if (fdresult != FUNCDETAIL_AGGREGATE)
{
/*
* Oops. Time to die.
@ -341,167 +265,64 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
"\n\tYou may need to add explicit typecasts");
}
/* got it */
funcnode = makeNode(Func);
funcnode->funcid = funcid;
funcnode->functype = rettype;
funcnode->func_fcache = NULL;
/* perform the necessary typecasting of arguments */
make_arguments(pstate, nargs, fargs, oid_array, true_oid_array);
expr = makeNode(Expr);
expr->typeOid = rettype;
expr->opType = FUNC_EXPR;
expr->oper = (Node *) funcnode;
expr->args = fargs;
retval = (Node *) expr;
/*
* if the function returns a set of values, then we need to iterate
* over all the returned values in the executor, so we stick an iter
* node here. if it returns a singleton, then we don't need the iter
* node.
*/
if (retset)
/* build the appropriate output structure */
if (fdresult == FUNCDETAIL_NORMAL)
{
Iter *iter = makeNode(Iter);
Expr *expr = makeNode(Expr);
Func *funcnode = makeNode(Func);
iter->itertype = rettype;
iter->iterexpr = retval;
retval = (Node *) iter;
funcnode->funcid = funcid;
funcnode->functype = rettype;
funcnode->func_fcache = NULL;
expr->typeOid = rettype;
expr->opType = FUNC_EXPR;
expr->oper = (Node *) funcnode;
expr->args = fargs;
retval = (Node *) expr;
/*
* if the function returns a set of values, then we need to iterate
* over all the returned values in the executor, so we stick an iter
* node here. if it returns a singleton, then we don't need the iter
* node.
*/
if (retset)
{
Iter *iter = makeNode(Iter);
iter->itertype = rettype;
iter->iterexpr = retval;
retval = (Node *) iter;
}
}
else
{
/* aggregate function */
Aggref *aggref = makeNode(Aggref);
aggref->aggfnoid = funcid;
aggref->aggtype = rettype;
aggref->target = lfirst(fargs);
aggref->aggstar = agg_star;
aggref->aggdistinct = agg_distinct;
retval = (Node *) aggref;
if (retset)
elog(ERROR, "Aggregates may not return sets");
pstate->p_hasAggs = true;
}
return retval;
}
static int
agg_get_candidates(List *aggname,
Oid typeId,
FuncCandidateList *candidates)
{
Relation pg_aggregate_desc;
SysScanDesc pg_aggregate_scan;
HeapTuple tup;
int ncandidates = 0;
ScanKeyData aggKey[1];
*candidates = NULL;
ScanKeyEntryInitialize(&aggKey[0], 0,
Anum_pg_aggregate_aggname,
F_NAMEEQ,
NameGetDatum(strVal(llast(aggname))));
pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock);
pg_aggregate_scan = systable_beginscan(pg_aggregate_desc,
AggregateNameTypeIndex, true,
SnapshotNow,
1, aggKey);
while (HeapTupleIsValid(tup = systable_getnext(pg_aggregate_scan)))
{
Form_pg_aggregate agg = (Form_pg_aggregate) GETSTRUCT(tup);
FuncCandidateList current_candidate;
current_candidate = (FuncCandidateList)
palloc(sizeof(struct _FuncCandidateList));
current_candidate->args[0] = agg->aggbasetype;
current_candidate->next = *candidates;
*candidates = current_candidate;
ncandidates++;
}
systable_endscan(pg_aggregate_scan);
heap_close(pg_aggregate_desc, AccessShareLock);
return ncandidates;
} /* agg_get_candidates() */
/* agg_select_candidate()
*
* Try to choose only one candidate aggregate function from a list of
* possible matches. Return value is Oid of input type of aggregate
* if successful, else InvalidOid.
*/
static Oid
agg_select_candidate(Oid typeid, FuncCandidateList candidates)
{
FuncCandidateList current_candidate;
FuncCandidateList last_candidate;
Oid current_typeid;
int ncandidates;
CATEGORY category,
current_category;
/*
* First look for exact matches or binary compatible matches. (Of
* course exact matches shouldn't even get here, but anyway.)
*/
ncandidates = 0;
last_candidate = NULL;
for (current_candidate = candidates;
current_candidate != NULL;
current_candidate = current_candidate->next)
{
current_typeid = current_candidate->args[0];
if (IsBinaryCompatible(current_typeid, typeid))
{
last_candidate = current_candidate;
ncandidates++;
}
}
if (ncandidates == 1)
return last_candidate->args[0];
/*
* If no luck that way, look for candidates which allow coercion and
* have a preferred type. Keep all candidates if none match.
*/
category = TypeCategory(typeid);
ncandidates = 0;
last_candidate = NULL;
for (current_candidate = candidates;
current_candidate != NULL;
current_candidate = current_candidate->next)
{
current_typeid = current_candidate->args[0];
current_category = TypeCategory(current_typeid);
if (current_category == category
&& IsPreferredType(current_category, current_typeid)
&& can_coerce_type(1, &typeid, &current_typeid))
{
/* only one so far? then keep it... */
if (last_candidate == NULL)
{
candidates = current_candidate;
last_candidate = current_candidate;
ncandidates = 1;
}
/* otherwise, keep this one too... */
else
{
last_candidate->next = current_candidate;
last_candidate = current_candidate;
ncandidates++;
}
}
/* otherwise, don't bother keeping this one around... */
}
if (last_candidate) /* terminate rebuilt list */
last_candidate->next = NULL;
if (ncandidates == 1)
return candidates->args[0];
return InvalidOid;
} /* agg_select_candidate() */
/* match_argtypes()
*
* Given a list of possible typeid arrays to a function and an array of
@ -529,7 +350,8 @@ match_argtypes(int nargs,
current_candidate = next_candidate)
{
next_candidate = current_candidate->next;
if (can_coerce_type(nargs, input_typeids, current_candidate->args))
if (can_coerce_type(nargs, input_typeids, current_candidate->args,
false))
{
current_candidate->next = *candidates;
*candidates = current_candidate;
@ -1014,6 +836,7 @@ func_get_detail(List *funcname,
{
HeapTuple ftup;
Form_pg_proc pform;
FuncDetailCode result;
*funcid = best_candidate->oid;
*true_typeids = best_candidate->args;
@ -1026,8 +849,9 @@ func_get_detail(List *funcname,
pform = (Form_pg_proc) GETSTRUCT(ftup);
*rettype = pform->prorettype;
*retset = pform->proretset;
result = pform->proisagg ? FUNCDETAIL_AGGREGATE : FUNCDETAIL_NORMAL;
ReleaseSysCache(ftup);
return FUNCDETAIL_NORMAL;
return result;
}
return FUNCDETAIL_NOTFOUND;
@ -1294,7 +1118,8 @@ make_arguments(ParseState *pstate,
lfirst(current_fargs) = coerce_type(pstate,
lfirst(current_fargs),
input_typeids[i],
function_typeids[i], -1);
function_typeids[i], -1,
false);
}
}
}
@ -1450,6 +1275,58 @@ func_error(const char *caller, List *funcname,
}
}
/*
* find_aggregate_func
* Convenience routine to check that a function exists and is an
* aggregate.
*
* Note: basetype is InvalidOid if we are looking for an aggregate on
* all types.
*/
Oid
find_aggregate_func(const char *caller, List *aggname, Oid basetype)
{
Oid oid;
HeapTuple ftup;
Form_pg_proc pform;
oid = LookupFuncName(aggname, 1, &basetype);
if (!OidIsValid(oid))
{
if (basetype == InvalidOid)
elog(ERROR, "%s: aggregate '%s' for all types does not exist",
caller, NameListToString(aggname));
else
elog(ERROR, "%s: aggregate '%s' for type %s does not exist",
caller, NameListToString(aggname),
format_type_be(basetype));
}
/* Make sure it's an aggregate */
ftup = SearchSysCache(PROCOID,
ObjectIdGetDatum(oid),
0, 0, 0);
if (!HeapTupleIsValid(ftup)) /* should not happen */
elog(ERROR, "function %u not found", oid);
pform = (Form_pg_proc) GETSTRUCT(ftup);
if (!pform->proisagg)
{
if (basetype == InvalidOid)
elog(ERROR, "%s: function %s(*) is not an aggregate",
caller, NameListToString(aggname));
else
elog(ERROR, "%s: function %s(%s) is not an aggregate",
caller, NameListToString(aggname),
format_type_be(basetype));
}
ReleaseSysCache(ftup);
return oid;
}
/*
* LookupFuncName
* Given a possibly-qualified function name and a set of argument types,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.60 2002/03/21 16:01:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.61 2002/04/11 20:00:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -73,7 +73,8 @@ make_operand(char *opname,
{
/* must coerce? */
if (target_typeId != orig_typeId)
result = coerce_type(NULL, tree, orig_typeId, target_typeId, -1);
result = coerce_type(NULL, tree, orig_typeId, target_typeId, -1,
false);
else
result = tree;
}
@ -288,7 +289,7 @@ transformArraySubscripts(ParseState *pstate,
subexpr = transformExpr(pstate, ai->lidx);
/* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
INT4OID, -1);
INT4OID, -1, false);
if (subexpr == NULL)
elog(ERROR, "array index expressions must be integers");
}
@ -308,7 +309,7 @@ transformArraySubscripts(ParseState *pstate,
subexpr = transformExpr(pstate, ai->uidx);
/* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
INT4OID, -1);
INT4OID, -1, false);
if (subexpr == NULL)
elog(ERROR, "array index expressions must be integers");
upperIndexpr = lappend(upperIndexpr, subexpr);
@ -329,7 +330,7 @@ transformArraySubscripts(ParseState *pstate,
/* XXX fixme: need to get the array's atttypmod? */
assignFrom = CoerceTargetExpr(pstate, assignFrom,
typesource, typeneeded,
-1);
-1, false);
if (assignFrom == NULL)
elog(ERROR, "Array assignment requires type '%s'"
" but expression is of type '%s'"

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.53 2002/03/20 19:44:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.54 2002/04/11 20:00:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -265,7 +265,8 @@ oper_select_candidate(int nargs,
current_candidate != NULL;
current_candidate = current_candidate->next)
{
if (can_coerce_type(nargs, input_typeids, current_candidate->args))
if (can_coerce_type(nargs, input_typeids, current_candidate->args,
false))
{
if (last_candidate == NULL)
{

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.83 2002/04/09 20:35:53 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.84 2002/04/11 20:00:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -290,7 +290,8 @@ updateTargetListEntry(ParseState *pstate,
if (type_id != attrtype)
{
tle->expr = CoerceTargetExpr(pstate, tle->expr, type_id,
attrtype, attrtypmod);
attrtype, attrtypmod,
false);
if (tle->expr == NULL)
elog(ERROR, "column \"%s\" is of type '%s'"
" but expression is of type '%s'"
@ -327,10 +328,12 @@ CoerceTargetExpr(ParseState *pstate,
Node *expr,
Oid type_id,
Oid attrtype,
int32 attrtypmod)
int32 attrtypmod,
bool isExplicit)
{
if (can_coerce_type(1, &type_id, &attrtype))
expr = coerce_type(pstate, expr, type_id, attrtype, attrtypmod);
if (can_coerce_type(1, &type_id, &attrtype, isExplicit))
expr = coerce_type(pstate, expr, type_id, attrtype, attrtypmod,
isExplicit);
#ifndef DISABLE_STRING_HACKS
@ -345,8 +348,9 @@ CoerceTargetExpr(ParseState *pstate,
if (type_id == TEXTOID)
{
}
else if (can_coerce_type(1, &type_id, &text_id))
expr = coerce_type(pstate, expr, type_id, text_id, attrtypmod);
else if (can_coerce_type(1, &type_id, &text_id, isExplicit))
expr = coerce_type(pstate, expr, type_id, text_id, attrtypmod,
isExplicit);
else
expr = NULL;
}

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.101 2002/04/05 05:47:05 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.102 2002/04/11 20:00:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -476,7 +476,7 @@ build_column_default(Relation rel, int attrno)
if (exprtype != atttype)
{
expr = CoerceTargetExpr(NULL, expr, exprtype,
atttype, atttypmod);
atttype, atttypmod, false);
/*
* This really shouldn't fail; should have checked the

View File

@ -9,7 +9,7 @@
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.22 2002/04/05 00:31:28 tgl Exp $
# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.23 2002/04/11 20:00:04 tgl Exp $
#
#-------------------------------------------------------------------------
@ -88,6 +88,8 @@ trap 'echo "Caught signal." ; cleanup ; exit 1' 1 2 15
# deal with preprocessor statements first (before we sort the
# function table by oid).
#
# Note assumption here that prolang == $5 and INTERNALlanguageId == 12.
#
$AWK '
BEGIN { raw = 0; }
/^DATA/ { print; next; }
@ -161,6 +163,8 @@ cat > "$$-$OIDSFILE" <<FuNkYfMgRsTuFf
*/
FuNkYfMgRsTuFf
# Note assumption here that prosrc == $(NF-2).
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $RAWFILE | \
$AWK '
BEGIN { OFS = ""; }
@ -209,6 +213,8 @@ cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF
FuNkYfMgRtAbStUfF
# Note assumption here that prosrc == $(NF-2).
$AWK '{ print "extern Datum", $(NF-2), "(PG_FUNCTION_ARGS);"; }' $RAWFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then
@ -226,13 +232,16 @@ FuNkYfMgRtAbStUfF
# Note: using awk arrays to translate from pg_proc values to fmgrtab values
# may seem tedious, but avoid the temptation to write a quick x?y:z
# conditional expression instead. Not all awks have conditional expressions.
#
# Note assumptions here that prosrc == $(NF-2), pronargs == $12,
# proisstrict == $9, proretset == $10
$AWK 'BEGIN {
Bool["t"] = "true"
Bool["f"] = "false"
}
{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
$1, $(NF-2), $10, Bool[$8], Bool[$11], $(NF-2)
$1, $(NF-2), $12, Bool[$9], Bool[$10], $(NF-2)
}' $RAWFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then

View File

@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.95 2002/03/22 02:56:35 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.96 2002/04/11 20:00:04 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -130,6 +130,7 @@ static void get_names_for_var(Var *var, deparse_context *context,
char **refname, char **attname);
static void get_rule_expr(Node *node, deparse_context *context);
static void get_func_expr(Expr *expr, deparse_context *context);
static void get_agg_expr(Aggref *aggref, deparse_context *context);
static Node *strip_type_coercion(Node *expr, Oid resultType);
static void get_tle_expr(TargetEntry *tle, deparse_context *context);
static void get_const_expr(Const *constval, deparse_context *context);
@ -1694,18 +1695,7 @@ get_rule_expr(Node *node, deparse_context *context)
break;
case T_Aggref:
{
Aggref *aggref = (Aggref *) node;
appendStringInfo(buf, "%s(%s",
quote_identifier(aggref->aggname),
aggref->aggdistinct ? "DISTINCT " : "");
if (aggref->aggstar)
appendStringInfo(buf, "*");
else
get_rule_expr(aggref->target, context);
appendStringInfoChar(buf, ')');
}
get_agg_expr((Aggref *) node, context);
break;
case T_Iter:
@ -2000,6 +1990,45 @@ get_func_expr(Expr *expr, deparse_context *context)
ReleaseSysCache(proctup);
}
/* ----------
* get_agg_expr - Parse back an Aggref node
* ----------
*/
static void
get_agg_expr(Aggref *aggref, deparse_context *context)
{
StringInfo buf = context->buf;
HeapTuple proctup;
Form_pg_proc procStruct;
char *proname;
/*
* Get the aggregate's pg_proc tuple
*/
proctup = SearchSysCache(PROCOID,
ObjectIdGetDatum(aggref->aggfnoid),
0, 0, 0);
if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup for proc %u failed", aggref->aggfnoid);
procStruct = (Form_pg_proc) GETSTRUCT(proctup);
proname = NameStr(procStruct->proname);
/*
* Display it
*/
appendStringInfo(buf, "%s(%s",
quote_identifier(proname),
aggref->aggdistinct ? "DISTINCT " : "");
if (aggref->aggstar)
appendStringInfo(buf, "*");
else
get_rule_expr(aggref->target, context);
appendStringInfoChar(buf, ')');
ReleaseSysCache(proctup);
}
/*
* strip_type_coercion

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.42 2002/04/05 00:31:29 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.43 2002/04/11 20:00:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -58,16 +58,19 @@ SetDefine(char *querystr, Oid elemType)
true, /* returnsSet */
elemType, /* returnType */
SQLlanguageId, /* language */
querystr, /* sourceCode */
fileName, /* fileName */
querystr, /* prosrc */
fileName, /* probin */
false, /* not aggregate */
true, /* trusted */
false, /* not implicit coercion */
false, /* isStrict (irrelevant, no args) */
PROVOLATILE_VOLATILE, /* assume unsafe */
100, /* byte_pct */
0, /* perbyte_cpu */
0, /* percall_cpu */
100, /* outin_ratio */
NIL); /* argList */
0, /* parameterCount */
NULL); /* parameterTypes */
/*
* Since we're still inside this command of the transaction, we can't

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.88 2002/03/09 17:35:36 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.89 2002/04/11 20:00:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -307,19 +307,6 @@ _bpchar(PG_FUNCTION_ARGS)
}
/* bpchar_char()
* Convert bpchar(1) to char.
*
* If input is multiple chars, only the first is returned.
*/
Datum
bpchar_char(PG_FUNCTION_ARGS)
{
BpChar *s = PG_GETARG_BPCHAR_P(0);
PG_RETURN_CHAR(*VARDATA(s));
}
/* char_bpchar()
* Convert char to bpchar(1).
*/

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.75 2002/04/09 20:35:54 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.76 2002/04/11 20:00:06 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@ -93,22 +93,12 @@ struct cachedesc
};
static const struct cachedesc cacheinfo[] = {
{AggregateRelationName, /* AGGNAME */
AggregateNameTypeIndex,
0,
2,
{
Anum_pg_aggregate_aggname,
Anum_pg_aggregate_aggbasetype,
0,
0
}},
{AggregateRelationName, /* AGGOID */
AggregateOidIndex,
{AggregateRelationName, /* AGGFNOID */
AggregateFnoidIndex,
0,
1,
{
ObjectIdAttributeNumber,
Anum_pg_aggregate_aggfnoid,
0,
0,
0

View File

@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.246 2002/04/05 11:51:12 momjian Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.247 2002/04/11 20:00:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1873,7 +1873,7 @@ getAggregates(int *numAggs)
"(select usename from pg_user where aggowner = usesysid) as usename "
"from pg_aggregate");
}
else
else if (g_fout->remoteVersion < 70300)
{
appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, aggtransfn, "
"aggfinalfn, aggtranstype, aggbasetype, "
@ -1882,6 +1882,16 @@ getAggregates(int *numAggs)
"(select usename from pg_user where aggowner = usesysid) as usename "
"from pg_aggregate");
}
else
{
appendPQExpBuffer(query, "SELECT p.oid, proname as aggname, aggtransfn, "
"aggfinalfn, aggtranstype, proargtypes[0] as aggbasetype, "
"agginitval, "
"'t'::boolean as convertok, "
"(select usename from pg_user where proowner = usesysid) as usename "
"from pg_aggregate a, pg_proc p "
"where a.aggfnoid = p.oid");
}
res = PQexec(g_conn, query->data);
if (!res ||
@ -1960,6 +1970,7 @@ getFuncs(int *numFuncs)
int i_prosrc;
int i_probin;
int i_provolatile;
int i_isimplicit;
int i_isstrict;
int i_usename;
@ -1972,7 +1983,8 @@ getFuncs(int *numFuncs)
"proretset, proargtypes, prosrc, probin, "
"(select usename from pg_user where proowner = usesysid) as usename, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
"'f'::boolean as proisstrict "
"'f'::boolean as proimplicit, "
"'f'::boolean as proisstrict "
"from pg_proc "
"where pg_proc.oid > '%u'::oid",
g_last_builtin_oid);
@ -1984,6 +1996,7 @@ getFuncs(int *numFuncs)
"proretset, proargtypes, prosrc, probin, "
"(select usename from pg_user where proowner = usesysid) as usename, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
"'f'::boolean as proimplicit, "
"proisstrict "
"from pg_proc "
"where pg_proc.oid > '%u'::oid",
@ -1995,9 +2008,9 @@ getFuncs(int *numFuncs)
"SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
"proretset, proargtypes, prosrc, probin, "
"(select usename from pg_user where proowner = usesysid) as usename, "
"provolatile, proisstrict "
"provolatile, proimplicit, proisstrict "
"from pg_proc "
"where pg_proc.oid > '%u'::oid",
"where pg_proc.oid > '%u'::oid and not proisagg",
g_last_builtin_oid);
}
@ -2028,6 +2041,7 @@ getFuncs(int *numFuncs)
i_prosrc = PQfnumber(res, "prosrc");
i_probin = PQfnumber(res, "probin");
i_provolatile = PQfnumber(res, "provolatile");
i_isimplicit = PQfnumber(res, "proimplicit");
i_isstrict = PQfnumber(res, "proisstrict");
i_usename = PQfnumber(res, "usename");
@ -2045,6 +2059,7 @@ getFuncs(int *numFuncs)
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
finfo[i].provolatile = (PQgetvalue(res, i, i_provolatile))[0];
finfo[i].isimplicit = (strcmp(PQgetvalue(res, i, i_isimplicit), "t") == 0);
finfo[i].isstrict = (strcmp(PQgetvalue(res, i, i_isstrict), "t") == 0);
if (strlen(finfo[i].usename) == 0)
@ -3670,6 +3685,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
formatStringLiteral(q, func_lang, CONV_ALL);
if (finfo[i].provolatile != PROVOLATILE_VOLATILE ||
finfo[i].isimplicit ||
finfo[i].isstrict) /* OR in new attrs here */
{
appendPQExpBuffer(q, " WITH (");
@ -3692,11 +3708,18 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
exit_nicely();
}
if (finfo[i].isimplicit)
{
appendPQExpBuffer(q, "%s implicitCoercion", listSep);
listSep = listSepComma;
}
if (finfo[i].isstrict)
{
appendPQExpBuffer(q, "%s isStrict", listSep);
listSep = listSepComma;
}
appendPQExpBuffer(q, " )");
}
@ -4012,7 +4035,12 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
resetPQExpBuffer(q);
appendPQExpBuffer(q, "AGGREGATE %s", aggSig->data);
dumpComment(fout, q->data, agginfo[i].oid, "pg_aggregate", 0, NULL);
if (g_fout->remoteVersion < 70300)
dumpComment(fout, q->data, agginfo[i].oid, "pg_aggregate",
0, NULL);
else
dumpComment(fout, q->data, agginfo[i].oid, "pg_proc",
0, NULL);
}
destroyPQExpBuffer(q);

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_dump.h,v 1.80 2002/04/05 11:51:13 momjian Exp $
* $Id: pg_dump.h,v 1.81 2002/04/11 20:00:08 tgl Exp $
*
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
*
@ -73,6 +73,7 @@ typedef struct _funcInfo
char *probin;
char *usename;
char provolatile; /* Attr */
bool isimplicit; /* Attr */
bool isstrict; /* Attr */
int dumped; /* 1 if already dumped */
} FuncInfo;

View File

@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.48 2002/04/05 11:52:38 momjian Exp $
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.49 2002/04/11 20:00:08 tgl Exp $
*/
#include "postgres_fe.h"
#include "describe.h"
@ -43,22 +43,23 @@ describeAggregates(const char *name)
/*
* There are two kinds of aggregates: ones that work on particular
* types ones that work on all
* types and ones that work on all (denoted by input type = 0)
*/
snprintf(buf, sizeof(buf),
"SELECT a.aggname AS \"%s\",\n"
" CASE a.aggbasetype\n"
"SELECT p.proname AS \"%s\",\n"
" CASE p.proargtypes[0]\n"
" WHEN 0 THEN CAST('%s' AS text)\n"
" ELSE format_type(a.aggbasetype, NULL)\n"
" ELSE format_type(p.proargtypes[0], NULL)\n"
" END AS \"%s\",\n"
" obj_description(a.oid, 'pg_aggregate') as \"%s\"\n"
"FROM pg_aggregate a\n",
" obj_description(p.oid, 'pg_proc') as \"%s\"\n"
"FROM pg_proc p\n"
"WHERE p.proisagg\n",
_("Name"), _("(all types)"),
_("Data type"), _("Description"));
if (name)
{
strcat(buf, "WHERE a.aggname ~ '^");
strcat(buf, " AND p.proname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@ -112,12 +113,12 @@ describeFunctions(const char *name, bool verbose)
if (!verbose)
strcat(buf,
"\nFROM pg_proc p\n"
"WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '')\n");
"WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
else
strcat(buf,
"\nFROM pg_proc p, pg_language l, pg_user u\n"
"WHERE p.prolang = l.oid AND p.proowner = u.usesysid\n"
" AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '')\n");
" AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
if (name)
{
@ -347,16 +348,17 @@ objectDescription(const char *object)
"FROM (\n"
/* Aggregate descriptions */
" SELECT a.oid as oid, a.tableoid as tableoid,\n"
" CAST(a.aggname AS text) as name, CAST('%s' AS text) as object\n"
" FROM pg_aggregate a\n"
" SELECT p.oid as oid, p.tableoid as tableoid,\n"
" CAST(p.proname AS text) as name, CAST('%s' AS text) as object\n"
" FROM pg_proc p\n"
" WHERE p.proisagg\n"
/* Function descriptions (except in/outs for datatypes) */
"UNION ALL\n"
" SELECT p.oid as oid, p.tableoid as tableoid,\n"
" CAST(p.proname AS text) as name, CAST('%s' AS text) as object\n"
" FROM pg_proc p\n"
" WHERE p.pronargs = 0 or oidvectortypes(p.proargtypes) <> ''\n"
" WHERE (p.pronargs = 0 or oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n"
/* Operator descriptions (must get comment via associated function) */
"UNION ALL\n"

View File

@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.47 2002/04/01 03:34:27 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.48 2002/04/11 20:00:09 tgl Exp $
*/
/*----------------------------------------------------------------------
@ -132,7 +132,7 @@ typedef struct
} pgsql_thing_t;
pgsql_thing_t words_after_create[] = {
{"AGGREGATE", "SELECT distinct aggname FROM pg_aggregate WHERE substr(aggname,1,%d)='%s'"},
{"AGGREGATE", "SELECT distinct proname FROM pg_proc WHERE proisagg AND substr(proname,1,%d)='%s'"},
{"DATABASE", "SELECT datname FROM pg_database WHERE substr(datname,1,%d)='%s'"},
{"FUNCTION", "SELECT distinct proname FROM pg_proc WHERE substr(proname,1,%d)='%s'"},
{"GROUP", "SELECT groname FROM pg_group WHERE substr(groname,1,%d)='%s'"},

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.113 2002/04/05 00:31:32 tgl Exp $
* $Id: catversion.h,v 1.114 2002/04/11 20:00:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200204031
#define CATALOG_VERSION_NO 200204101
#endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: indexing.h,v 1.61 2002/04/05 00:31:32 tgl Exp $
* $Id: indexing.h,v 1.62 2002/04/11 20:00:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,7 +20,7 @@
/*
* Number of indices that exist for each system catalog
*/
#define Num_pg_aggregate_indices 2
#define Num_pg_aggregate_indices 1
#define Num_pg_am_indices 2
#define Num_pg_amop_indices 2
#define Num_pg_amproc_indices 1
@ -51,8 +51,7 @@
#define AccessMethodOperatorIndex "pg_amop_opc_opr_index"
#define AccessMethodStrategyIndex "pg_amop_opc_strategy_index"
#define AccessMethodProcedureIndex "pg_amproc_opc_procnum_index"
#define AggregateNameTypeIndex "pg_aggregate_name_type_index"
#define AggregateOidIndex "pg_aggregate_oid_index"
#define AggregateFnoidIndex "pg_aggregate_fnoid_index"
#define AmNameIndex "pg_am_name_index"
#define AmOidIndex "pg_am_oid_index"
#define AttrDefaultIndex "pg_attrdef_adrelid_adnum_index"
@ -145,8 +144,7 @@ extern void CatalogIndexInsert(Relation *idescs, int nIndices,
* that is just like in a normal 'create index' SQL command.
*/
DECLARE_UNIQUE_INDEX(pg_aggregate_name_type_index on pg_aggregate using btree(aggname name_ops, aggbasetype oid_ops));
DECLARE_UNIQUE_INDEX(pg_aggregate_oid_index on pg_aggregate using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_aggregate_fnoid_index on pg_aggregate using btree(aggfnoid oid_ops));
DECLARE_UNIQUE_INDEX(pg_am_name_index on pg_am using btree(amname name_ops));
DECLARE_UNIQUE_INDEX(pg_am_oid_index on pg_am using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_amop_opc_opr_index on pg_amop using btree(amopclaid oid_ops, amopopr oid_ops));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_aggregate.h,v 1.37 2002/04/09 20:35:54 tgl Exp $
* $Id: pg_aggregate.h,v 1.38 2002/04/11 20:00:11 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -31,25 +31,19 @@
*
* cpp turns this into typedef struct FormData_pg_aggregate
*
* aggname name of the aggregate
* aggowner owner (creator) of the aggregate
* aggfnoid pg_proc OID of the aggregate itself
* aggtransfn transition function
* aggfinalfn final function
* aggbasetype type of data on which aggregate operates
* aggtranstype type of aggregate's transition (state) data
* aggfinaltype type of aggregate's final result
* agginitval initial value for transition state
* ----------------------------------------------------------------
*/
CATALOG(pg_aggregate)
CATALOG(pg_aggregate) BKI_WITHOUT_OIDS
{
NameData aggname;
int4 aggowner;
regproc aggfnoid;
regproc aggtransfn;
regproc aggfinalfn;
Oid aggbasetype;
Oid aggtranstype;
Oid aggfinaltype;
text agginitval; /* VARIABLE LENGTH FIELD */
} FormData_pg_aggregate;
@ -65,15 +59,12 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
* ----------------
*/
#define Natts_pg_aggregate 8
#define Anum_pg_aggregate_aggname 1
#define Anum_pg_aggregate_aggowner 2
#define Anum_pg_aggregate_aggtransfn 3
#define Anum_pg_aggregate_aggfinalfn 4
#define Anum_pg_aggregate_aggbasetype 5
#define Anum_pg_aggregate_aggtranstype 6
#define Anum_pg_aggregate_aggfinaltype 7
#define Anum_pg_aggregate_agginitval 8
#define Natts_pg_aggregate 5
#define Anum_pg_aggregate_aggfnoid 1
#define Anum_pg_aggregate_aggtransfn 2
#define Anum_pg_aggregate_aggfinalfn 3
#define Anum_pg_aggregate_aggtranstype 4
#define Anum_pg_aggregate_agginitval 5
/* ----------------
@ -81,76 +72,82 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
* ---------------
*/
DATA(insert OID = 0 ( avg PGUID int8_accum numeric_avg 20 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( avg PGUID int4_avg_accum int8_avg 23 1016 1700 "{0,0}" ));
DATA(insert OID = 0 ( avg PGUID int2_avg_accum int8_avg 21 1016 1700 "{0,0}" ));
DATA(insert OID = 0 ( avg PGUID numeric_accum numeric_avg 1700 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( avg PGUID float4_accum float8_avg 700 1022 701 "{0,0,0}" ));
DATA(insert OID = 0 ( avg PGUID float8_accum float8_avg 701 1022 701 "{0,0,0}" ));
DATA(insert OID = 0 ( avg PGUID interval_accum interval_avg 1186 1187 1186 "{0 second,0 second}" ));
/* avg */
DATA(insert ( 2100 int8_accum numeric_avg 1231 "{0,0,0}" ));
DATA(insert ( 2101 int4_avg_accum int8_avg 1016 "{0,0}" ));
DATA(insert ( 2102 int2_avg_accum int8_avg 1016 "{0,0}" ));
DATA(insert ( 2103 numeric_accum numeric_avg 1231 "{0,0,0}" ));
DATA(insert ( 2104 float4_accum float8_avg 1022 "{0,0,0}" ));
DATA(insert ( 2105 float8_accum float8_avg 1022 "{0,0,0}" ));
DATA(insert ( 2106 interval_accum interval_avg 1187 "{0 second,0 second}" ));
DATA(insert OID = 0 ( sum PGUID int8_sum - 20 1700 1700 _null_ ));
DATA(insert OID = 0 ( sum PGUID int4_sum - 23 20 20 _null_ ));
DATA(insert OID = 0 ( sum PGUID int2_sum - 21 20 20 _null_ ));
DATA(insert OID = 0 ( sum PGUID float4pl - 700 700 700 _null_ ));
DATA(insert OID = 0 ( sum PGUID float8pl - 701 701 701 _null_ ));
DATA(insert OID = 0 ( sum PGUID cash_pl - 790 790 790 _null_ ));
DATA(insert OID = 0 ( sum PGUID interval_pl - 1186 1186 1186 _null_ ));
DATA(insert OID = 0 ( sum PGUID numeric_add - 1700 1700 1700 _null_ ));
/* sum */
DATA(insert ( 2107 int8_sum - 1700 _null_ ));
DATA(insert ( 2108 int4_sum - 20 _null_ ));
DATA(insert ( 2109 int2_sum - 20 _null_ ));
DATA(insert ( 2110 float4pl - 700 _null_ ));
DATA(insert ( 2111 float8pl - 701 _null_ ));
DATA(insert ( 2112 cash_pl - 790 _null_ ));
DATA(insert ( 2113 interval_pl - 1186 _null_ ));
DATA(insert ( 2114 numeric_add - 1700 _null_ ));
DATA(insert OID = 0 ( max PGUID int8larger - 20 20 20 _null_ ));
DATA(insert OID = 0 ( max PGUID int4larger - 23 23 23 _null_ ));
DATA(insert OID = 0 ( max PGUID int2larger - 21 21 21 _null_ ));
DATA(insert OID = 0 ( max PGUID oidlarger - 26 26 26 _null_ ));
DATA(insert OID = 0 ( max PGUID float4larger - 700 700 700 _null_ ));
DATA(insert OID = 0 ( max PGUID float8larger - 701 701 701 _null_ ));
DATA(insert OID = 0 ( max PGUID int4larger - 702 702 702 _null_ ));
DATA(insert OID = 0 ( max PGUID date_larger - 1082 1082 1082 _null_ ));
DATA(insert OID = 0 ( max PGUID time_larger - 1083 1083 1083 _null_ ));
DATA(insert OID = 0 ( max PGUID timetz_larger - 1266 1266 1266 _null_ ));
DATA(insert OID = 0 ( max PGUID cashlarger - 790 790 790 _null_ ));
DATA(insert OID = 0 ( max PGUID timestamp_larger - 1114 1114 1114 _null_ ));
DATA(insert OID = 0 ( max PGUID timestamptz_larger - 1184 1184 1184 _null_ ));
DATA(insert OID = 0 ( max PGUID interval_larger - 1186 1186 1186 _null_ ));
DATA(insert OID = 0 ( max PGUID text_larger - 25 25 25 _null_ ));
DATA(insert OID = 0 ( max PGUID numeric_larger - 1700 1700 1700 _null_ ));
/* max */
DATA(insert ( 2115 int8larger - 20 _null_ ));
DATA(insert ( 2116 int4larger - 23 _null_ ));
DATA(insert ( 2117 int2larger - 21 _null_ ));
DATA(insert ( 2118 oidlarger - 26 _null_ ));
DATA(insert ( 2119 float4larger - 700 _null_ ));
DATA(insert ( 2120 float8larger - 701 _null_ ));
DATA(insert ( 2121 int4larger - 702 _null_ ));
DATA(insert ( 2122 date_larger - 1082 _null_ ));
DATA(insert ( 2123 time_larger - 1083 _null_ ));
DATA(insert ( 2124 timetz_larger - 1266 _null_ ));
DATA(insert ( 2125 cashlarger - 790 _null_ ));
DATA(insert ( 2126 timestamp_larger - 1114 _null_ ));
DATA(insert ( 2127 timestamptz_larger - 1184 _null_ ));
DATA(insert ( 2128 interval_larger - 1186 _null_ ));
DATA(insert ( 2129 text_larger - 25 _null_ ));
DATA(insert ( 2130 numeric_larger - 1700 _null_ ));
DATA(insert OID = 0 ( min PGUID int8smaller - 20 20 20 _null_ ));
DATA(insert OID = 0 ( min PGUID int4smaller - 23 23 23 _null_ ));
DATA(insert OID = 0 ( min PGUID int2smaller - 21 21 21 _null_ ));
DATA(insert OID = 0 ( min PGUID oidsmaller - 26 26 26 _null_ ));
DATA(insert OID = 0 ( min PGUID float4smaller - 700 700 700 _null_ ));
DATA(insert OID = 0 ( min PGUID float8smaller - 701 701 701 _null_ ));
DATA(insert OID = 0 ( min PGUID int4smaller - 702 702 702 _null_ ));
DATA(insert OID = 0 ( min PGUID date_smaller - 1082 1082 1082 _null_ ));
DATA(insert OID = 0 ( min PGUID time_smaller - 1083 1083 1083 _null_ ));
DATA(insert OID = 0 ( min PGUID timetz_smaller - 1266 1266 1266 _null_ ));
DATA(insert OID = 0 ( min PGUID cashsmaller - 790 790 790 _null_ ));
DATA(insert OID = 0 ( min PGUID timestamp_smaller - 1114 1114 1114 _null_ ));
DATA(insert OID = 0 ( min PGUID timestamptz_smaller - 1184 1184 1184 _null_ ));
DATA(insert OID = 0 ( min PGUID interval_smaller - 1186 1186 1186 _null_ ));
DATA(insert OID = 0 ( min PGUID text_smaller - 25 25 25 _null_ ));
DATA(insert OID = 0 ( min PGUID numeric_smaller - 1700 1700 1700 _null_ ));
/* min */
DATA(insert ( 2131 int8smaller - 20 _null_ ));
DATA(insert ( 2132 int4smaller - 23 _null_ ));
DATA(insert ( 2133 int2smaller - 21 _null_ ));
DATA(insert ( 2134 oidsmaller - 26 _null_ ));
DATA(insert ( 2135 float4smaller - 700 _null_ ));
DATA(insert ( 2136 float8smaller - 701 _null_ ));
DATA(insert ( 2137 int4smaller - 702 _null_ ));
DATA(insert ( 2138 date_smaller - 1082 _null_ ));
DATA(insert ( 2139 time_smaller - 1083 _null_ ));
DATA(insert ( 2140 timetz_smaller - 1266 _null_ ));
DATA(insert ( 2141 cashsmaller - 790 _null_ ));
DATA(insert ( 2142 timestamp_smaller - 1114 _null_ ));
DATA(insert ( 2143 timestamptz_smaller - 1184 _null_ ));
DATA(insert ( 2144 interval_smaller - 1186 _null_ ));
DATA(insert ( 2145 text_smaller - 25 _null_ ));
DATA(insert ( 2146 numeric_smaller - 1700 _null_ ));
/*
* Using int8inc for count() is cheating a little, since it really only
* takes 1 parameter not 2, but nodeAgg.c won't complain ...
*/
DATA(insert OID = 0 ( count PGUID int8inc - 0 20 20 0 ));
DATA(insert ( 2147 int8inc - 20 0 ));
DATA(insert OID = 0 ( variance PGUID int8_accum numeric_variance 20 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( variance PGUID int4_accum numeric_variance 23 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( variance PGUID int2_accum numeric_variance 21 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( variance PGUID float4_accum float8_variance 700 1022 701 "{0,0,0}" ));
DATA(insert OID = 0 ( variance PGUID float8_accum float8_variance 701 1022 701 "{0,0,0}" ));
DATA(insert OID = 0 ( variance PGUID numeric_accum numeric_variance 1700 1231 1700 "{0,0,0}" ));
/* variance */
DATA(insert ( 2148 int8_accum numeric_variance 1231 "{0,0,0}" ));
DATA(insert ( 2149 int4_accum numeric_variance 1231 "{0,0,0}" ));
DATA(insert ( 2150 int2_accum numeric_variance 1231 "{0,0,0}" ));
DATA(insert ( 2151 float4_accum float8_variance 1022 "{0,0,0}" ));
DATA(insert ( 2152 float8_accum float8_variance 1022 "{0,0,0}" ));
DATA(insert ( 2153 numeric_accum numeric_variance 1231 "{0,0,0}" ));
DATA(insert OID = 0 ( stddev PGUID int8_accum numeric_stddev 20 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( stddev PGUID int4_accum numeric_stddev 23 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( stddev PGUID int2_accum numeric_stddev 21 1231 1700 "{0,0,0}" ));
DATA(insert OID = 0 ( stddev PGUID float4_accum float8_stddev 700 1022 701 "{0,0,0}" ));
DATA(insert OID = 0 ( stddev PGUID float8_accum float8_stddev 701 1022 701 "{0,0,0}" ));
DATA(insert OID = 0 ( stddev PGUID numeric_accum numeric_stddev 1700 1231 1700 "{0,0,0}" ));
/* stddev */
DATA(insert ( 2154 int8_accum numeric_stddev 1231 "{0,0,0}" ));
DATA(insert ( 2155 int4_accum numeric_stddev 1231 "{0,0,0}" ));
DATA(insert ( 2156 int2_accum numeric_stddev 1231 "{0,0,0}" ));
DATA(insert ( 2157 float4_accum float8_stddev 1022 "{0,0,0}" ));
DATA(insert ( 2158 float8_accum float8_stddev 1022 "{0,0,0}" ));
DATA(insert ( 2159 numeric_accum numeric_stddev 1231 "{0,0,0}" ));
/*
* prototypes for functions in pg_aggregate.c
@ -163,7 +160,4 @@ extern void AggregateCreate(const char *aggName,
Oid aggTransType,
const char *agginitval);
extern Datum AggNameGetInitVal(char *aggName, Oid basetype,
bool *isNull);
#endif /* PG_AGGREGATE_H */

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_attribute.h,v 1.89 2002/04/05 00:31:33 tgl Exp $
* $Id: pg_attribute.h,v 1.90 2002/04/11 20:00:11 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -298,41 +298,43 @@ DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
{ 1255, {"pronamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"proowner"}, 23, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prolang"}, 26, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"proisinh"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proisagg"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proistrusted"}, 16, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proisstrict"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"provolatile"}, 18, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"pronargs"}, 21, 0, 2, 9, 0, -1, -1, true, 'p', false, 's', false, false }, \
{ 1255, {"proretset"}, 16, 0, 1, 10, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"prorettype"}, 26, 0, 4, 11, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', false, 'i', false, false }, \
{ 1255, {"probyte_pct"}, 23, 0, 4, 13, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"properbyte_cpu"}, 23, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"propercall_cpu"}, 23, 0, 4, 15, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prooutin_ratio"}, 23, 0, 4, 16, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prosrc"}, 25, 0, -1, 17, 0, -1, -1, false, 'x', false, 'i', false, false }, \
{ 1255, {"probin"}, 17, 0, -1, 18, 0, -1, -1, false, 'x', false, 'i', false, false }, \
{ 1255, {"proacl"}, 1034, 0, -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false }
{ 1255, {"proimplicit"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proisstrict"}, 16, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proretset"}, 16, 0, 1, 9, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"provolatile"}, 18, 0, 1, 10, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"pronargs"}, 21, 0, 2, 11, 0, -1, -1, true, 'p', false, 's', false, false }, \
{ 1255, {"prorettype"}, 26, 0, 4, 12, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 13, 0, -1, -1, false, 'p', false, 'i', false, false }, \
{ 1255, {"probyte_pct"}, 23, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"properbyte_cpu"}, 23, 0, 4, 15, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"propercall_cpu"}, 23, 0, 4, 16, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prooutin_ratio"}, 23, 0, 4, 17, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prosrc"}, 25, 0, -1, 18, 0, -1, -1, false, 'x', false, 'i', false, false }, \
{ 1255, {"probin"}, 17, 0, -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false }, \
{ 1255, {"proacl"}, 1034, 0, -1, 20, 0, -1, -1, false, 'x', false, 'i', false, false }
DATA(insert ( 1255 proname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1255 pronamespace 26 0 4 2 0 -1 -1 t p f i f f));
DATA(insert ( 1255 proowner 23 0 4 3 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prolang 26 0 4 4 0 -1 -1 t p f i f f));
DATA(insert ( 1255 proisinh 16 0 1 5 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proisagg 16 0 1 5 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proistrusted 16 0 1 6 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proisstrict 16 0 1 7 0 -1 -1 t p f c f f));
DATA(insert ( 1255 provolatile 18 0 1 8 0 -1 -1 t p f c f f));
DATA(insert ( 1255 pronargs 21 0 2 9 0 -1 -1 t p f s f f));
DATA(insert ( 1255 proretset 16 0 1 10 0 -1 -1 t p f c f f));
DATA(insert ( 1255 prorettype 26 0 4 11 0 -1 -1 t p f i f f));
DATA(insert ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 12 0 -1 -1 f p f i f f));
DATA(insert ( 1255 probyte_pct 23 0 4 13 0 -1 -1 t p f i f f));
DATA(insert ( 1255 properbyte_cpu 23 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1255 propercall_cpu 23 0 4 15 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prooutin_ratio 23 0 4 16 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prosrc 25 0 -1 17 0 -1 -1 f x f i f f));
DATA(insert ( 1255 probin 17 0 -1 18 0 -1 -1 f x f i f f));
DATA(insert ( 1255 proacl 1034 0 -1 19 0 -1 -1 f x f i f f));
DATA(insert ( 1255 proimplicit 16 0 1 7 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proisstrict 16 0 1 8 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proretset 16 0 1 9 0 -1 -1 t p f c f f));
DATA(insert ( 1255 provolatile 18 0 1 10 0 -1 -1 t p f c f f));
DATA(insert ( 1255 pronargs 21 0 2 11 0 -1 -1 t p f s f f));
DATA(insert ( 1255 prorettype 26 0 4 12 0 -1 -1 t p f i f f));
DATA(insert ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 13 0 -1 -1 f p f i f f));
DATA(insert ( 1255 probyte_pct 23 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1255 properbyte_cpu 23 0 4 15 0 -1 -1 t p f i f f));
DATA(insert ( 1255 propercall_cpu 23 0 4 16 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prooutin_ratio 23 0 4 17 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prosrc 25 0 -1 18 0 -1 -1 f x f i f f));
DATA(insert ( 1255 probin 17 0 -1 19 0 -1 -1 f x f i f f));
DATA(insert ( 1255 proacl 1034 0 -1 20 0 -1 -1 f x f i f f));
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_class.h,v 1.65 2002/04/05 00:31:33 tgl Exp $
* $Id: pg_class.h,v 1.66 2002/04/11 20:00:11 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -138,7 +138,7 @@ DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 f f r 23 0 0 0
DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 19 0 0 0 0 0 t f f f _null_ ));
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 20 0 0 0 0 0 t f f f _null_ ));
DESCR("");
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 f f r 24 0 0 0 0 0 t f f f _null_ ));
DESCR("");

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_operator.h,v 1.100 2002/03/29 19:06:19 tgl Exp $
* $Id: pg_operator.h,v 1.101 2002/04/11 20:00:11 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -289,10 +289,10 @@ DATA(insert OID = 612 ( ">=" PGUID 0 b t f 26 26 16 611 609 0 0 oidge s
#define MAX_OIDCMP 612 /* used by cache code */
DATA(insert OID = 644 ( "<>" PGUID 0 b t f 30 30 16 644 649 0 0 oidvectorne neqsel neqjoinsel ));
DATA(insert OID = 645 ( "<" PGUID 0 b t f 30 30 16 646 648 0 0 oidvectorlt - - ));
DATA(insert OID = 646 ( ">" PGUID 0 b t f 30 30 16 645 647 0 0 oidvectorgt - - ));
DATA(insert OID = 647 ( "<=" PGUID 0 b t f 30 30 16 648 646 0 0 oidvectorle - - ));
DATA(insert OID = 648 ( ">=" PGUID 0 b t f 30 30 16 647 645 0 0 oidvectorge - - ));
DATA(insert OID = 645 ( "<" PGUID 0 b t f 30 30 16 646 648 0 0 oidvectorlt scalarltsel scalarltjoinsel ));
DATA(insert OID = 646 ( ">" PGUID 0 b t f 30 30 16 645 647 0 0 oidvectorgt scalargtsel scalargtjoinsel ));
DATA(insert OID = 647 ( "<=" PGUID 0 b t f 30 30 16 648 646 0 0 oidvectorle scalarltsel scalarltjoinsel ));
DATA(insert OID = 648 ( ">=" PGUID 0 b t f 30 30 16 647 645 0 0 oidvectorge scalargtsel scalargtjoinsel ));
DATA(insert OID = 649 ( "=" PGUID 0 b t t 30 30 16 649 644 645 645 oidvectoreq eqsel eqjoinsel ));
DATA(insert OID = 613 ( "<->" PGUID 0 b t f 600 628 701 0 0 0 0 dist_pl - - ));

File diff suppressed because it is too large Load Diff

View File

@ -7,13 +7,14 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodeAgg.h,v 1.15 2001/11/05 17:46:33 momjian Exp $
* $Id: nodeAgg.h,v 1.16 2002/04/11 20:00:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef NODEAGG_H
#define NODEAGG_H
#include "fmgr.h"
#include "nodes/plannodes.h"
extern TupleTableSlot *ExecAgg(Agg *node);
@ -22,4 +23,6 @@ extern int ExecCountSlotsAgg(Agg *node);
extern void ExecEndAgg(Agg *node);
extern void ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent);
extern Datum aggregate_dummy(PG_FUNCTION_ARGS);
#endif /* NODEAGG_H */

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: primnodes.h,v 1.60 2002/03/26 19:16:53 tgl Exp $
* $Id: primnodes.h,v 1.61 2002/04/11 20:00:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -322,13 +322,9 @@ typedef struct Iter
typedef struct Aggref
{
NodeTag type;
char *aggname; /* name of the aggregate */
Oid basetype; /* base type Oid of the aggregate (ie,
* input type) */
Oid aggtype; /* type Oid of final result of the
* aggregate */
Node *target; /* attribute or expression we are
* aggregating on */
Oid aggfnoid; /* pg_proc Oid of the aggregate */
Oid aggtype; /* type Oid of result of the aggregate */
Node *target; /* expression we are aggregating on */
bool aggstar; /* TRUE if argument was really '*' */
bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */
int aggno; /* workspace for executor (see nodeAgg.c) */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_agg.h,v 1.22 2002/04/09 20:35:55 tgl Exp $
* $Id: parse_agg.h,v 1.23 2002/04/11 20:00:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,10 +16,6 @@
#include "parser/parse_node.h"
extern void AddAggToParseState(ParseState *pstate, Aggref *aggref);
extern void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual);
extern Aggref *ParseAgg(ParseState *pstate, List *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct);
extern void agg_error(const char *caller, List *aggname, Oid basetypeID);
#endif /* PARSE_AGG_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_coerce.h,v 1.41 2002/03/20 19:45:07 tgl Exp $
* $Id: parse_coerce.h,v 1.42 2002/04/11 20:00:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -38,9 +38,10 @@ extern bool IsBinaryCompatible(Oid type1, Oid type2);
extern bool IsPreferredType(CATEGORY category, Oid type);
extern CATEGORY TypeCategory(Oid type);
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids);
extern bool can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
bool isExplicit);
extern Node *coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
Oid targetTypeId, int32 atttypmod);
Oid targetTypeId, int32 atttypmod, bool isExplicit);
extern Node *coerce_type_typmod(ParseState *pstate, Node *node,
Oid targetTypeId, int32 atttypmod);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_func.h,v 1.38 2002/04/09 20:35:55 tgl Exp $
* $Id: parse_func.h,v 1.39 2002/04/11 20:00:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -42,7 +42,8 @@ typedef struct _CandidateList
typedef enum
{
FUNCDETAIL_NOTFOUND, /* no suitable interpretation */
FUNCDETAIL_NORMAL, /* found a matching function */
FUNCDETAIL_NORMAL, /* found a matching regular function */
FUNCDETAIL_AGGREGATE, /* found a matching aggregate function */
FUNCDETAIL_COERCION /* it's a type coercion request */
} FuncDetailCode;
@ -62,6 +63,9 @@ extern void func_error(const char *caller, List *funcname,
int nargs, const Oid *argtypes,
const char *msg);
extern Oid find_aggregate_func(const char *caller, List *aggname,
Oid basetype);
extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes);
extern Oid LookupFuncNameTypeNames(List *funcname, List *argtypes,
bool opaqueOK, const char *caller);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_target.h,v 1.23 2001/11/05 17:46:35 momjian Exp $
* $Id: parse_target.h,v 1.24 2002/04/11 20:00:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -24,7 +24,8 @@ extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle,
char *colname, int attrno,
List *indirection);
extern Node *CoerceTargetExpr(ParseState *pstate, Node *expr,
Oid type_id, Oid attrtype, int32 attrtypmod);
Oid type_id, Oid attrtype, int32 attrtypmod,
bool isExplicit);
extern List *checkInsertTargets(ParseState *pstate, List *cols,
List **attrnos);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: acl.h,v 1.41 2002/03/21 23:27:25 tgl Exp $
* $Id: acl.h,v 1.42 2002/04/11 20:00:17 tgl Exp $
*
* NOTES
* For backward-compatibility purposes we have to allow there
@ -209,6 +209,5 @@ extern bool pg_class_ownercheck(Oid class_oid, Oid userid);
extern bool pg_type_ownercheck(Oid type_oid, Oid userid);
extern bool pg_oper_ownercheck(Oid oper_oid, Oid userid);
extern bool pg_proc_ownercheck(Oid proc_oid, Oid userid);
extern bool pg_aggr_ownercheck(Oid aggr_oid, Oid userid);
#endif /* ACL_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.175 2002/04/01 03:34:27 tgl Exp $
* $Id: builtins.h,v 1.176 2002/04/11 20:00:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -363,7 +363,6 @@ extern Datum bpcharout(PG_FUNCTION_ARGS);
extern Datum bpchar(PG_FUNCTION_ARGS);
extern Datum _bpchar(PG_FUNCTION_ARGS);
extern Datum char_bpchar(PG_FUNCTION_ARGS);
extern Datum bpchar_char(PG_FUNCTION_ARGS);
extern Datum name_bpchar(PG_FUNCTION_ARGS);
extern Datum bpchar_name(PG_FUNCTION_ARGS);
extern Datum bpchareq(PG_FUNCTION_ARGS);

View File

@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: syscache.h,v 1.43 2002/04/09 20:35:55 tgl Exp $
* $Id: syscache.h,v 1.44 2002/04/11 20:00:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -28,37 +28,36 @@
* Keep them in alphabetical order.
*/
#define AGGNAME 0
#define AGGOID 1
#define AMNAME 2
#define AMOID 3
#define AMOPOPID 4
#define AMOPSTRATEGY 5
#define AMPROCNUM 6
#define ATTNAME 7
#define ATTNUM 8
#define CLAAMNAME 9
#define CLAOID 10
#define GRONAME 11
#define GROSYSID 12
#define INDEXRELID 13
#define INHRELID 14
#define LANGNAME 15
#define LANGOID 16
#define NAMESPACENAME 17
#define NAMESPACEOID 18
#define OPERNAME 19
#define OPEROID 20
#define PROCNAMENSP 21
#define PROCOID 22
#define RELNAMENSP 23
#define RELOID 24
#define RULENAME 25
#define SHADOWNAME 26
#define SHADOWSYSID 27
#define STATRELATT 28
#define TYPENAMENSP 29
#define TYPEOID 30
#define AGGFNOID 0
#define AMNAME 1
#define AMOID 2
#define AMOPOPID 3
#define AMOPSTRATEGY 4
#define AMPROCNUM 5
#define ATTNAME 6
#define ATTNUM 7
#define CLAAMNAME 8
#define CLAOID 9
#define GRONAME 10
#define GROSYSID 11
#define INDEXRELID 12
#define INHRELID 13
#define LANGNAME 14
#define LANGOID 15
#define NAMESPACENAME 16
#define NAMESPACEOID 17
#define OPERNAME 18
#define OPEROID 19
#define PROCNAMENSP 20
#define PROCOID 21
#define RELNAMENSP 22
#define RELOID 23
#define RULENAME 24
#define SHADOWNAME 25
#define SHADOWSYSID 26
#define STATRELATT 27
#define TYPENAMENSP 28
#define TYPEOID 29
extern void InitCatalogCache(void);

View File

@ -101,10 +101,11 @@ def list_lang_func(pgcnx, l):
# lists all the aggregate functions and the type to which they can be applied
def list_agg_func(pgcnx):
result = pgcnx.query("""SELECT a.aggname, t.typname
FROM pg_aggregate a, pg_type t
WHERE a.aggbasetype = t.oid
ORDER BY aggname, typname""")
result = pgcnx.query("""SELECT p.proname, t.typname
FROM pg_aggregate a, pg_proc p, pg_type t
WHERE a.aggfnoid = p.oid
and p.proargtypes[0] = t.oid
ORDER BY proname, typname""")
return result
# lists all the operator classes that can be used with each access method as

View File

@ -292,8 +292,8 @@ ALTER TABLE foo_seq RENAME TO foo_seq_new;
SELECT * FROM foo_seq_new;
sequence_name | last_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
foo_seq | 1 | 1 | 9223372036854775807 | 1 | 1 | 1 | f | f
(1 row)
foo_seq | 1 | 1 | 9223372036854775807 | 1 | 1 | 1 | f | f
(1 row)
DROP SEQUENCE foo_seq_new;
-- FOREIGN KEY CONSTRAINT adding TEST
@ -345,17 +345,17 @@ DROP TABLE tmp2;
-- is run in parallel with foreign_key.sql.
CREATE TEMP TABLE PKTABLE (ptest1 int PRIMARY KEY);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
CREATE TEMP TABLE FKTABLE (ftest1 text);
-- This next should fail, because text=int does not exist
CREATE TEMP TABLE FKTABLE (ftest1 inet);
-- This next should fail, because inet=int does not exist
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable;
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- This should also fail for the same reason, but here we
-- give the column name
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1);
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- This should succeed, even though they are different types
-- because varchar=int does exist
@ -370,7 +370,7 @@ DROP TABLE pktable;
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable"
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable"
DROP TABLE fktable;
CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 text,
CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet,
PRIMARY KEY(ptest1, ptest2));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
-- This should fail, because we just chose really odd types
@ -389,17 +389,17 @@ ERROR: Unable to identify an operator '=' for types 'cidr' and 'integer'
You will have to retype this query using an explicit cast
-- This fails because we mixed up the column ordering
DROP TABLE FKTABLE;
CREATE TEMP TABLE FKTABLE (ftest1 int, ftest2 text);
CREATE TEMP TABLE FKTABLE (ftest1 int, ftest2 inet);
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
references pktable(ptest2, ptest1);
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'integer' and 'text'
ERROR: Unable to identify an operator '=' for types 'integer' and 'inet'
You will have to retype this query using an explicit cast
-- As does this...
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1)
references pktable(ptest1, ptest2);
NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- temp tables should go away by themselves, need not drop them.
-- test check constraint adding

View File

@ -718,16 +718,16 @@ DROP TABLE PKTABLE;
-- Basic one column, two table setup
CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
-- This next should fail, because text=int does not exist
CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable);
-- This next should fail, because inet=int does not exist
CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable);
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- This should also fail for the same reason, but here we
-- give the column name
CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable(ptest1));
CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable(ptest1));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- This should succeed, even though they are different types
-- because varchar=int does exist
@ -744,7 +744,7 @@ NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "p
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable"
DROP TABLE PKTABLE;
-- Two columns, two tables
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, PRIMARY KEY(ptest1, ptest2));
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
-- This should fail, because we just chose really odd types
CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable);
@ -757,28 +757,28 @@ NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'cidr' and 'integer'
You will have to retype this query using an explicit cast
-- This fails because we mixed up the column ordering
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable);
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable);
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- As does this...
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- And again..
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'integer' and 'text'
ERROR: Unable to identify an operator '=' for types 'integer' and 'inet'
You will have to retype this query using an explicit cast
-- This works...
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
DROP TABLE FKTABLE;
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable"
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable"
-- As does this
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
DROP TABLE FKTABLE;
NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable"
@ -786,37 +786,37 @@ NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "p
DROP TABLE PKTABLE;
-- Two columns, same table
-- Make sure this still works...
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
ptest4) REFERENCES pktable(ptest1, ptest2));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
DROP TABLE PKTABLE;
-- And this,
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
ptest4) REFERENCES pktable);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
DROP TABLE PKTABLE;
-- This shouldn't (mixed up columns)
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
ptest4) REFERENCES pktable(ptest2, ptest1));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'integer' and 'text'
ERROR: Unable to identify an operator '=' for types 'integer' and 'inet'
You will have to retype this query using an explicit cast
-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
ptest3) REFERENCES pktable(ptest1, ptest2));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
-- Not this one either... Same as the last one except we didn't defined the columns being referenced.
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
ptest3) REFERENCES pktable);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
--
-- Now some cases with inheritance
@ -907,7 +907,7 @@ drop table pktable;
drop table pktable_base;
-- 2 columns (2 tables), mismatched types
create table pktable_base(base1 int not null);
create table pktable(ptest1 text, primary key(base1, ptest1)) inherits (pktable_base);
create table pktable(ptest1 inet, primary key(base1, ptest1)) inherits (pktable_base);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
-- just generally bad types (with and without column references on the referenced table)
create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable);
@ -919,45 +919,45 @@ NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'cidr' and 'integer'
You will have to retype this query using an explicit cast
-- let's mix up which columns reference which
create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable);
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable);
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable(base1, ptest1));
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
create table fktable(ftest1 int, ftest2 text, foreign key(ftest1, ftest2) references pktable(ptest1, base1));
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1));
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'integer' and 'text'
ERROR: Unable to identify an operator '=' for types 'integer' and 'inet'
You will have to retype this query using an explicit cast
drop table pktable;
drop table pktable_base;
-- 2 columns (1 table), mismatched types
create table pktable_base(base1 int not null, base2 int);
create table pktable(ptest1 text, ptest2 text[], primary key(base1, ptest1), foreign key(base2, ptest2) references
create table pktable(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references
pktable(base1, ptest1)) inherits (pktable_base);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text[]' and 'text'
ERROR: Unable to identify an operator '=' for types 'inet[]' and 'inet'
You will have to retype this query using an explicit cast
create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(base2, ptest2) references
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references
pktable(ptest1, base1)) inherits (pktable_base);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'integer' and 'text'
ERROR: Unable to identify an operator '=' for types 'integer' and 'inet'
You will have to retype this query using an explicit cast
create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references
pktable(base1, ptest1)) inherits (pktable_base);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references
pktable(base1, ptest1)) inherits (pktable_base);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable'
NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
ERROR: Unable to identify an operator '=' for types 'text' and 'integer'
ERROR: Unable to identify an operator '=' for types 'inet' and 'integer'
You will have to retype this query using an explicit cast
drop table pktable;
ERROR: table "pktable" does not exist

View File

@ -1,6 +1,14 @@
--
-- This is created by pgsql/contrib/findoidjoins/make_oidjoin_check
--
SELECT ctid, pg_aggregate.aggfnoid
FROM pg_aggregate
WHERE pg_aggregate.aggfnoid != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggfnoid);
ctid | aggfnoid
------+----------
(0 rows)
SELECT ctid, pg_aggregate.aggtransfn
FROM pg_aggregate
WHERE pg_aggregate.aggtransfn != 0 AND
@ -17,14 +25,6 @@ WHERE pg_aggregate.aggfinalfn != 0 AND
------+------------
(0 rows)
SELECT ctid, pg_aggregate.aggbasetype
FROM pg_aggregate
WHERE pg_aggregate.aggbasetype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggbasetype);
ctid | aggbasetype
------+-------------
(0 rows)
SELECT ctid, pg_aggregate.aggtranstype
FROM pg_aggregate
WHERE pg_aggregate.aggtranstype != 0 AND
@ -33,14 +33,6 @@ WHERE pg_aggregate.aggtranstype != 0 AND
------+--------------
(0 rows)
SELECT ctid, pg_aggregate.aggfinaltype
FROM pg_aggregate
WHERE pg_aggregate.aggfinaltype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggfinaltype);
ctid | aggfinaltype
------+--------------
(0 rows)
SELECT ctid, pg_am.amgettuple
FROM pg_am
WHERE pg_am.amgettuple != 0 AND

View File

@ -48,7 +48,7 @@ WHERE p1.oid != p2.oid AND
-----+---------+-----+---------
(0 rows)
-- Considering only built-in procs (prolang = 11/12), look for multiple uses
-- Considering only built-in procs (prolang = 12), look for multiple uses
-- of the same internal function (ie, matching prosrc fields). It's OK to
-- have several entries with different pronames for the same internal function,
-- but conflicts in the number of arguments and other critical items should
@ -57,14 +57,14 @@ SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
(p1.prolang != p2.prolang OR
p1.proisinh != p2.proisinh OR
p1.proisagg != p2.proisagg OR
p1.proistrusted != p2.proistrusted OR
p1.proisstrict != p2.proisstrict OR
p1.proretset != p2.proretset OR
p1.provolatile != p2.provolatile OR
p1.pronargs != p2.pronargs OR
p1.proretset != p2.proretset);
p1.pronargs != p2.pronargs);
oid | proname | oid | proname
-----+---------+-----+---------
(0 rows)
@ -75,12 +75,14 @@ WHERE p1.oid != p2.oid AND
-- That's not wrong, necessarily, but we make lists of all the types being
-- so treated. Note that the expected output of this part of the test will
-- need to be modified whenever new pairs of types are made binary-equivalent!
-- Note: ignore aggregate functions here, since they all point to the same
-- dummy built-in function.
SELECT DISTINCT p1.prorettype, p2.prorettype
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.prorettype < p2.prorettype);
prorettype | prorettype
------------+------------
@ -92,8 +94,8 @@ SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[0] < p2.proargtypes[0]);
proargtypes | proargtypes
-------------+-------------
@ -106,8 +108,8 @@ SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[1] < p2.proargtypes[1]);
proargtypes | proargtypes
-------------+-------------
@ -119,8 +121,8 @@ SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[2] < p2.proargtypes[2]);
proargtypes | proargtypes
-------------+-------------
@ -131,8 +133,8 @@ SELECT DISTINCT p1.proargtypes[3], p2.proargtypes[3]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[3] < p2.proargtypes[3]);
proargtypes | proargtypes
-------------+-------------
@ -143,8 +145,8 @@ SELECT DISTINCT p1.proargtypes[4], p2.proargtypes[4]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[4] < p2.proargtypes[4]);
proargtypes | proargtypes
-------------+-------------
@ -154,8 +156,8 @@ SELECT DISTINCT p1.proargtypes[5], p2.proargtypes[5]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[5] < p2.proargtypes[5]);
proargtypes | proargtypes
-------------+-------------
@ -165,8 +167,8 @@ SELECT DISTINCT p1.proargtypes[6], p2.proargtypes[6]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[6] < p2.proargtypes[6]);
proargtypes | proargtypes
-------------+-------------
@ -176,13 +178,29 @@ SELECT DISTINCT p1.proargtypes[7], p2.proargtypes[7]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[7] < p2.proargtypes[7]);
proargtypes | proargtypes
-------------+-------------
(0 rows)
-- If a proc is marked as an implicit cast, then it should be something that
-- the system might actually use as a cast function: name same as the name
-- of its output type, and either one arg that's a different type, or two
-- args where the first is the same as the output type and the second is int4.
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.proimplicit AND
(NOT EXISTS (SELECT 1 FROM pg_type t WHERE t.oid = p1.prorettype AND
t.typname = p1.proname) OR
NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
p1.proargtypes[1] = 23)));
oid | proname
-----+---------
(0 rows)
-- **************** pg_operator ****************
-- Look for illegal values in pg_operator fields.
SELECT p1.oid, p1.oprname
@ -238,6 +256,7 @@ WHERE p1.oprcom = p2.oid AND
-- single-operand operators.
-- We expect that B will always say that B.oprnegate = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.
-- Also, A and B had better not be the same operator.
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
WHERE p1.oprnegate = p2.oid AND
@ -246,7 +265,8 @@ WHERE p1.oprnegate = p2.oid AND
p1.oprright != p2.oprright OR
p1.oprresult != 16 OR
p2.oprresult != 16 OR
p1.oid != p2.oprnegate);
p1.oid != p2.oprnegate OR
p1.oid = p2.oid);
oid | oprcode | oid | oprcode
-----+---------+-----+---------
(0 rows)
@ -455,19 +475,38 @@ WHERE p1.oprjoin = p2.oid AND
-- **************** pg_aggregate ****************
-- Look for illegal values in pg_aggregate fields.
SELECT p1.oid, p1.aggname
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
WHERE aggtransfn = 0 OR aggtranstype = 0 OR aggfinaltype = 0;
oid | aggname
WHERE aggfnoid = 0 OR aggtransfn = 0 OR aggtranstype = 0;
ctid | aggfnoid
------+----------
(0 rows)
-- Make sure the matching pg_proc entry is sensible, too.
SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
(NOT p.proisagg OR p.pronargs != 1 OR p.proretset);
aggfnoid | proname
----------+---------
(0 rows)
-- Make sure there are no proisagg pg_proc entries without matches.
SELECT oid, proname
FROM pg_proc as p
WHERE p.proisagg AND
NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid);
oid | proname
-----+---------
(0 rows)
-- If there is no finalfn then the output type must be the transtype.
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
oid | aggname
-----+---------
SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
a.aggfinalfn = 0 AND p.prorettype != a.aggtranstype;
aggfnoid | proname
----------+---------
(0 rows)
-- Cross-check transfn against its entry in pg_proc.
@ -476,41 +515,44 @@ WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
-- implemented using int4larger/int4smaller. Until we have
-- some cleaner way of dealing with binary-equivalent types, just leave
-- those two tuples in the expected output.
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn = p2.oid AND
SELECT a.aggfnoid::oid, p.proname, p2.oid, p2.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS p2
WHERE a.aggfnoid = p.oid AND
a.aggtransfn = p2.oid AND
(p2.proretset OR
p1.aggtranstype != p2.prorettype OR
p1.aggtranstype != p2.proargtypes[0] OR
NOT ((p2.pronargs = 2 AND p1.aggbasetype = p2.proargtypes[1]) OR
(p2.pronargs = 1 AND p1.aggbasetype = 0)));
oid | aggname | oid | proname
-------+---------+-----+-------------
10021 | max | 768 | int4larger
10037 | min | 769 | int4smaller
a.aggtranstype != p2.prorettype OR
a.aggtranstype != p2.proargtypes[0] OR
NOT ((p2.pronargs = 2 AND p.proargtypes[0] = p2.proargtypes[1]) OR
(p2.pronargs = 1 AND p.proargtypes[0] = 0)));
aggfnoid | proname | oid | proname
----------+---------+-----+-------------
2121 | max | 768 | int4larger
2137 | min | 769 | int4smaller
(2 rows)
-- Cross-check finalfn (if present) against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggfinalfn = p2.oid AND
(p2.proretset OR p1.aggfinaltype != p2.prorettype OR
SELECT a.aggfnoid::oid, p.proname, p2.oid, p2.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS p2
WHERE a.aggfnoid = p.oid AND
a.aggfinalfn = p2.oid AND
(p2.proretset OR p.prorettype != p2.prorettype OR
p2.pronargs != 1 OR
p1.aggtranstype != p2.proargtypes[0]);
oid | aggname | oid | proname
-----+---------+-----+---------
a.aggtranstype != p2.proargtypes[0]);
aggfnoid | proname | oid | proname
----------+---------+-----+---------
(0 rows)
-- If transfn is strict then either initval should be non-NULL, or
-- basetype should equal transtype so that the first non-null input
-- input type should equal transtype so that the first non-null input
-- can be assigned as the state value.
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn = p2.oid AND p2.proisstrict AND
p1.agginitval IS NULL AND p1.aggbasetype != p1.aggtranstype;
oid | aggname | oid | proname
-----+---------+-----+---------
SELECT a.aggfnoid::oid, p.proname, p2.oid, p2.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS p2
WHERE a.aggfnoid = p.oid AND
a.aggtransfn = p2.oid AND p2.proisstrict AND
a.agginitval IS NULL AND p.proargtypes[0] != a.aggtranstype;
aggfnoid | proname | oid | proname
----------+---------+-----+---------
(0 rows)
-- **************** pg_opclass ****************
@ -574,6 +616,17 @@ WHERE p1.amopopr = p2.oid AND
-----------+---------+-----+---------
(0 rows)
-- Check that all operators linked to by opclass entries have selectivity
-- estimators. This is not absolutely required, but it seems a reasonable
-- thing to insist on for all standard datatypes.
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
amopclaid | amopopr | oid | oprname
-----------+---------+-----+---------
(0 rows)
-- Check that operator input types match the opclass
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3

View File

@ -1024,7 +1024,7 @@ SELECT * FROM shoe_ready WHERE total_avail >= 2;
NEW.sl_name,
NEW.sl_avail,
'Al Bundy',
'epoch'::text
'epoch'
);
UPDATE shoelace_data SET sl_avail = 6 WHERE sl_name = 'sl7';
SELECT * FROM shoelace_log;
@ -1308,8 +1308,8 @@ SELECT viewname, definition FROM pg_views ORDER BY viewname;
SELECT tablename, rulename, definition FROM pg_rules
ORDER BY tablename, rulename;
tablename | rulename | definition
---------------+-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tablename | rulename | definition
---------------+-----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
rtest_emp | rtest_emp_del | CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (old.ename, "current_user"(), 'fired '::bpchar, '$0.00'::money, old.salary);
rtest_emp | rtest_emp_ins | CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'hired '::bpchar, new.salary, '$0.00'::money);
rtest_emp | rtest_emp_upd | CREATE RULE rtest_emp_upd AS ON UPDATE TO rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'honored '::bpchar, new.salary, old.salary);
@ -1335,7 +1335,7 @@ SELECT tablename, rulename, definition FROM pg_rules
shoelace | shoelace_del | CREATE RULE shoelace_del AS ON DELETE TO shoelace DO INSTEAD DELETE FROM shoelace_data WHERE (shoelace_data.sl_name = old.sl_name);
shoelace | shoelace_ins | CREATE RULE shoelace_ins AS ON INSERT TO shoelace DO INSTEAD INSERT INTO shoelace_data (sl_name, sl_avail, sl_color, sl_len, sl_unit) VALUES (new.sl_name, new.sl_avail, new.sl_color, new.sl_len, new.sl_unit);
shoelace | shoelace_upd | CREATE RULE shoelace_upd AS ON UPDATE TO shoelace DO INSTEAD UPDATE shoelace_data SET sl_name = new.sl_name, sl_avail = new.sl_avail, sl_color = new.sl_color, sl_len = new.sl_len, sl_unit = new.sl_unit WHERE (shoelace_data.sl_name = old.sl_name);
shoelace_data | log_shoelace | CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data WHERE (new.sl_avail <> old.sl_avail) DO INSERT INTO shoelace_log (sl_name, sl_avail, log_who, log_when) VALUES (new.sl_name, new.sl_avail, 'Al Bundy'::name, "timestamp"('epoch'::text));
shoelace_data | log_shoelace | CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data WHERE (new.sl_avail <> old.sl_avail) DO INSERT INTO shoelace_log (sl_name, sl_avail, log_who, log_when) VALUES (new.sl_name, new.sl_avail, 'Al Bundy'::name, 'Thu Jan 01 00:00:00 1970'::"timestamp");
shoelace_ok | shoelace_ok_ins | CREATE RULE shoelace_ok_ins AS ON INSERT TO shoelace_ok DO INSTEAD UPDATE shoelace SET sl_avail = (shoelace.sl_avail + new.ok_quant) WHERE (shoelace.sl_name = new.ok_name);
(27 rows)

View File

@ -234,8 +234,8 @@ DROP TABLE tmp2;
-- is run in parallel with foreign_key.sql.
CREATE TEMP TABLE PKTABLE (ptest1 int PRIMARY KEY);
CREATE TEMP TABLE FKTABLE (ftest1 text);
-- This next should fail, because text=int does not exist
CREATE TEMP TABLE FKTABLE (ftest1 inet);
-- This next should fail, because inet=int does not exist
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable;
-- This should also fail for the same reason, but here we
-- give the column name
@ -250,7 +250,7 @@ ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1);
DROP TABLE pktable;
DROP TABLE fktable;
CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 text,
CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet,
PRIMARY KEY(ptest1, ptest2));
-- This should fail, because we just chose really odd types
CREATE TEMP TABLE FKTABLE (ftest1 cidr, ftest2 datetime);
@ -262,7 +262,7 @@ ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
references pktable(ptest1, ptest2);
-- This fails because we mixed up the column ordering
DROP TABLE FKTABLE;
CREATE TEMP TABLE FKTABLE (ftest1 int, ftest2 text);
CREATE TEMP TABLE FKTABLE (ftest1 int, ftest2 inet);
ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
references pktable(ptest2, ptest1);
-- As does this...

View File

@ -431,11 +431,11 @@ DROP TABLE PKTABLE;
--
-- Basic one column, two table setup
CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY);
-- This next should fail, because text=int does not exist
CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable);
-- This next should fail, because inet=int does not exist
CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable);
-- This should also fail for the same reason, but here we
-- give the column name
CREATE TABLE FKTABLE (ftest1 text REFERENCES pktable(ptest1));
CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable(ptest1));
-- This should succeed, even though they are different types
-- because varchar=int does exist
CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable);
@ -446,42 +446,42 @@ DROP TABLE FKTABLE;
DROP TABLE PKTABLE;
-- Two columns, two tables
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, PRIMARY KEY(ptest1, ptest2));
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2));
-- This should fail, because we just chose really odd types
CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable);
-- Again, so should this...
CREATE TABLE FKTABLE (ftest1 cidr, ftest2 datetime, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
-- This fails because we mixed up the column ordering
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable);
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable);
-- As does this...
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2));
-- And again..
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1));
-- This works...
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1));
DROP TABLE FKTABLE;
-- As does this
CREATE TABLE FKTABLE (ftest1 int, ftest2 text, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2));
DROP TABLE FKTABLE;
DROP TABLE PKTABLE;
-- Two columns, same table
-- Make sure this still works...
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
ptest4) REFERENCES pktable(ptest1, ptest2));
DROP TABLE PKTABLE;
-- And this,
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
ptest4) REFERENCES pktable);
DROP TABLE PKTABLE;
-- This shouldn't (mixed up columns)
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3,
ptest4) REFERENCES pktable(ptest2, ptest1));
-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
ptest3) REFERENCES pktable(ptest1, ptest2));
-- Not this one either... Same as the last one except we didn't defined the columns being referenced.
CREATE TABLE PKTABLE (ptest1 int, ptest2 text, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4,
ptest3) REFERENCES pktable);
--
@ -557,26 +557,26 @@ drop table pktable_base;
-- 2 columns (2 tables), mismatched types
create table pktable_base(base1 int not null);
create table pktable(ptest1 text, primary key(base1, ptest1)) inherits (pktable_base);
create table pktable(ptest1 inet, primary key(base1, ptest1)) inherits (pktable_base);
-- just generally bad types (with and without column references on the referenced table)
create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable);
create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1));
-- let's mix up which columns reference which
create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable);
create table fktable(ftest1 int, ftest2 text, foreign key(ftest2, ftest1) references pktable(base1, ptest1));
create table fktable(ftest1 int, ftest2 text, foreign key(ftest1, ftest2) references pktable(ptest1, base1));
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable);
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1));
create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1));
drop table pktable;
drop table pktable_base;
-- 2 columns (1 table), mismatched types
create table pktable_base(base1 int not null, base2 int);
create table pktable(ptest1 text, ptest2 text[], primary key(base1, ptest1), foreign key(base2, ptest2) references
create table pktable(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references
pktable(base1, ptest1)) inherits (pktable_base);
create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(base2, ptest2) references
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references
pktable(ptest1, base1)) inherits (pktable_base);
create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references
pktable(base1, ptest1)) inherits (pktable_base);
create table pktable(ptest1 text, ptest2 text, primary key(base1, ptest1), foreign key(ptest2, base2) references
create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references
pktable(base1, ptest1)) inherits (pktable_base);
drop table pktable;
drop table pktable_base;

View File

@ -1,6 +1,10 @@
--
-- This is created by pgsql/contrib/findoidjoins/make_oidjoin_check
--
SELECT ctid, pg_aggregate.aggfnoid
FROM pg_aggregate
WHERE pg_aggregate.aggfnoid != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggfnoid);
SELECT ctid, pg_aggregate.aggtransfn
FROM pg_aggregate
WHERE pg_aggregate.aggtransfn != 0 AND
@ -9,18 +13,10 @@ SELECT ctid, pg_aggregate.aggfinalfn
FROM pg_aggregate
WHERE pg_aggregate.aggfinalfn != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggfinalfn);
SELECT ctid, pg_aggregate.aggbasetype
FROM pg_aggregate
WHERE pg_aggregate.aggbasetype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggbasetype);
SELECT ctid, pg_aggregate.aggtranstype
FROM pg_aggregate
WHERE pg_aggregate.aggtranstype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype);
SELECT ctid, pg_aggregate.aggfinaltype
FROM pg_aggregate
WHERE pg_aggregate.aggfinaltype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggfinaltype);
SELECT ctid, pg_am.amgettuple
FROM pg_am
WHERE pg_am.amgettuple != 0 AND

View File

@ -46,7 +46,7 @@ WHERE p1.oid != p2.oid AND
p1.pronargs = p2.pronargs AND
p1.proargtypes = p2.proargtypes;
-- Considering only built-in procs (prolang = 11/12), look for multiple uses
-- Considering only built-in procs (prolang = 12), look for multiple uses
-- of the same internal function (ie, matching prosrc fields). It's OK to
-- have several entries with different pronames for the same internal function,
-- but conflicts in the number of arguments and other critical items should
@ -56,14 +56,14 @@ SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
(p1.prolang != p2.prolang OR
p1.proisinh != p2.proisinh OR
p1.proisagg != p2.proisagg OR
p1.proistrusted != p2.proistrusted OR
p1.proisstrict != p2.proisstrict OR
p1.proretset != p2.proretset OR
p1.provolatile != p2.provolatile OR
p1.pronargs != p2.pronargs OR
p1.proretset != p2.proretset);
p1.pronargs != p2.pronargs);
-- Look for uses of different type OIDs in the argument/result type fields
-- for different aliases of the same built-in function.
@ -71,79 +71,95 @@ WHERE p1.oid != p2.oid AND
-- That's not wrong, necessarily, but we make lists of all the types being
-- so treated. Note that the expected output of this part of the test will
-- need to be modified whenever new pairs of types are made binary-equivalent!
-- Note: ignore aggregate functions here, since they all point to the same
-- dummy built-in function.
SELECT DISTINCT p1.prorettype, p2.prorettype
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.prorettype < p2.prorettype);
SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[0] < p2.proargtypes[0]);
SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[1] < p2.proargtypes[1]);
SELECT DISTINCT p1.proargtypes[2], p2.proargtypes[2]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[2] < p2.proargtypes[2]);
SELECT DISTINCT p1.proargtypes[3], p2.proargtypes[3]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[3] < p2.proargtypes[3]);
SELECT DISTINCT p1.proargtypes[4], p2.proargtypes[4]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[4] < p2.proargtypes[4]);
SELECT DISTINCT p1.proargtypes[5], p2.proargtypes[5]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[5] < p2.proargtypes[5]);
SELECT DISTINCT p1.proargtypes[6], p2.proargtypes[6]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[6] < p2.proargtypes[6]);
SELECT DISTINCT p1.proargtypes[7], p2.proargtypes[7]
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid != p2.oid AND
p1.prosrc = p2.prosrc AND
(p1.prolang = 11 OR p1.prolang = 12) AND
(p2.prolang = 11 OR p2.prolang = 12) AND
p1.prolang = 12 AND p2.prolang = 12 AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[7] < p2.proargtypes[7]);
-- If a proc is marked as an implicit cast, then it should be something that
-- the system might actually use as a cast function: name same as the name
-- of its output type, and either one arg that's a different type, or two
-- args where the first is the same as the output type and the second is int4.
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.proimplicit AND
(NOT EXISTS (SELECT 1 FROM pg_type t WHERE t.oid = p1.prorettype AND
t.typname = p1.proname) OR
NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
p1.proargtypes[1] = 23)));
-- **************** pg_operator ****************
-- Look for illegal values in pg_operator fields.
@ -192,6 +208,7 @@ WHERE p1.oprcom = p2.oid AND
-- single-operand operators.
-- We expect that B will always say that B.oprnegate = A as well; that's not
-- inherently essential, but it would be inefficient not to mark it so.
-- Also, A and B had better not be the same operator.
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
FROM pg_operator AS p1, pg_operator AS p2
@ -201,7 +218,8 @@ WHERE p1.oprnegate = p2.oid AND
p1.oprright != p2.oprright OR
p1.oprresult != 16 OR
p2.oprresult != 16 OR
p1.oid != p2.oprnegate);
p1.oid != p2.oprnegate OR
p1.oid = p2.oid);
-- Look for mergejoin operators that don't match their links.
-- A mergejoin link leads from an '=' operator to the
@ -378,15 +396,30 @@ WHERE p1.oprjoin = p2.oid AND
-- Look for illegal values in pg_aggregate fields.
SELECT p1.oid, p1.aggname
SELECT ctid, aggfnoid::oid
FROM pg_aggregate as p1
WHERE aggtransfn = 0 OR aggtranstype = 0 OR aggfinaltype = 0;
WHERE aggfnoid = 0 OR aggtransfn = 0 OR aggtranstype = 0;
-- Make sure the matching pg_proc entry is sensible, too.
SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
(NOT p.proisagg OR p.pronargs != 1 OR p.proretset);
-- Make sure there are no proisagg pg_proc entries without matches.
SELECT oid, proname
FROM pg_proc as p
WHERE p.proisagg AND
NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid);
-- If there is no finalfn then the output type must be the transtype.
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
SELECT a.aggfnoid::oid, p.proname
FROM pg_aggregate as a, pg_proc as p
WHERE a.aggfnoid = p.oid AND
a.aggfinalfn = 0 AND p.prorettype != a.aggtranstype;
-- Cross-check transfn against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
@ -394,33 +427,36 @@ WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
-- implemented using int4larger/int4smaller. Until we have
-- some cleaner way of dealing with binary-equivalent types, just leave
-- those two tuples in the expected output.
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn = p2.oid AND
SELECT a.aggfnoid::oid, p.proname, p2.oid, p2.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS p2
WHERE a.aggfnoid = p.oid AND
a.aggtransfn = p2.oid AND
(p2.proretset OR
p1.aggtranstype != p2.prorettype OR
p1.aggtranstype != p2.proargtypes[0] OR
NOT ((p2.pronargs = 2 AND p1.aggbasetype = p2.proargtypes[1]) OR
(p2.pronargs = 1 AND p1.aggbasetype = 0)));
a.aggtranstype != p2.prorettype OR
a.aggtranstype != p2.proargtypes[0] OR
NOT ((p2.pronargs = 2 AND p.proargtypes[0] = p2.proargtypes[1]) OR
(p2.pronargs = 1 AND p.proargtypes[0] = 0)));
-- Cross-check finalfn (if present) against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggfinalfn = p2.oid AND
(p2.proretset OR p1.aggfinaltype != p2.prorettype OR
SELECT a.aggfnoid::oid, p.proname, p2.oid, p2.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS p2
WHERE a.aggfnoid = p.oid AND
a.aggfinalfn = p2.oid AND
(p2.proretset OR p.prorettype != p2.prorettype OR
p2.pronargs != 1 OR
p1.aggtranstype != p2.proargtypes[0]);
a.aggtranstype != p2.proargtypes[0]);
-- If transfn is strict then either initval should be non-NULL, or
-- basetype should equal transtype so that the first non-null input
-- input type should equal transtype so that the first non-null input
-- can be assigned as the state value.
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn = p2.oid AND p2.proisstrict AND
p1.agginitval IS NULL AND p1.aggbasetype != p1.aggtranstype;
SELECT a.aggfnoid::oid, p.proname, p2.oid, p2.proname
FROM pg_aggregate AS a, pg_proc AS p, pg_proc AS p2
WHERE a.aggfnoid = p.oid AND
a.aggtransfn = p2.oid AND p2.proisstrict AND
a.agginitval IS NULL AND p.proargtypes[0] != a.aggtranstype;
-- **************** pg_opclass ****************
@ -473,6 +509,15 @@ FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND
(p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright);
-- Check that all operators linked to by opclass entries have selectivity
-- estimators. This is not absolutely required, but it seems a reasonable
-- thing to insist on for all standard datatypes.
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND
(p2.oprrest = 0 OR p2.oprjoin = 0);
-- Check that operator input types match the opclass
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname

View File

@ -604,7 +604,7 @@ SELECT * FROM shoe_ready WHERE total_avail >= 2;
NEW.sl_name,
NEW.sl_avail,
'Al Bundy',
'epoch'::text
'epoch'
);
UPDATE shoelace_data SET sl_avail = 6 WHERE sl_name = 'sl7';

View File

@ -7,7 +7,7 @@
-- Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
-- Portions Copyright (c) 1994, Regents of the University of California
--
-- $Id: syscat.source,v 1.5 2001/08/21 16:36:06 tgl Exp $
-- $Id: syscat.source,v 1.6 2002/04/11 20:00:18 tgl Exp $
--
---------------------------------------------------------------------------
@ -129,10 +129,11 @@ SELECT p.proname, p.pronargs, t.typname
--
-- lists all aggregate functions and the types to which they can be applied
--
SELECT a.aggname, t.typname
FROM pg_aggregate a, pg_type t
WHERE a.aggbasetype = t.oid
ORDER BY aggname, typname;
SELECT p.proname, t.typname
FROM pg_aggregate a, pg_proc p, pg_type t
WHERE a.aggfnoid = p.oid
and p.proargtypes[0] = t.oid
ORDER BY proname, typname;
--