Commit 2e7a6889 authored by Tom Lane's avatar Tom Lane

Add aggsortop column to pg_aggregate, so that MIN/MAX optimization can

be supported for all datatypes.  Add CREATE AGGREGATE and pg_dump support
too.  Add specialized min/max aggregates for bpchar, instead of depending
on text's min/max, because otherwise the possible use of bpchar indexes
cannot be recognized.
initdb forced because of catalog changes.
parent 3803f243
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.99 2005/03/29 19:44:22 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.100 2005/04/12 04:26:13 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
...@@ -250,11 +250,17 @@ ...@@ -250,11 +250,17 @@
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>Final function (zero if none)</entry> <entry>Final function (zero if none)</entry>
</row> </row>
<row>
<entry><structfield>aggsortop</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry>
<entry>Associated sort operator (zero if none)</entry>
</row>
<row> <row>
<entry><structfield>aggtranstype</structfield></entry> <entry><structfield>aggtranstype</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
<entry>The type of the aggregate function's internal transition (state) data</entry> <entry>Data type of the aggregate function's internal transition (state) data</entry>
</row> </row>
<row> <row>
<entry><structfield>agginitval</structfield></entry> <entry><structfield>agginitval</structfield></entry>
...@@ -263,7 +269,7 @@ ...@@ -263,7 +269,7 @@
<entry> <entry>
The initial value of the transition state. This is a text The initial value of the transition state. This is a text
field containing the initial value in its external string field containing the initial value in its external string
representation. If the value is null, the transition state representation. If this field is null, the transition state
value starts out null. value starts out null.
</entry> </entry>
</row> </row>
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.31 2005/01/04 00:39:53 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.32 2005/04/12 04:26:15 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -26,6 +26,7 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( ...@@ -26,6 +26,7 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
STYPE = <replaceable class="PARAMETER">state_data_type</replaceable> STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ] [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ] [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
[ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
) )
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -125,6 +126,29 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( ...@@ -125,6 +126,29 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
<function>avg</function> returns null when it sees there were zero <function>avg</function> returns null when it sees there were zero
input rows. input rows.
</para> </para>
<para>
Aggregates that behave like <function>MIN</> or <function>MAX</> can
sometimes be optimized by looking into an index instead of scanning every
input row. If this aggregate can be so optimized, indicate it by
specifying a <firstterm>sort operator</>. The basic requirement is that
the aggregate must yield the first element in the sort ordering induced by
the operator; in other words
<programlisting>
SELECT agg(col) FROM tab;
</programlisting>
must be equivalent to
<programlisting>
SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
</programlisting>
Further assumptions are that the aggregate ignores null inputs, and that
it delivers a null result if and only if there were no non-null inputs.
Ordinarily, a datatype's <literal>&lt;</> operator is the proper sort
operator for <function>MIN</>, and <literal>&gt;</> is the proper sort
operator for <function>MAX</>. Note that the optimization will never
actually take effect unless the specified operator is the LessThan or
GreaterThan strategy member of a btree index opclass.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
...@@ -211,6 +235,19 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( ...@@ -211,6 +235,19 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">sort_operator</replaceable></term>
<listitem>
<para>
The associated sort operator for a <function>MIN</>- or
<function>MAX</>-like aggregate.
This is just an operator name (possibly schema-qualified).
The operator is assumed to have the same input datatypes as
the aggregate.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
<para> <para>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.72 2005/03/31 22:46:06 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.73 2005/04/12 04:26:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "optimizer/cost.h" #include "optimizer/cost.h"
#include "parser/parse_coerce.h" #include "parser/parse_coerce.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
...@@ -42,9 +43,10 @@ static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types, ...@@ -42,9 +43,10 @@ static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types,
void void
AggregateCreate(const char *aggName, AggregateCreate(const char *aggName,
Oid aggNamespace, Oid aggNamespace,
Oid aggBaseType,
List *aggtransfnName, List *aggtransfnName,
List *aggfinalfnName, List *aggfinalfnName,
Oid aggBaseType, List *aggsortopName,
Oid aggTransType, Oid aggTransType,
const char *agginitval) const char *agginitval)
{ {
...@@ -55,6 +57,7 @@ AggregateCreate(const char *aggName, ...@@ -55,6 +57,7 @@ AggregateCreate(const char *aggName,
Form_pg_proc proc; Form_pg_proc proc;
Oid transfn; Oid transfn;
Oid finalfn = InvalidOid; /* can be omitted */ Oid finalfn = InvalidOid; /* can be omitted */
Oid sortop = InvalidOid; /* can be omitted */
Oid rettype; Oid rettype;
Oid finaltype; Oid finaltype;
Oid fnArgs[2]; /* we only deal with 1- and 2-arg fns */ Oid fnArgs[2]; /* we only deal with 1- and 2-arg fns */
...@@ -167,6 +170,12 @@ AggregateCreate(const char *aggName, ...@@ -167,6 +170,12 @@ AggregateCreate(const char *aggName,
errdetail("An aggregate returning \"anyarray\" or \"anyelement\" " errdetail("An aggregate returning \"anyarray\" or \"anyelement\" "
"must have one of them as its base type."))); "must have one of them as its base type.")));
/* handle sortop, if supplied */
if (aggsortopName)
sortop = LookupOperName(aggsortopName,
aggBaseType, aggBaseType,
false);
/* /*
* Everything looks okay. Try to create the pg_proc entry for the * Everything looks okay. Try to create the pg_proc entry for the
* aggregate. (This could fail if there's already a conflicting * aggregate. (This could fail if there's already a conflicting
...@@ -207,6 +216,7 @@ AggregateCreate(const char *aggName, ...@@ -207,6 +216,7 @@ AggregateCreate(const char *aggName,
values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid); values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn); values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn); values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType); values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
if (agginitval) if (agginitval)
values[Anum_pg_aggregate_agginitval - 1] = values[Anum_pg_aggregate_agginitval - 1] =
...@@ -248,6 +258,15 @@ AggregateCreate(const char *aggName, ...@@ -248,6 +258,15 @@ AggregateCreate(const char *aggName,
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
/* Depends on sort operator, if any */
if (OidIsValid(sortop))
{
referenced.classId = get_system_catalog_relid(OperatorRelationName);
referenced.objectId = sortop;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
} }
/* /*
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.23 2005/03/29 00:16:57 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.24 2005/04/12 04:26:20 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -51,6 +51,7 @@ DefineAggregate(List *names, List *parameters) ...@@ -51,6 +51,7 @@ DefineAggregate(List *names, List *parameters)
AclResult aclresult; AclResult aclresult;
List *transfuncName = NIL; List *transfuncName = NIL;
List *finalfuncName = NIL; List *finalfuncName = NIL;
List *sortoperatorName = NIL;
TypeName *baseType = NULL; TypeName *baseType = NULL;
TypeName *transType = NULL; TypeName *transType = NULL;
char *initval = NULL; char *initval = NULL;
...@@ -81,6 +82,8 @@ DefineAggregate(List *names, List *parameters) ...@@ -81,6 +82,8 @@ DefineAggregate(List *names, List *parameters)
transfuncName = defGetQualifiedName(defel); transfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "finalfunc") == 0) else if (pg_strcasecmp(defel->defname, "finalfunc") == 0)
finalfuncName = defGetQualifiedName(defel); finalfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "sortop") == 0)
sortoperatorName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "basetype") == 0) else if (pg_strcasecmp(defel->defname, "basetype") == 0)
baseType = defGetTypeName(defel); baseType = defGetTypeName(defel);
else if (pg_strcasecmp(defel->defname, "stype") == 0) else if (pg_strcasecmp(defel->defname, "stype") == 0)
...@@ -143,9 +146,10 @@ DefineAggregate(List *names, List *parameters) ...@@ -143,9 +146,10 @@ DefineAggregate(List *names, List *parameters)
*/ */
AggregateCreate(aggName, /* aggregate name */ AggregateCreate(aggName, /* aggregate name */
aggNamespace, /* namespace */ aggNamespace, /* namespace */
baseTypeId, /* type of data being aggregated */
transfuncName, /* step function name */ transfuncName, /* step function name */
finalfuncName, /* final function name */ finalfuncName, /* final function name */
baseTypeId, /* type of data being aggregated */ sortoperatorName, /* sort operator name */
transTypeId, /* transition data type */ transTypeId, /* transition data type */
initval); /* initial condition */ initval); /* initial condition */
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.1 2005/04/11 23:06:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.2 2005/04/12 04:26:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -542,7 +542,6 @@ replace_aggs_with_params_mutator(Node *node, List **context) ...@@ -542,7 +542,6 @@ replace_aggs_with_params_mutator(Node *node, List **context)
static Oid static Oid
fetch_agg_sort_op(Oid aggfnoid) fetch_agg_sort_op(Oid aggfnoid)
{ {
#ifdef NOT_YET
HeapTuple aggTuple; HeapTuple aggTuple;
Form_pg_aggregate aggform; Form_pg_aggregate aggform;
Oid aggsortop; Oid aggsortop;
...@@ -558,18 +557,4 @@ fetch_agg_sort_op(Oid aggfnoid) ...@@ -558,18 +557,4 @@ fetch_agg_sort_op(Oid aggfnoid)
ReleaseSysCache(aggTuple); ReleaseSysCache(aggTuple);
return aggsortop; return aggsortop;
#else
/*
* XXX stub implementation for testing: hardwire a few cases.
*/
if (aggfnoid == 2132) /* min(int4) -> int4lt */
return 97;
if (aggfnoid == 2116) /* max(int4) -> int4gt */
return 521;
if (aggfnoid == 2145) /* min(text) -> text_lt */
return 664;
if (aggfnoid == 2129) /* max(text) -> text_gt */
return 666;
return InvalidOid;
#endif
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.108 2004/12/31 22:01:22 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.109 2005/04/12 04:26:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -687,6 +687,40 @@ bpcharcmp(PG_FUNCTION_ARGS) ...@@ -687,6 +687,40 @@ bpcharcmp(PG_FUNCTION_ARGS)
PG_RETURN_INT32(cmp); PG_RETURN_INT32(cmp);
} }
Datum
bpchar_larger(PG_FUNCTION_ARGS)
{
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
int len1,
len2;
int cmp;
len1 = bcTruelen(arg1);
len2 = bcTruelen(arg2);
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);
}
Datum
bpchar_smaller(PG_FUNCTION_ARGS)
{
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
int len1,
len2;
int cmp;
len1 = bcTruelen(arg1);
len2 = bcTruelen(arg2);
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2);
}
/* /*
* bpchar needs a specialized hash function because we want to ignore * bpchar needs a specialized hash function because we want to ignore
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.405 2005/04/01 18:35:41 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.406 2005/04/12 04:26:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -6325,6 +6325,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6325,6 +6325,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
int ntups; int ntups;
int i_aggtransfn; int i_aggtransfn;
int i_aggfinalfn; int i_aggfinalfn;
int i_aggsortop;
int i_aggtranstype; int i_aggtranstype;
int i_agginitval; int i_agginitval;
int i_anybasetype; int i_anybasetype;
...@@ -6332,6 +6333,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6332,6 +6333,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
int i_convertok; int i_convertok;
const char *aggtransfn; const char *aggtransfn;
const char *aggfinalfn; const char *aggfinalfn;
const char *aggsortop;
const char *aggtranstype; const char *aggtranstype;
const char *agginitval; const char *agginitval;
bool convertok; bool convertok;
...@@ -6349,10 +6351,25 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6349,10 +6351,25 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name); selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name);
/* Get aggregate-specific details */ /* Get aggregate-specific details */
if (g_fout->remoteVersion >= 70300) if (g_fout->remoteVersion >= 80100)
{
appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
"aggsortop::pg_catalog.regoperator, "
"agginitval, "
"proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype as anybasetype, "
"proargtypes[0]::pg_catalog.regtype as fmtbasetype, "
"'t'::boolean as convertok "
"from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
"where a.aggfnoid = p.oid "
"and p.oid = '%u'::pg_catalog.oid",
agginfo->aggfn.dobj.catId.oid);
}
else if (g_fout->remoteVersion >= 70300)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, " "aggfinalfn, aggtranstype::pg_catalog.regtype, "
"0 as aggsortop, "
"agginitval, " "agginitval, "
"proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype as anybasetype, " "proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype as anybasetype, "
"proargtypes[0]::pg_catalog.regtype as fmtbasetype, " "proargtypes[0]::pg_catalog.regtype as fmtbasetype, "
...@@ -6366,6 +6383,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6366,6 +6383,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
{ {
appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, " appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
"format_type(aggtranstype, NULL) as aggtranstype, " "format_type(aggtranstype, NULL) as aggtranstype, "
"0 as aggsortop, "
"agginitval, " "agginitval, "
"aggbasetype = 0 as anybasetype, " "aggbasetype = 0 as anybasetype, "
"CASE WHEN aggbasetype = 0 THEN '-' " "CASE WHEN aggbasetype = 0 THEN '-' "
...@@ -6380,6 +6398,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6380,6 +6398,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, " appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, "
"aggfinalfn, " "aggfinalfn, "
"(select typname from pg_type where oid = aggtranstype1) as aggtranstype, " "(select typname from pg_type where oid = aggtranstype1) as aggtranstype, "
"0 as aggsortop, "
"agginitval1 as agginitval, " "agginitval1 as agginitval, "
"aggbasetype = 0 as anybasetype, " "aggbasetype = 0 as anybasetype, "
"(select typname from pg_type where oid = aggbasetype) as fmtbasetype, " "(select typname from pg_type where oid = aggbasetype) as fmtbasetype, "
...@@ -6403,6 +6422,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6403,6 +6422,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
i_aggtransfn = PQfnumber(res, "aggtransfn"); i_aggtransfn = PQfnumber(res, "aggtransfn");
i_aggfinalfn = PQfnumber(res, "aggfinalfn"); i_aggfinalfn = PQfnumber(res, "aggfinalfn");
i_aggsortop = PQfnumber(res, "aggsortop");
i_aggtranstype = PQfnumber(res, "aggtranstype"); i_aggtranstype = PQfnumber(res, "aggtranstype");
i_agginitval = PQfnumber(res, "agginitval"); i_agginitval = PQfnumber(res, "agginitval");
i_anybasetype = PQfnumber(res, "anybasetype"); i_anybasetype = PQfnumber(res, "anybasetype");
...@@ -6411,6 +6431,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6411,6 +6431,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
aggtransfn = PQgetvalue(res, 0, i_aggtransfn); aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn); aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
aggsortop = PQgetvalue(res, 0, i_aggsortop);
aggtranstype = PQgetvalue(res, 0, i_aggtranstype); aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
agginitval = PQgetvalue(res, 0, i_agginitval); agginitval = PQgetvalue(res, 0, i_agginitval);
/* we save anybasetype for format_aggregate_signature */ /* we save anybasetype for format_aggregate_signature */
...@@ -6471,6 +6492,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo) ...@@ -6471,6 +6492,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
aggfinalfn); aggfinalfn);
} }
aggsortop = convertOperatorReference(aggsortop);
if (aggsortop)
{
appendPQExpBuffer(details, ",\n SORTOP = %s",
aggsortop);
}
/* /*
* DROP must be fully qualified in case same name appears in * DROP must be fully qualified in case same name appears in
* pg_catalog * pg_catalog
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.263 2005/04/06 16:34:07 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.264 2005/04/12 04:26:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200504061 #define CATALOG_VERSION_NO 200504111
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_aggregate.h,v 1.49 2005/02/28 03:45:22 neilc Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_aggregate.h,v 1.50 2005/04/12 04:26:28 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -35,9 +35,10 @@ ...@@ -35,9 +35,10 @@
* *
* aggfnoid pg_proc OID of the aggregate itself * aggfnoid pg_proc OID of the aggregate itself
* aggtransfn transition function * aggtransfn transition function
* aggfinalfn final function * aggfinalfn final function (0 if none)
* aggsortop associated sort operator (0 if none)
* aggtranstype type of aggregate's transition (state) data * aggtranstype type of aggregate's transition (state) data
* agginitval initial value for transition state * agginitval initial value for transition state (can be NULL)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
CATALOG(pg_aggregate) BKI_WITHOUT_OIDS CATALOG(pg_aggregate) BKI_WITHOUT_OIDS
...@@ -45,6 +46,7 @@ CATALOG(pg_aggregate) BKI_WITHOUT_OIDS ...@@ -45,6 +46,7 @@ CATALOG(pg_aggregate) BKI_WITHOUT_OIDS
regproc aggfnoid; regproc aggfnoid;
regproc aggtransfn; regproc aggtransfn;
regproc aggfinalfn; regproc aggfinalfn;
Oid aggsortop;
Oid aggtranstype; Oid aggtranstype;
text agginitval; /* VARIABLE LENGTH FIELD */ text agginitval; /* VARIABLE LENGTH FIELD */
} FormData_pg_aggregate; } FormData_pg_aggregate;
...@@ -61,12 +63,13 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; ...@@ -61,12 +63,13 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
* ---------------- * ----------------
*/ */
#define Natts_pg_aggregate 5 #define Natts_pg_aggregate 6
#define Anum_pg_aggregate_aggfnoid 1 #define Anum_pg_aggregate_aggfnoid 1
#define Anum_pg_aggregate_aggtransfn 2 #define Anum_pg_aggregate_aggtransfn 2
#define Anum_pg_aggregate_aggfinalfn 3 #define Anum_pg_aggregate_aggfinalfn 3
#define Anum_pg_aggregate_aggtranstype 4 #define Anum_pg_aggregate_aggsortop 4
#define Anum_pg_aggregate_agginitval 5 #define Anum_pg_aggregate_aggtranstype 5
#define Anum_pg_aggregate_agginitval 6
/* ---------------- /* ----------------
...@@ -75,107 +78,110 @@ typedef FormData_pg_aggregate *Form_pg_aggregate; ...@@ -75,107 +78,110 @@ typedef FormData_pg_aggregate *Form_pg_aggregate;
*/ */
/* avg */ /* avg */
DATA(insert ( 2100 int8_accum numeric_avg 1231 "{0,0,0}" )); DATA(insert ( 2100 int8_accum numeric_avg 0 1231 "{0,0,0}" ));
DATA(insert ( 2101 int4_avg_accum int8_avg 1016 "{0,0}" )); DATA(insert ( 2101 int4_avg_accum int8_avg 0 1016 "{0,0}" ));
DATA(insert ( 2102 int2_avg_accum int8_avg 1016 "{0,0}" )); DATA(insert ( 2102 int2_avg_accum int8_avg 0 1016 "{0,0}" ));
DATA(insert ( 2103 numeric_accum numeric_avg 1231 "{0,0,0}" )); DATA(insert ( 2103 numeric_accum numeric_avg 0 1231 "{0,0,0}" ));
DATA(insert ( 2104 float4_accum float8_avg 1022 "{0,0,0}" )); DATA(insert ( 2104 float4_accum float8_avg 0 1022 "{0,0,0}" ));
DATA(insert ( 2105 float8_accum float8_avg 1022 "{0,0,0}" )); DATA(insert ( 2105 float8_accum float8_avg 0 1022 "{0,0,0}" ));
DATA(insert ( 2106 interval_accum interval_avg 1187 "{0 second,0 second}" )); DATA(insert ( 2106 interval_accum interval_avg 0 1187 "{0 second,0 second}" ));
/* sum */ /* sum */
DATA(insert ( 2107 int8_sum - 1700 _null_ )); DATA(insert ( 2107 int8_sum - 0 1700 _null_ ));
DATA(insert ( 2108 int4_sum - 20 _null_ )); DATA(insert ( 2108 int4_sum - 0 20 _null_ ));
DATA(insert ( 2109 int2_sum - 20 _null_ )); DATA(insert ( 2109 int2_sum - 0 20 _null_ ));
DATA(insert ( 2110 float4pl - 700 _null_ )); DATA(insert ( 2110 float4pl - 0 700 _null_ ));
DATA(insert ( 2111 float8pl - 701 _null_ )); DATA(insert ( 2111 float8pl - 0 701 _null_ ));
DATA(insert ( 2112 cash_pl - 790 _null_ )); DATA(insert ( 2112 cash_pl - 0 790 _null_ ));
DATA(insert ( 2113 interval_pl - 1186 _null_ )); DATA(insert ( 2113 interval_pl - 0 1186 _null_ ));
DATA(insert ( 2114 numeric_add - 1700 _null_ )); DATA(insert ( 2114 numeric_add - 0 1700 _null_ ));
/* max */ /* max */
DATA(insert ( 2115 int8larger - 20 _null_ )); DATA(insert ( 2115 int8larger - 413 20 _null_ ));
DATA(insert ( 2116 int4larger - 23 _null_ )); DATA(insert ( 2116 int4larger - 521 23 _null_ ));
DATA(insert ( 2117 int2larger - 21 _null_ )); DATA(insert ( 2117 int2larger - 520 21 _null_ ));
DATA(insert ( 2118 oidlarger - 26 _null_ )); DATA(insert ( 2118 oidlarger - 610 26 _null_ ));
DATA(insert ( 2119 float4larger - 700 _null_ )); DATA(insert ( 2119 float4larger - 623 700 _null_ ));
DATA(insert ( 2120 float8larger - 701 _null_ )); DATA(insert ( 2120 float8larger - 674 701 _null_ ));
DATA(insert ( 2121 int4larger - 702 _null_ )); DATA(insert ( 2121 int4larger - 563 702 _null_ ));
DATA(insert ( 2122 date_larger - 1082 _null_ )); DATA(insert ( 2122 date_larger - 1097 1082 _null_ ));
DATA(insert ( 2123 time_larger - 1083 _null_ )); DATA(insert ( 2123 time_larger - 1112 1083 _null_ ));
DATA(insert ( 2124 timetz_larger - 1266 _null_ )); DATA(insert ( 2124 timetz_larger - 1554 1266 _null_ ));
DATA(insert ( 2125 cashlarger - 790 _null_ )); DATA(insert ( 2125 cashlarger - 903 790 _null_ ));
DATA(insert ( 2126 timestamp_larger - 1114 _null_ )); DATA(insert ( 2126 timestamp_larger - 2064 1114 _null_ ));
DATA(insert ( 2127 timestamptz_larger - 1184 _null_ )); DATA(insert ( 2127 timestamptz_larger - 1324 1184 _null_ ));
DATA(insert ( 2128 interval_larger - 1186 _null_ )); DATA(insert ( 2128 interval_larger - 1334 1186 _null_ ));
DATA(insert ( 2129 text_larger - 25 _null_ )); DATA(insert ( 2129 text_larger - 666 25 _null_ ));
DATA(insert ( 2130 numeric_larger - 1700 _null_ )); DATA(insert ( 2130 numeric_larger - 1756 1700 _null_ ));
DATA(insert ( 2050 array_larger - 2277 _null_ )); DATA(insert ( 2050 array_larger - 1073 2277 _null_ ));
DATA(insert ( 2244 bpchar_larger - 1060 1042 _null_ ));
/* min */ /* min */
DATA(insert ( 2131 int8smaller - 20 _null_ )); DATA(insert ( 2131 int8smaller - 412 20 _null_ ));
DATA(insert ( 2132 int4smaller - 23 _null_ )); DATA(insert ( 2132 int4smaller - 97 23 _null_ ));
DATA(insert ( 2133 int2smaller - 21 _null_ )); DATA(insert ( 2133 int2smaller - 95 21 _null_ ));
DATA(insert ( 2134 oidsmaller - 26 _null_ )); DATA(insert ( 2134 oidsmaller - 609 26 _null_ ));
DATA(insert ( 2135 float4smaller - 700 _null_ )); DATA(insert ( 2135 float4smaller - 622 700 _null_ ));
DATA(insert ( 2136 float8smaller - 701 _null_ )); DATA(insert ( 2136 float8smaller - 672 701 _null_ ));
DATA(insert ( 2137 int4smaller - 702 _null_ )); DATA(insert ( 2137 int4smaller - 562 702 _null_ ));
DATA(insert ( 2138 date_smaller - 1082 _null_ )); DATA(insert ( 2138 date_smaller - 1095 1082 _null_ ));
DATA(insert ( 2139 time_smaller - 1083 _null_ )); DATA(insert ( 2139 time_smaller - 1110 1083 _null_ ));
DATA(insert ( 2140 timetz_smaller - 1266 _null_ )); DATA(insert ( 2140 timetz_smaller - 1552 1266 _null_ ));
DATA(insert ( 2141 cashsmaller - 790 _null_ )); DATA(insert ( 2141 cashsmaller - 902 790 _null_ ));
DATA(insert ( 2142 timestamp_smaller - 1114 _null_ )); DATA(insert ( 2142 timestamp_smaller - 2062 1114 _null_ ));
DATA(insert ( 2143 timestamptz_smaller - 1184 _null_ )); DATA(insert ( 2143 timestamptz_smaller - 1322 1184 _null_ ));
DATA(insert ( 2144 interval_smaller - 1186 _null_ )); DATA(insert ( 2144 interval_smaller - 1332 1186 _null_ ));
DATA(insert ( 2145 text_smaller - 25 _null_ )); DATA(insert ( 2145 text_smaller - 664 25 _null_ ));
DATA(insert ( 2146 numeric_smaller - 1700 _null_ )); DATA(insert ( 2146 numeric_smaller - 1754 1700 _null_ ));
DATA(insert ( 2051 array_smaller - 2277 _null_ )); DATA(insert ( 2051 array_smaller - 1072 2277 _null_ ));
DATA(insert ( 2245 bpchar_smaller - 1058 1042 _null_ ));
/* /*
* Using int8inc for count() is cheating a little, since it really only * Using int8inc for count() is cheating a little, since it really only
* takes 1 parameter not 2, but nodeAgg.c won't complain ... * takes 1 parameter not 2, but nodeAgg.c won't complain ...
*/ */
DATA(insert ( 2147 int8inc - 20 0 )); DATA(insert ( 2147 int8inc - 0 20 0 ));
/* variance */ /* variance */
DATA(insert ( 2148 int8_accum numeric_variance 1231 "{0,0,0}" )); DATA(insert ( 2148 int8_accum numeric_variance 0 1231 "{0,0,0}" ));
DATA(insert ( 2149 int4_accum numeric_variance 1231 "{0,0,0}" )); DATA(insert ( 2149 int4_accum numeric_variance 0 1231 "{0,0,0}" ));
DATA(insert ( 2150 int2_accum numeric_variance 1231 "{0,0,0}" )); DATA(insert ( 2150 int2_accum numeric_variance 0 1231 "{0,0,0}" ));
DATA(insert ( 2151 float4_accum float8_variance 1022 "{0,0,0}" )); DATA(insert ( 2151 float4_accum float8_variance 0 1022 "{0,0,0}" ));
DATA(insert ( 2152 float8_accum float8_variance 1022 "{0,0,0}" )); DATA(insert ( 2152 float8_accum float8_variance 0 1022 "{0,0,0}" ));
DATA(insert ( 2153 numeric_accum numeric_variance 1231 "{0,0,0}" )); DATA(insert ( 2153 numeric_accum numeric_variance 0 1231 "{0,0,0}" ));
/* stddev */ /* stddev */
DATA(insert ( 2154 int8_accum numeric_stddev 1231 "{0,0,0}" )); DATA(insert ( 2154 int8_accum numeric_stddev 0 1231 "{0,0,0}" ));
DATA(insert ( 2155 int4_accum numeric_stddev 1231 "{0,0,0}" )); DATA(insert ( 2155 int4_accum numeric_stddev 0 1231 "{0,0,0}" ));
DATA(insert ( 2156 int2_accum numeric_stddev 1231 "{0,0,0}" )); DATA(insert ( 2156 int2_accum numeric_stddev 0 1231 "{0,0,0}" ));
DATA(insert ( 2157 float4_accum float8_stddev 1022 "{0,0,0}" )); DATA(insert ( 2157 float4_accum float8_stddev 0 1022 "{0,0,0}" ));
DATA(insert ( 2158 float8_accum float8_stddev 1022 "{0,0,0}" )); DATA(insert ( 2158 float8_accum float8_stddev 0 1022 "{0,0,0}" ));
DATA(insert ( 2159 numeric_accum numeric_stddev 1231 "{0,0,0}" )); DATA(insert ( 2159 numeric_accum numeric_stddev 0 1231 "{0,0,0}" ));
/* boolean-and and boolean-or */ /* boolean-and and boolean-or */
DATA(insert ( 2517 booland_statefunc - 16 _null_ )); DATA(insert ( 2517 booland_statefunc - 0 16 _null_ ));
DATA(insert ( 2518 boolor_statefunc - 16 _null_ )); DATA(insert ( 2518 boolor_statefunc - 0 16 _null_ ));
DATA(insert ( 2519 booland_statefunc - 16 _null_ )); DATA(insert ( 2519 booland_statefunc - 0 16 _null_ ));
/* bitwise integer */ /* bitwise integer */
DATA(insert ( 2236 int2and - 21 _null_ )); DATA(insert ( 2236 int2and - 0 21 _null_ ));
DATA(insert ( 2237 int2or - 21 _null_ )); DATA(insert ( 2237 int2or - 0 21 _null_ ));
DATA(insert ( 2238 int4and - 23 _null_ )); DATA(insert ( 2238 int4and - 0 23 _null_ ));
DATA(insert ( 2239 int4or - 23 _null_ )); DATA(insert ( 2239 int4or - 0 23 _null_ ));
DATA(insert ( 2240 int8and - 20 _null_ )); DATA(insert ( 2240 int8and - 0 20 _null_ ));
DATA(insert ( 2241 int8or - 20 _null_ )); DATA(insert ( 2241 int8or - 0 20 _null_ ));
DATA(insert ( 2242 bitand - 1560 _null_ )); DATA(insert ( 2242 bitand - 0 1560 _null_ ));
DATA(insert ( 2243 bitor - 1560 _null_ )); DATA(insert ( 2243 bitor - 0 1560 _null_ ));
/* /*
* prototypes for functions in pg_aggregate.c * prototypes for functions in pg_aggregate.c
*/ */
extern void AggregateCreate(const char *aggName, extern void AggregateCreate(const char *aggName,
Oid aggNamespace, Oid aggNamespace,
Oid aggBaseType,
List *aggtransfnName, List *aggtransfnName,
List *aggfinalfnName, List *aggfinalfnName,
Oid aggBaseType, List *aggsortopName,
Oid aggTransType, Oid aggTransType,
const char *agginitval); const char *agginitval);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.357 2005/03/31 22:46:18 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.358 2005/04/12 04:26:28 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -1372,6 +1372,10 @@ DATA(insert OID = 1052 ( bpcharge PGNSP PGUID 12 f f t f i 2 16 "1042 1042" ...@@ -1372,6 +1372,10 @@ DATA(insert OID = 1052 ( bpcharge PGNSP PGUID 12 f f t f i 2 16 "1042 1042"
DESCR("greater-than-or-equal"); DESCR("greater-than-or-equal");
DATA(insert OID = 1053 ( bpcharne PGNSP PGUID 12 f f t f i 2 16 "1042 1042" _null_ _null_ _null_ bpcharne - _null_ )); DATA(insert OID = 1053 ( bpcharne PGNSP PGUID 12 f f t f i 2 16 "1042 1042" _null_ _null_ _null_ bpcharne - _null_ ));
DESCR("not equal"); DESCR("not equal");
DATA(insert OID = 1063 ( bpchar_larger PGNSP PGUID 12 f f t f i 2 1042 "1042 1042" _null_ _null_ _null_ bpchar_larger - _null_ ));
DESCR("larger of two");
DATA(insert OID = 1064 ( bpchar_smaller PGNSP PGUID 12 f f t f i 2 1042 "1042 1042" _null_ _null_ _null_ bpchar_smaller - _null_ ));
DESCR("smaller of two");
DATA(insert OID = 1078 ( bpcharcmp PGNSP PGUID 12 f f t f i 2 23 "1042 1042" _null_ _null_ _null_ bpcharcmp - _null_ )); DATA(insert OID = 1078 ( bpcharcmp PGNSP PGUID 12 f f t f i 2 23 "1042 1042" _null_ _null_ _null_ bpcharcmp - _null_ ));
DESCR("less-equal-greater"); DESCR("less-equal-greater");
DATA(insert OID = 1080 ( hashbpchar PGNSP PGUID 12 f f t f i 1 23 "1042" _null_ _null_ _null_ hashbpchar - _null_ )); DATA(insert OID = 1080 ( hashbpchar PGNSP PGUID 12 f f t f i 1 23 "1042" _null_ _null_ _null_ hashbpchar - _null_ ));
...@@ -3048,6 +3052,7 @@ DATA(insert OID = 2128 ( max PGNSP PGUID 12 t f f f i 1 1186 "1186" _null_ _ ...@@ -3048,6 +3052,7 @@ DATA(insert OID = 2128 ( max PGNSP PGUID 12 t f f f i 1 1186 "1186" _null_ _
DATA(insert OID = 2129 ( max PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2129 ( max PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2130 ( max PGNSP PGUID 12 t f f f i 1 1700 "1700" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2130 ( max PGNSP PGUID 12 t f f f i 1 1700 "1700" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2050 ( max PGNSP PGUID 12 t f f f i 1 2277 "2277" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2050 ( max PGNSP PGUID 12 t f f f i 1 2277 "2277" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2244 ( max PGNSP PGUID 12 t f f f i 1 1042 "1042" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2131 ( min PGNSP PGUID 12 t f f f i 1 20 "20" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2131 ( min PGNSP PGUID 12 t f f f i 1 20 "20" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2132 ( min PGNSP PGUID 12 t f f f i 1 23 "23" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2132 ( min PGNSP PGUID 12 t f f f i 1 23 "23" _null_ _null_ _null_ aggregate_dummy - _null_ ));
...@@ -3066,6 +3071,7 @@ DATA(insert OID = 2144 ( min PGNSP PGUID 12 t f f f i 1 1186 "1186" _null_ _ ...@@ -3066,6 +3071,7 @@ DATA(insert OID = 2144 ( min PGNSP PGUID 12 t f f f i 1 1186 "1186" _null_ _
DATA(insert OID = 2145 ( min PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2145 ( min PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2146 ( min PGNSP PGUID 12 t f f f i 1 1700 "1700" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2146 ( min PGNSP PGUID 12 t f f f i 1 1700 "1700" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2051 ( min PGNSP PGUID 12 t f f f i 1 2277 "2277" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2051 ( min PGNSP PGUID 12 t f f f i 1 2277 "2277" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2245 ( min PGNSP PGUID 12 t f f f i 1 1042 "1042" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DATA(insert OID = 2147 ( count PGNSP PGUID 12 t f f f i 1 20 "2276" _null_ _null_ _null_ aggregate_dummy - _null_ )); DATA(insert OID = 2147 ( count PGNSP PGUID 12 t f f f i 1 20 "2276" _null_ _null_ _null_ aggregate_dummy - _null_ ));
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.254 2005/03/29 00:17:18 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.255 2005/04/12 04:26:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -522,6 +522,8 @@ extern Datum bpcharle(PG_FUNCTION_ARGS); ...@@ -522,6 +522,8 @@ extern Datum bpcharle(PG_FUNCTION_ARGS);
extern Datum bpchargt(PG_FUNCTION_ARGS); extern Datum bpchargt(PG_FUNCTION_ARGS);
extern Datum bpcharge(PG_FUNCTION_ARGS); extern Datum bpcharge(PG_FUNCTION_ARGS);
extern Datum bpcharcmp(PG_FUNCTION_ARGS); extern Datum bpcharcmp(PG_FUNCTION_ARGS);
extern Datum bpchar_larger(PG_FUNCTION_ARGS);
extern Datum bpchar_smaller(PG_FUNCTION_ARGS);
extern Datum bpcharlen(PG_FUNCTION_ARGS); extern Datum bpcharlen(PG_FUNCTION_ARGS);
extern Datum bpcharoctetlen(PG_FUNCTION_ARGS); extern Datum bpcharoctetlen(PG_FUNCTION_ARGS);
extern Datum hashbpchar(PG_FUNCTION_ARGS); extern Datum hashbpchar(PG_FUNCTION_ARGS);
......
...@@ -25,6 +25,14 @@ WHERE aggfinalfn != 0 AND ...@@ -25,6 +25,14 @@ WHERE aggfinalfn != 0 AND
------+------------ ------+------------
(0 rows) (0 rows)
SELECT ctid, aggsortop
FROM pg_catalog.pg_aggregate fk
WHERE aggsortop != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.aggsortop);
ctid | aggsortop
------+-----------
(0 rows)
SELECT ctid, aggtranstype SELECT ctid, aggtranstype
FROM pg_catalog.pg_aggregate fk FROM pg_catalog.pg_aggregate fk
WHERE aggtranstype != 0 AND WHERE aggtranstype != 0 AND
...@@ -33,14 +41,6 @@ WHERE aggtranstype != 0 AND ...@@ -33,14 +41,6 @@ WHERE aggtranstype != 0 AND
------+-------------- ------+--------------
(0 rows) (0 rows)
SELECT ctid, amgettuple
FROM pg_catalog.pg_am fk
WHERE amgettuple != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgettuple);
ctid | amgettuple
------+------------
(0 rows)
SELECT ctid, aminsert SELECT ctid, aminsert
FROM pg_catalog.pg_am fk FROM pg_catalog.pg_am fk
WHERE aminsert != 0 AND WHERE aminsert != 0 AND
...@@ -57,6 +57,22 @@ WHERE ambeginscan != 0 AND ...@@ -57,6 +57,22 @@ WHERE ambeginscan != 0 AND
------+------------- ------+-------------
(0 rows) (0 rows)
SELECT ctid, amgettuple
FROM pg_catalog.pg_am fk
WHERE amgettuple != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgettuple);
ctid | amgettuple
------+------------
(0 rows)
SELECT ctid, amgetmulti
FROM pg_catalog.pg_am fk
WHERE amgetmulti != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgetmulti);
ctid | amgetmulti
------+------------
(0 rows)
SELECT ctid, amrescan SELECT ctid, amrescan
FROM pg_catalog.pg_am fk FROM pg_catalog.pg_am fk
WHERE amrescan != 0 AND WHERE amrescan != 0 AND
......
...@@ -677,6 +677,53 @@ WHERE a.aggfnoid = p.oid AND ...@@ -677,6 +677,53 @@ WHERE a.aggfnoid = p.oid AND
----------+---------+-----+--------- ----------+---------+-----+---------
(0 rows) (0 rows)
-- Cross-check aggsortop (if present) against pg_operator.
-- We expect to find only "<" for "min" and ">" for "max".
SELECT DISTINCT proname, oprname
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid
ORDER BY 1;
proname | oprname
---------+---------
max | >
min | <
(2 rows)
-- Check datatypes match
SELECT a.aggfnoid::oid, o.oid
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
(oprkind != 'b' OR oprresult != 'boolean'::regtype
OR oprleft != p.proargtypes[0] OR oprright != p.proargtypes[0]);
aggfnoid | oid
----------+-----
(0 rows)
-- Check operator is a suitable btree opclass member
SELECT a.aggfnoid::oid, o.oid
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
NOT EXISTS(SELECT 1 FROM pg_amop ao, pg_opclass oc
WHERE amopclaid = oc.oid AND amopsubtype = 0
AND amopopr = o.oid AND opcamid = 403
AND opcintype = o.oprleft AND opcdefault);
aggfnoid | oid
----------+-----
(0 rows)
-- Check correspondence of btree strategies and names
SELECT DISTINCT proname, oprname, amopstrategy
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p,
pg_amop as ao, pg_opclass oc
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
amopclaid = oc.oid AND amopopr = o.oid AND opcamid = 403
ORDER BY 1;
proname | oprname | amopstrategy
---------+---------+--------------
max | > | 5
min | < | 1
(2 rows)
-- **************** pg_opclass **************** -- **************** pg_opclass ****************
-- Look for illegal values in pg_opclass fields -- Look for illegal values in pg_opclass fields
SELECT p1.oid SELECT p1.oid
......
...@@ -13,14 +13,14 @@ SELECT ctid, aggfinalfn ...@@ -13,14 +13,14 @@ SELECT ctid, aggfinalfn
FROM pg_catalog.pg_aggregate fk FROM pg_catalog.pg_aggregate fk
WHERE aggfinalfn != 0 AND WHERE aggfinalfn != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.aggfinalfn); NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.aggfinalfn);
SELECT ctid, aggsortop
FROM pg_catalog.pg_aggregate fk
WHERE aggsortop != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.aggsortop);
SELECT ctid, aggtranstype SELECT ctid, aggtranstype
FROM pg_catalog.pg_aggregate fk FROM pg_catalog.pg_aggregate fk
WHERE aggtranstype != 0 AND WHERE aggtranstype != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.aggtranstype); NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.aggtranstype);
SELECT ctid, amgettuple
FROM pg_catalog.pg_am fk
WHERE amgettuple != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgettuple);
SELECT ctid, aminsert SELECT ctid, aminsert
FROM pg_catalog.pg_am fk FROM pg_catalog.pg_am fk
WHERE aminsert != 0 AND WHERE aminsert != 0 AND
...@@ -29,6 +29,14 @@ SELECT ctid, ambeginscan ...@@ -29,6 +29,14 @@ SELECT ctid, ambeginscan
FROM pg_catalog.pg_am fk FROM pg_catalog.pg_am fk
WHERE ambeginscan != 0 AND WHERE ambeginscan != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.ambeginscan); NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.ambeginscan);
SELECT ctid, amgettuple
FROM pg_catalog.pg_am fk
WHERE amgettuple != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgettuple);
SELECT ctid, amgetmulti
FROM pg_catalog.pg_am fk
WHERE amgetmulti != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgetmulti);
SELECT ctid, amrescan SELECT ctid, amrescan
FROM pg_catalog.pg_am fk FROM pg_catalog.pg_am fk
WHERE amrescan != 0 AND WHERE amrescan != 0 AND
......
...@@ -561,6 +561,41 @@ WHERE a.aggfnoid = p.oid AND ...@@ -561,6 +561,41 @@ WHERE a.aggfnoid = p.oid AND
a.agginitval IS NULL AND a.agginitval IS NULL AND
NOT binary_coercible(p.proargtypes[0], a.aggtranstype); NOT binary_coercible(p.proargtypes[0], a.aggtranstype);
-- Cross-check aggsortop (if present) against pg_operator.
-- We expect to find only "<" for "min" and ">" for "max".
SELECT DISTINCT proname, oprname
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid
ORDER BY 1;
-- Check datatypes match
SELECT a.aggfnoid::oid, o.oid
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
(oprkind != 'b' OR oprresult != 'boolean'::regtype
OR oprleft != p.proargtypes[0] OR oprright != p.proargtypes[0]);
-- Check operator is a suitable btree opclass member
SELECT a.aggfnoid::oid, o.oid
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
NOT EXISTS(SELECT 1 FROM pg_amop ao, pg_opclass oc
WHERE amopclaid = oc.oid AND amopsubtype = 0
AND amopopr = o.oid AND opcamid = 403
AND opcintype = o.oprleft AND opcdefault);
-- Check correspondence of btree strategies and names
SELECT DISTINCT proname, oprname, amopstrategy
FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p,
pg_amop as ao, pg_opclass oc
WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
amopclaid = oc.oid AND amopopr = o.oid AND opcamid = 403
ORDER BY 1;
-- **************** pg_opclass **************** -- **************** pg_opclass ****************
-- Look for illegal values in pg_opclass fields -- Look for illegal values in pg_opclass fields
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment