mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
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.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
#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"
|
||||
@@ -42,9 +43,10 @@ static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types,
|
||||
void
|
||||
AggregateCreate(const char *aggName,
|
||||
Oid aggNamespace,
|
||||
Oid aggBaseType,
|
||||
List *aggtransfnName,
|
||||
List *aggfinalfnName,
|
||||
Oid aggBaseType,
|
||||
List *aggsortopName,
|
||||
Oid aggTransType,
|
||||
const char *agginitval)
|
||||
{
|
||||
@@ -55,6 +57,7 @@ AggregateCreate(const char *aggName,
|
||||
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 */
|
||||
@@ -167,6 +170,12 @@ AggregateCreate(const char *aggName,
|
||||
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
|
||||
@@ -207,6 +216,7 @@ AggregateCreate(const char *aggName,
|
||||
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] =
|
||||
@@ -248,6 +258,15 @@ AggregateCreate(const char *aggName,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -51,6 +51,7 @@ DefineAggregate(List *names, List *parameters)
|
||||
AclResult aclresult;
|
||||
List *transfuncName = NIL;
|
||||
List *finalfuncName = NIL;
|
||||
List *sortoperatorName = NIL;
|
||||
TypeName *baseType = NULL;
|
||||
TypeName *transType = NULL;
|
||||
char *initval = NULL;
|
||||
@@ -81,6 +82,8 @@ DefineAggregate(List *names, List *parameters)
|
||||
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)
|
||||
@@ -143,9 +146,10 @@ DefineAggregate(List *names, List *parameters)
|
||||
*/
|
||||
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 */
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
static Oid
|
||||
fetch_agg_sort_op(Oid aggfnoid)
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
HeapTuple aggTuple;
|
||||
Form_pg_aggregate aggform;
|
||||
Oid aggsortop;
|
||||
@@ -558,18 +557,4 @@ fetch_agg_sort_op(Oid aggfnoid)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user