<!--
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">
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>Final function (zero if none)</entry>
</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>
<entry><structfield>aggtranstype</structfield></entry>
<entry><type>oid</type></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>
<entry><structfield>agginitval</structfield></entry>
<entry>
The initial value of the transition state. This is a text
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.
</entry>
</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
-->
STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
[ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
[ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
+ [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
)
</synopsis>
</refsynopsisdiv>
<function>avg</function> returns null when it sees there were zero
input rows.
</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><</> operator is the proper sort
+ operator for <function>MIN</>, and <literal>></> 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>
</para>
</listitem>
</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>
<para>
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/cost.h"
#include "parser/parse_coerce.h"
#include "parser/parse_func.h"
+#include "parser/parse_oper.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
void
AggregateCreate(const char *aggName,
Oid aggNamespace,
+ Oid aggBaseType,
List *aggtransfnName,
List *aggfinalfnName,
- Oid aggBaseType,
+ List *aggsortopName,
Oid aggTransType,
const char *agginitval)
{
Form_pg_proc proc;
Oid transfn;
Oid finalfn = InvalidOid; /* can be omitted */
+ Oid sortop = InvalidOid; /* can be omitted */
Oid rettype;
Oid finaltype;
Oid fnArgs[2]; /* we only deal with 1- and 2-arg fns */
errdetail("An aggregate returning \"anyarray\" or \"anyelement\" "
"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
* aggregate. (This could fail if there's already a conflicting
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_aggsortop - 1] = ObjectIdGetDatum(sortop);
values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
if (agginitval)
values[Anum_pg_aggregate_agginitval - 1] =
referenced.objectSubId = 0;
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);
+ }
}
/*
*
*
* 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
* The "DefineFoo" routines take the parse tree and pick out the
AclResult aclresult;
List *transfuncName = NIL;
List *finalfuncName = NIL;
+ List *sortoperatorName = NIL;
TypeName *baseType = NULL;
TypeName *transType = NULL;
char *initval = NULL;
transfuncName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "finalfunc") == 0)
finalfuncName = defGetQualifiedName(defel);
+ else if (pg_strcasecmp(defel->defname, "sortop") == 0)
+ sortoperatorName = defGetQualifiedName(defel);
else if (pg_strcasecmp(defel->defname, "basetype") == 0)
baseType = defGetTypeName(defel);
else if (pg_strcasecmp(defel->defname, "stype") == 0)
*/
AggregateCreate(aggName, /* aggregate name */
aggNamespace, /* namespace */
+ baseTypeId, /* type of data being aggregated */
transfuncName, /* step function name */
finalfuncName, /* final function name */
- baseTypeId, /* type of data being aggregated */
+ sortoperatorName, /* sort operator name */
transTypeId, /* transition data type */
initval); /* initial condition */
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
static Oid
fetch_agg_sort_op(Oid aggfnoid)
{
-#ifdef NOT_YET
HeapTuple aggTuple;
Form_pg_aggregate aggform;
Oid aggsortop;
ReleaseSysCache(aggTuple);
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
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
* by PostgreSQL
*
* 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 $
*
*-------------------------------------------------------------------------
*/
int ntups;
int i_aggtransfn;
int i_aggfinalfn;
+ int i_aggsortop;
int i_aggtranstype;
int i_agginitval;
int i_anybasetype;
int i_convertok;
const char *aggtransfn;
const char *aggfinalfn;
+ const char *aggsortop;
const char *aggtranstype;
const char *agginitval;
bool convertok;
selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name);
/* 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, "
"aggfinalfn, aggtranstype::pg_catalog.regtype, "
+ "0 as aggsortop, "
"agginitval, "
"proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype as anybasetype, "
"proargtypes[0]::pg_catalog.regtype as fmtbasetype, "
{
appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
"format_type(aggtranstype, NULL) as aggtranstype, "
+ "0 as aggsortop, "
"agginitval, "
"aggbasetype = 0 as anybasetype, "
"CASE WHEN aggbasetype = 0 THEN '-' "
appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, "
"aggfinalfn, "
"(select typname from pg_type where oid = aggtranstype1) as aggtranstype, "
+ "0 as aggsortop, "
"agginitval1 as agginitval, "
"aggbasetype = 0 as anybasetype, "
"(select typname from pg_type where oid = aggbasetype) as fmtbasetype, "
i_aggtransfn = PQfnumber(res, "aggtransfn");
i_aggfinalfn = PQfnumber(res, "aggfinalfn");
+ i_aggsortop = PQfnumber(res, "aggsortop");
i_aggtranstype = PQfnumber(res, "aggtranstype");
i_agginitval = PQfnumber(res, "agginitval");
i_anybasetype = PQfnumber(res, "anybasetype");
aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
+ aggsortop = PQgetvalue(res, 0, i_aggsortop);
aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
agginitval = PQgetvalue(res, 0, i_agginitval);
/* we save anybasetype for format_aggregate_signature */
aggfinalfn);
}
+ aggsortop = convertOperatorReference(aggsortop);
+ if (aggsortop)
+ {
+ appendPQExpBuffer(details, ",\n SORTOP = %s",
+ aggsortop);
+ }
+
/*
* DROP must be fully qualified in case same name appears in
* pg_catalog
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200504061
+#define CATALOG_VERSION_NO 200504111
#endif
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* 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
* the genbki.sh script reads this file and generates .bki
*
* aggfnoid pg_proc OID of the aggregate itself
* 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
- * agginitval initial value for transition state
+ * agginitval initial value for transition state (can be NULL)
* ----------------------------------------------------------------
*/
CATALOG(pg_aggregate) BKI_WITHOUT_OIDS
regproc aggfnoid;
regproc aggtransfn;
regproc aggfinalfn;
+ Oid aggsortop;
Oid aggtranstype;
text agginitval; /* VARIABLE LENGTH FIELD */
} FormData_pg_aggregate;
* ----------------
*/
-#define Natts_pg_aggregate 5
+#define Natts_pg_aggregate 6
#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
+#define Anum_pg_aggregate_aggsortop 4
+#define Anum_pg_aggregate_aggtranstype 5
+#define Anum_pg_aggregate_agginitval 6
/* ----------------
*/
/* 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 ( 2100 int8_accum numeric_avg 0 1231 "{0,0,0}" ));
+DATA(insert ( 2101 int4_avg_accum int8_avg 0 1016 "{0,0}" ));
+DATA(insert ( 2102 int2_avg_accum int8_avg 0 1016 "{0,0}" ));
+DATA(insert ( 2103 numeric_accum numeric_avg 0 1231 "{0,0,0}" ));
+DATA(insert ( 2104 float4_accum float8_avg 0 1022 "{0,0,0}" ));
+DATA(insert ( 2105 float8_accum float8_avg 0 1022 "{0,0,0}" ));
+DATA(insert ( 2106 interval_accum interval_avg 0 1187 "{0 second,0 second}" ));
/* 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 ( 2107 int8_sum - 0 1700 _null_ ));
+DATA(insert ( 2108 int4_sum - 0 20 _null_ ));
+DATA(insert ( 2109 int2_sum - 0 20 _null_ ));
+DATA(insert ( 2110 float4pl - 0 700 _null_ ));
+DATA(insert ( 2111 float8pl - 0 701 _null_ ));
+DATA(insert ( 2112 cash_pl - 0 790 _null_ ));
+DATA(insert ( 2113 interval_pl - 0 1186 _null_ ));
+DATA(insert ( 2114 numeric_add - 0 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 ( 2050 array_larger - 2277 _null_ ));
+DATA(insert ( 2115 int8larger - 413 20 _null_ ));
+DATA(insert ( 2116 int4larger - 521 23 _null_ ));
+DATA(insert ( 2117 int2larger - 520 21 _null_ ));
+DATA(insert ( 2118 oidlarger - 610 26 _null_ ));
+DATA(insert ( 2119 float4larger - 623 700 _null_ ));
+DATA(insert ( 2120 float8larger - 674 701 _null_ ));
+DATA(insert ( 2121 int4larger - 563 702 _null_ ));
+DATA(insert ( 2122 date_larger - 1097 1082 _null_ ));
+DATA(insert ( 2123 time_larger - 1112 1083 _null_ ));
+DATA(insert ( 2124 timetz_larger - 1554 1266 _null_ ));
+DATA(insert ( 2125 cashlarger - 903 790 _null_ ));
+DATA(insert ( 2126 timestamp_larger - 2064 1114 _null_ ));
+DATA(insert ( 2127 timestamptz_larger - 1324 1184 _null_ ));
+DATA(insert ( 2128 interval_larger - 1334 1186 _null_ ));
+DATA(insert ( 2129 text_larger - 666 25 _null_ ));
+DATA(insert ( 2130 numeric_larger - 1756 1700 _null_ ));
+DATA(insert ( 2050 array_larger - 1073 2277 _null_ ));
+DATA(insert ( 2244 bpchar_larger - 1060 1042 _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_ ));
-DATA(insert ( 2051 array_smaller - 2277 _null_ ));
+DATA(insert ( 2131 int8smaller - 412 20 _null_ ));
+DATA(insert ( 2132 int4smaller - 97 23 _null_ ));
+DATA(insert ( 2133 int2smaller - 95 21 _null_ ));
+DATA(insert ( 2134 oidsmaller - 609 26 _null_ ));
+DATA(insert ( 2135 float4smaller - 622 700 _null_ ));
+DATA(insert ( 2136 float8smaller - 672 701 _null_ ));
+DATA(insert ( 2137 int4smaller - 562 702 _null_ ));
+DATA(insert ( 2138 date_smaller - 1095 1082 _null_ ));
+DATA(insert ( 2139 time_smaller - 1110 1083 _null_ ));
+DATA(insert ( 2140 timetz_smaller - 1552 1266 _null_ ));
+DATA(insert ( 2141 cashsmaller - 902 790 _null_ ));
+DATA(insert ( 2142 timestamp_smaller - 2062 1114 _null_ ));
+DATA(insert ( 2143 timestamptz_smaller - 1322 1184 _null_ ));
+DATA(insert ( 2144 interval_smaller - 1332 1186 _null_ ));
+DATA(insert ( 2145 text_smaller - 664 25 _null_ ));
+DATA(insert ( 2146 numeric_smaller - 1754 1700 _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
* 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 */
-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 ( 2148 int8_accum numeric_variance 0 1231 "{0,0,0}" ));
+DATA(insert ( 2149 int4_accum numeric_variance 0 1231 "{0,0,0}" ));
+DATA(insert ( 2150 int2_accum numeric_variance 0 1231 "{0,0,0}" ));
+DATA(insert ( 2151 float4_accum float8_variance 0 1022 "{0,0,0}" ));
+DATA(insert ( 2152 float8_accum float8_variance 0 1022 "{0,0,0}" ));
+DATA(insert ( 2153 numeric_accum numeric_variance 0 1231 "{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}" ));
+DATA(insert ( 2154 int8_accum numeric_stddev 0 1231 "{0,0,0}" ));
+DATA(insert ( 2155 int4_accum numeric_stddev 0 1231 "{0,0,0}" ));
+DATA(insert ( 2156 int2_accum numeric_stddev 0 1231 "{0,0,0}" ));
+DATA(insert ( 2157 float4_accum float8_stddev 0 1022 "{0,0,0}" ));
+DATA(insert ( 2158 float8_accum float8_stddev 0 1022 "{0,0,0}" ));
+DATA(insert ( 2159 numeric_accum numeric_stddev 0 1231 "{0,0,0}" ));
/* boolean-and and boolean-or */
-DATA(insert ( 2517 booland_statefunc - 16 _null_ ));
-DATA(insert ( 2518 boolor_statefunc - 16 _null_ ));
-DATA(insert ( 2519 booland_statefunc - 16 _null_ ));
+DATA(insert ( 2517 booland_statefunc - 0 16 _null_ ));
+DATA(insert ( 2518 boolor_statefunc - 0 16 _null_ ));
+DATA(insert ( 2519 booland_statefunc - 0 16 _null_ ));
/* bitwise integer */
-DATA(insert ( 2236 int2and - 21 _null_ ));
-DATA(insert ( 2237 int2or - 21 _null_ ));
-DATA(insert ( 2238 int4and - 23 _null_ ));
-DATA(insert ( 2239 int4or - 23 _null_ ));
-DATA(insert ( 2240 int8and - 20 _null_ ));
-DATA(insert ( 2241 int8or - 20 _null_ ));
-DATA(insert ( 2242 bitand - 1560 _null_ ));
-DATA(insert ( 2243 bitor - 1560 _null_ ));
+DATA(insert ( 2236 int2and - 0 21 _null_ ));
+DATA(insert ( 2237 int2or - 0 21 _null_ ));
+DATA(insert ( 2238 int4and - 0 23 _null_ ));
+DATA(insert ( 2239 int4or - 0 23 _null_ ));
+DATA(insert ( 2240 int8and - 0 20 _null_ ));
+DATA(insert ( 2241 int8or - 0 20 _null_ ));
+DATA(insert ( 2242 bitand - 0 1560 _null_ ));
+DATA(insert ( 2243 bitor - 0 1560 _null_ ));
/*
* prototypes for functions in pg_aggregate.c
*/
extern void AggregateCreate(const char *aggName,
Oid aggNamespace,
+ Oid aggBaseType,
List *aggtransfnName,
List *aggfinalfnName,
- Oid aggBaseType,
+ List *aggsortopName,
Oid aggTransType,
const char *agginitval);
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* 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
* The script catalog/genbki.sh reads this file and generates .bki
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_ ));
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_ ));
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 = 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 = 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 = 2132 ( min PGNSP PGUID 12 t f f f i 1 23 "23" _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 = 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_ ));
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* 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 $
*
*-------------------------------------------------------------------------
*/
extern Datum bpchargt(PG_FUNCTION_ARGS);
extern Datum bpcharge(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 bpcharoctetlen(PG_FUNCTION_ARGS);
extern Datum hashbpchar(PG_FUNCTION_ARGS);
------+------------
(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
FROM pg_catalog.pg_aggregate fk
WHERE aggtranstype != 0 AND
------+--------------
(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
FROM pg_catalog.pg_am fk
WHERE aminsert != 0 AND
------+-------------
(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
FROM pg_catalog.pg_am fk
WHERE amrescan != 0 AND
----------+---------+-----+---------
(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 ****************
-- Look for illegal values in pg_opclass fields
SELECT p1.oid
FROM pg_catalog.pg_aggregate fk
WHERE aggfinalfn != 0 AND
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
FROM pg_catalog.pg_aggregate fk
WHERE aggtranstype != 0 AND
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
FROM pg_catalog.pg_am fk
WHERE aminsert != 0 AND
FROM pg_catalog.pg_am fk
WHERE ambeginscan != 0 AND
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
FROM pg_catalog.pg_am fk
WHERE amrescan != 0 AND
a.agginitval IS NULL AND
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 ****************
-- Look for illegal values in pg_opclass fields