aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parser.c')
-rw-r--r--src/backend/parser/parser.c844
1 files changed, 449 insertions, 395 deletions
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index ab4276055cd..99c6ce2bfdb 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -6,14 +6,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.22 1997/08/22 07:12:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.23 1997/09/07 04:44:50 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include <pwd.h>
-#include <sys/param.h> /* for MAXPATHLEN */
+#include <sys/param.h> /* for MAXPATHLEN */
#include "postgres.h"
#include "parser/catalog_utils.h"
@@ -34,456 +34,510 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_type.h"
#include "access/heapam.h"
-#include "optimizer/clauses.h"
+#include "optimizer/clauses.h"
-void init_io(); /* from scan.l */
-void parser_init(Oid *typev, int nargs); /* from gram.y */
-int yyparse(); /* from gram.c */
+void init_io(); /* from scan.l */
+void parser_init(Oid * typev, int nargs); /* from gram.y */
+int yyparse(); /* from gram.c */
-char *parseString; /* the char* which holds the string to be parsed */
-char *parseCh; /* a pointer used during parsing to walk down ParseString*/
+char *parseString; /* the char* which holds the string to be
+ * parsed */
+char *parseCh; /* a pointer used during parsing to walk
+ * down ParseString */
-List *parsetree = NIL;
+List *parsetree = NIL;
#ifdef SETS_FIXED
-static void fixupsets();
-static void define_sets();
+static void fixupsets();
+static void define_sets();
+
#endif
/*
* parser-- returns a list of parse trees
- *
- * CALLER is responsible for free'ing the list returned
+ *
+ * CALLER is responsible for free'ing the list returned
*/
-QueryTreeList *
-parser(char *str, Oid *typev, int nargs)
+QueryTreeList *
+parser(char *str, Oid * typev, int nargs)
{
- QueryTreeList* queryList;
- int yyresult;
+ QueryTreeList *queryList;
+ int yyresult;
#if defined(FLEX_SCANNER)
- extern void DeleteBuffer(void);
-#endif /* FLEX_SCANNER */
-
- init_io();
-
- /* Set things up to read from the string, if there is one */
- parseString = (char *) palloc(strlen(str) + 1);
- memmove(parseString,str,strlen(str)+1);
-
- parser_init(typev, nargs);
- yyresult = yyparse();
+ extern void DeleteBuffer(void);
+
+#endif /* FLEX_SCANNER */
+
+ init_io();
+
+ /* Set things up to read from the string, if there is one */
+ parseString = (char *) palloc(strlen(str) + 1);
+ memmove(parseString, str, strlen(str) + 1);
+
+ parser_init(typev, nargs);
+ yyresult = yyparse();
#if defined(FLEX_SCANNER)
- DeleteBuffer();
-#endif /* FLEX_SCANNER */
-
- clearerr(stdin);
-
- if (yyresult) { /* error */
- return((QueryTreeList*)NULL);
- }
-
- queryList = parse_analyze(parsetree);
-
+ DeleteBuffer();
+#endif /* FLEX_SCANNER */
+
+ clearerr(stdin);
+
+ if (yyresult)
+ { /* error */
+ return ((QueryTreeList *) NULL);
+ }
+
+ queryList = parse_analyze(parsetree);
+
#ifdef SETS_FIXED
- /* Fixing up sets calls the parser, so it reassigns the global
- * variable parsetree. So save the real parsetree.
- */
- savetree = parsetree;
- foreach (parse, savetree) { /* savetree is really a list of parses */
- /* find set definitions embedded in query */
- fixupsets((Query *)lfirst(parse));
+ /*
+ * Fixing up sets calls the parser, so it reassigns the global
+ * variable parsetree. So save the real parsetree.
+ */
+ savetree = parsetree;
+ foreach(parse, savetree)
+ { /* savetree is really a list of parses */
+
+ /* find set definitions embedded in query */
+ fixupsets((Query *) lfirst(parse));
- }
- return savetree;
-#endif
+ }
+ return savetree;
+#endif
- return queryList;
+ return queryList;
}
#ifdef SETS_FIXED
static void
-fixupsets(Query *parse)
+fixupsets(Query * parse)
{
- if (parse == NULL)
- return;
- if (parse->commandType==CMD_UTILITY) /* utility */
- return;
- if (parse->commandType!=CMD_INSERT)
- return;
- define_sets(parse);
+ if (parse == NULL)
+ return;
+ if (parse->commandType == CMD_UTILITY) /* utility */
+ return;
+ if (parse->commandType != CMD_INSERT)
+ return;
+ define_sets(parse);
}
/* Recursively find all of the Consts in the parsetree. Some of
* these may represent a set. The value of the Const will be the
- * query (a string) which defines the set. Call SetDefine to define
+ * query (a string) which defines the set. Call SetDefine to define
* the set, and store the OID of the new set in the Const instead.
*/
static void
-define_sets(Node *clause)
+define_sets(Node * clause)
{
- Oid setoid;
- Type t = type("oid");
- Oid typeoid = typeid(t);
- Size oidsize = tlen(t);
- bool oidbyval = tbyval(t);
-
- if (clause==NULL) {
- return;
- } else if (IsA(clause,LispList)) {
- define_sets(lfirst(clause));
- define_sets(lnext(clause));
- } else if (IsA(clause,Const)) {
- if (get_constisnull((Const)clause) ||
- !get_constisset((Const)clause)) {
- return;
+ Oid setoid;
+ Type t = type("oid");
+ Oid typeoid = typeid(t);
+ Size oidsize = tlen(t);
+ bool oidbyval = tbyval(t);
+
+ if (clause == NULL)
+ {
+ return;
+ }
+ else if (IsA(clause, LispList))
+ {
+ define_sets(lfirst(clause));
+ define_sets(lnext(clause));
+ }
+ else if (IsA(clause, Const))
+ {
+ if (get_constisnull((Const) clause) ||
+ !get_constisset((Const) clause))
+ {
+ return;
+ }
+ setoid = SetDefine(((Const *) clause)->constvalue,
+ get_id_typname(((Const *) clause)->consttype));
+ set_constvalue((Const) clause, setoid);
+ set_consttype((Const) clause, typeoid);
+ set_constlen((Const) clause, oidsize);
+ set_constbyval((Const) clause, oidbyval);
+ }
+ else if (IsA(clause, Iter))
+ {
+ define_sets(((Iter *) clause)->iterexpr);
+ }
+ else if (single_node(clause))
+ {
+ return;
+ }
+ else if (or_clause(clause))
+ {
+ List *temp;
+
+ /* mapcan */
+ foreach(temp, ((Expr *) clause)->args)
+ {
+ define_sets(lfirst(temp));
+ }
}
- setoid = SetDefine(((Const*)clause)->constvalue,
- get_id_typname(((Const*)clause)->consttype));
- set_constvalue((Const)clause, setoid);
- set_consttype((Const)clause,typeoid);
- set_constlen((Const)clause,oidsize);
- set_constbyval((Const)clause,oidbyval);
- } else if ( IsA(clause,Iter) ) {
- define_sets(((Iter*)clause)->iterexpr);
- } else if (single_node (clause)) {
- return;
- } else if (or_clause(clause)) {
- List *temp;
- /* mapcan */
- foreach (temp, ((Expr*)clause)->args) {
- define_sets(lfirst(temp));
+ else if (is_funcclause(clause))
+ {
+ List *temp;
+
+ /* mapcan */
+ foreach(temp, ((Expr *) clause)->args)
+ {
+ define_sets(lfirst(temp));
+ }
}
- } else if (is_funcclause (clause)) {
- List *temp;
- /* mapcan */
- foreach(temp, ((Expr*)clause)->args) {
- define_sets(lfirst(temp));
+ else if (IsA(clause, ArrayRef))
+ {
+ define_sets(((ArrayRef *) clause)->refassgnexpr);
+ }
+ else if (not_clause(clause))
+ {
+ define_sets(get_notclausearg(clause));
+ }
+ else if (is_opclause(clause))
+ {
+ define_sets(get_leftop(clause));
+ define_sets(get_rightop(clause));
}
- } else if (IsA(clause,ArrayRef)) {
- define_sets(((ArrayRef*)clause)->refassgnexpr);
- } else if (not_clause (clause)) {
- define_sets (get_notclausearg (clause));
- } else if (is_opclause (clause)) {
- define_sets(get_leftop (clause));
- define_sets(get_rightop (clause));
- }
}
+
#endif
/* not used
-#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
+#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
*/
-Node *
-parser_typecast(Value *expr, TypeName *typename, int typlen)
+Node *
+parser_typecast(Value * expr, TypeName * typename, int typlen)
{
- /* check for passing non-ints */
- Const *adt;
- Datum lcp;
- Type tp;
- char type_string[16];
- int32 len;
- char *cp = NULL;
- char *const_string = NULL;
- bool string_palloced = false;
-
- switch(nodeTag(expr)) {
- case T_String:
- const_string = DatumGetPointer(expr->val.str);
- break;
- case T_Integer:
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string, "%d", expr->val.ival);
- break;
- default:
- elog(WARN,
- "parser_typecast: cannot cast this expression to type \"%s\"",
- typename->name);
- }
-
- if (typename->arrayBounds != NIL) {
- sprintf(type_string,"_%s", typename->name);
- tp = (Type) type(type_string);
- } else {
- tp = (Type) type(typename->name);
- }
-
- len = tlen(tp);
-
-#if 0 /* fix me */
- switch ( CInteger(lfirst(expr)) ) {
- case INT4OID: /* int4 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d", ((Const*)lnext(expr))->constvalue);
- break;
-
- case NAMEOID: /* char16 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%s", ((Const*)lnext(expr))->constvalue);
- break;
-
- case CHAROID: /* char */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%c", ((Const)lnext(expr))->constvalue);
- break;
-
- case FLOAT8OID:/* float8 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", ((Const)lnext(expr))->constvalue);
- break;
-
- case CASHOID: /* money */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d",
- (int) ((Const*)expr)->constvalue);
- break;
-
- case TEXTOID: /* text */
- const_string = DatumGetPointer(((Const)lnext(expr))->constvalue);
- const_string = (char *) textout((struct varlena *)const_string);
- break;
-
- case UNKNOWNOID: /* unknown */
- const_string = DatumGetPointer(((Const)lnext(expr))->constvalue);
- const_string = (char *) textout((struct varlena *)const_string);
- break;
-
- default:
- elog(WARN,"unknown type %d", CInteger(lfirst(expr)));
- }
+ /* check for passing non-ints */
+ Const *adt;
+ Datum lcp;
+ Type tp;
+ char type_string[16];
+ int32 len;
+ char *cp = NULL;
+ char *const_string = NULL;
+ bool string_palloced = false;
+
+ switch (nodeTag(expr))
+ {
+ case T_String:
+ const_string = DatumGetPointer(expr->val.str);
+ break;
+ case T_Integer:
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%d", expr->val.ival);
+ break;
+ default:
+ elog(WARN,
+ "parser_typecast: cannot cast this expression to type \"%s\"",
+ typename->name);
+ }
+
+ if (typename->arrayBounds != NIL)
+ {
+ sprintf(type_string, "_%s", typename->name);
+ tp = (Type) type(type_string);
+ }
+ else
+ {
+ tp = (Type) type(typename->name);
+ }
+
+ len = tlen(tp);
+
+#if 0 /* fix me */
+ switch (CInteger(lfirst(expr)))
+ {
+ case INT4OID: /* int4 */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%d", ((Const *) lnext(expr))->constvalue);
+ break;
+
+ case NAMEOID: /* char16 */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%s", ((Const *) lnext(expr))->constvalue);
+ break;
+
+ case CHAROID: /* char */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%c", ((Const) lnext(expr))->constvalue);
+ break;
+
+ case FLOAT8OID: /* float8 */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%f", ((Const) lnext(expr))->constvalue);
+ break;
+
+ case CASHOID: /* money */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%d",
+ (int) ((Const *) expr)->constvalue);
+ break;
+
+ case TEXTOID: /* text */
+ const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
+ const_string = (char *) textout((struct varlena *) const_string);
+ break;
+
+ case UNKNOWNOID: /* unknown */
+ const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
+ const_string = (char *) textout((struct varlena *) const_string);
+ break;
+
+ default:
+ elog(WARN, "unknown type %d", CInteger(lfirst(expr)));
+ }
#endif
- cp = instr2 (tp, const_string, typlen);
-
- if (!tbyvalue(tp)) {
+ cp = instr2(tp, const_string, typlen);
+
+ if (!tbyvalue(tp))
+ {
/*
- if (len >= 0 && len != PSIZE(cp)) {
- char *pp;
- pp = (char *) palloc(len);
- memmove(pp, cp, len);
- cp = pp;
- }
+ if (len >= 0 && len != PSIZE(cp)) {
+ char *pp;
+ pp = (char *) palloc(len);
+ memmove(pp, cp, len);
+ cp = pp;
+ }
*/
- lcp = PointerGetDatum(cp);
- } else {
- switch(len) {
- case 1:
- lcp = Int8GetDatum(cp);
- break;
- case 2:
- lcp = Int16GetDatum(cp);
- break;
- case 4:
- lcp = Int32GetDatum(cp);
- break;
- default:
- lcp = PointerGetDatum(cp);
- break;
+ lcp = PointerGetDatum(cp);
+ }
+ else
+ {
+ switch (len)
+ {
+ case 1:
+ lcp = Int8GetDatum(cp);
+ break;
+ case 2:
+ lcp = Int16GetDatum(cp);
+ break;
+ case 4:
+ lcp = Int32GetDatum(cp);
+ break;
+ default:
+ lcp = PointerGetDatum(cp);
+ break;
+ }
}
- }
-
- adt = makeConst(typeid(tp),
- len,
- (Datum)lcp ,
- false,
- tbyvalue(tp),
- false, /* not a set */
- true /* is cast */);
-
- if (string_palloced)
- pfree(const_string);
-
- return (Node*)adt;
+
+ adt = makeConst(typeid(tp),
+ len,
+ (Datum) lcp,
+ false,
+ tbyvalue(tp),
+ false, /* not a set */
+ true /* is cast */ );
+
+ if (string_palloced)
+ pfree(const_string);
+
+ return (Node *) adt;
}
-Node *
-parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
+Node *
+parser_typecast2(Node * expr, Oid exprType, Type tp, int typlen)
{
- /* check for passing non-ints */
- Const *adt;
- Datum lcp;
- int32 len = tlen(tp);
- char *cp = NULL;
-
- char *const_string = NULL;
- bool string_palloced = false;
-
- Assert(IsA(expr,Const));
-
- switch (exprType) {
- case 0: /* NULL */
- break;
- case INT4OID: /* int4 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d",
- (int) ((Const*)expr)->constvalue);
- break;
- case NAMEOID: /* char16 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%s",
- (char*) ((Const*)expr)->constvalue);
- break;
- case CHAROID: /* char */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%c",
- (char) ((Const*)expr)->constvalue);
- break;
- case FLOAT4OID: /* float4 */
+ /* check for passing non-ints */
+ Const *adt;
+ Datum lcp;
+ int32 len = tlen(tp);
+ char *cp = NULL;
+
+ char *const_string = NULL;
+ bool string_palloced = false;
+
+ Assert(IsA(expr, Const));
+
+ switch (exprType)
{
- float32 floatVal =
- DatumGetFloat32(((Const*)expr)->constvalue);
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", *floatVal);
- break;
+ case 0: /* NULL */
+ break;
+ case INT4OID: /* int4 */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%d",
+ (int) ((Const *) expr)->constvalue);
+ break;
+ case NAMEOID: /* char16 */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%s",
+ (char *) ((Const *) expr)->constvalue);
+ break;
+ case CHAROID: /* char */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%c",
+ (char) ((Const *) expr)->constvalue);
+ break;
+ case FLOAT4OID: /* float4 */
+ {
+ float32 floatVal =
+ DatumGetFloat32(((Const *) expr)->constvalue);
+
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%f", *floatVal);
+ break;
+ }
+ case FLOAT8OID: /* float8 */
+ {
+ float64 floatVal =
+ DatumGetFloat64(((Const *) expr)->constvalue);
+
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%f", *floatVal);
+ break;
+ }
+ case CASHOID: /* money */
+ const_string = (char *) palloc(256);
+ string_palloced = true;
+ sprintf(const_string, "%d",
+ (long) ((Const *) expr)->constvalue);
+ break;
+ case TEXTOID: /* text */
+ const_string =
+ DatumGetPointer(((Const *) expr)->constvalue);
+ const_string = (char *) textout((struct varlena *) const_string);
+ break;
+ case UNKNOWNOID: /* unknown */
+ const_string =
+ DatumGetPointer(((Const *) expr)->constvalue);
+ const_string = (char *) textout((struct varlena *) const_string);
+ break;
+ default:
+ elog(WARN, "unknown type %u ", exprType);
}
- case FLOAT8OID:/* float8 */
+
+ if (!exprType)
{
- float64 floatVal =
- DatumGetFloat64(((Const*)expr)->constvalue);
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", *floatVal);
- break;
+ adt = makeConst(typeid(tp),
+ (Size) 0,
+ (Datum) NULL,
+ true, /* isnull */
+ false, /* was omitted */
+ false, /* not a set */
+ true /* is cast */ );
+ return ((Node *) adt);
}
- case CASHOID: /* money */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d",
- (long) ((Const*)expr)->constvalue);
- break;
- case TEXTOID: /* text */
- const_string =
- DatumGetPointer(((Const*)expr)->constvalue );
- const_string = (char *) textout((struct varlena *)const_string);
- break;
- case UNKNOWNOID: /* unknown */
- const_string =
- DatumGetPointer(((Const*)expr)->constvalue );
- const_string = (char *) textout((struct varlena *)const_string);
- break;
- default:
- elog(WARN,"unknown type %u ",exprType);
- }
-
- if (!exprType) {
- adt = makeConst(typeid(tp),
- (Size) 0,
- (Datum) NULL,
- true, /* isnull */
- false, /* was omitted */
- false, /* not a set */
- true /* is cast */);
- return ((Node*) adt);
- }
-
- cp = instr2 (tp, const_string, typlen);
-
-
- if (!tbyvalue(tp)) {
+
+ cp = instr2(tp, const_string, typlen);
+
+
+ if (!tbyvalue(tp))
+ {
/*
- if (len >= 0 && len != PSIZE(cp)) {
- char *pp;
- pp = (char *) palloc(len);
- memmove(pp, cp, len);
- cp = pp;
- }
+ if (len >= 0 && len != PSIZE(cp)) {
+ char *pp;
+ pp = (char *) palloc(len);
+ memmove(pp, cp, len);
+ cp = pp;
+ }
*/
- lcp = PointerGetDatum(cp);
- } else {
- switch(len) {
- case 1:
- lcp = Int8GetDatum(cp);
- break;
- case 2:
- lcp = Int16GetDatum(cp);
- break;
- case 4:
- lcp = Int32GetDatum(cp);
- break;
- default:
- lcp = PointerGetDatum(cp);
- break;
+ lcp = PointerGetDatum(cp);
+ }
+ else
+ {
+ switch (len)
+ {
+ case 1:
+ lcp = Int8GetDatum(cp);
+ break;
+ case 2:
+ lcp = Int16GetDatum(cp);
+ break;
+ case 4:
+ lcp = Int32GetDatum(cp);
+ break;
+ default:
+ lcp = PointerGetDatum(cp);
+ break;
+ }
}
- }
-
- adt = makeConst(typeid(tp),
- (Size)len,
- (Datum)lcp,
- false,
- false, /*was omitted*/
- false, /* not a set */
- true /* is cast */);
- /*
- printf("adt %s : %u %d %d\n",CString(expr),typeid(tp) ,
- len,cp);
- */
- if (string_palloced) pfree(const_string);
-
- return ((Node*) adt);
+
+ adt = makeConst(typeid(tp),
+ (Size) len,
+ (Datum) lcp,
+ false,
+ false, /* was omitted */
+ false, /* not a set */
+ true /* is cast */ );
+
+ /*
+ * printf("adt %s : %u %d %d\n",CString(expr),typeid(tp) , len,cp);
+ */
+ if (string_palloced)
+ pfree(const_string);
+
+ return ((Node *) adt);
}
-Aggreg *
-ParseAgg(char *aggname, Oid basetype, Node *target)
+Aggreg *
+ParseAgg(char *aggname, Oid basetype, Node * target)
{
- Oid fintype;
- Oid vartype;
- Oid xfn1;
- Form_pg_aggregate aggform;
- Aggreg *aggreg;
- HeapTuple theAggTuple;
-
- theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
- ObjectIdGetDatum(basetype),
- 0, 0);
- if (!HeapTupleIsValid(theAggTuple)) {
- elog(WARN, "aggregate %s does not exist", aggname);
- }
-
- aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
- fintype = aggform->aggfinaltype;
- xfn1 = aggform->aggtransfn1;
-
- if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
- elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
-
- /* only aggregates with transfn1 need a base type */
- if (OidIsValid(xfn1)) {
- basetype = aggform->aggbasetype;
- if (nodeTag(target) == T_Var)
- vartype = ((Var*)target)->vartype;
- else
- vartype = ((Expr*)target)->typeOid;
-
- if (basetype != vartype) {
- Type tp1, tp2;
-
- tp1 = get_id_type(basetype);
- tp2 = get_id_type(vartype);
- elog(NOTICE, "Aggregate type mismatch:");
- elog(WARN, "%s works on %s, not %s", aggname,
- tname(tp1), tname(tp2));
- }
- }
-
- aggreg = makeNode(Aggreg);
- aggreg->aggname = pstrdup(aggname);
- aggreg->basetype = aggform->aggbasetype;
- aggreg->aggtype = fintype;
-
- aggreg->target = target;
-
- return aggreg;
-}
+ Oid fintype;
+ Oid vartype;
+ Oid xfn1;
+ Form_pg_aggregate aggform;
+ Aggreg *aggreg;
+ HeapTuple theAggTuple;
+ theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
+ ObjectIdGetDatum(basetype),
+ 0, 0);
+ if (!HeapTupleIsValid(theAggTuple))
+ {
+ elog(WARN, "aggregate %s does not exist", aggname);
+ }
+
+ aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
+ fintype = aggform->aggfinaltype;
+ xfn1 = aggform->aggtransfn1;
+
+ if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
+ elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
+
+ /* only aggregates with transfn1 need a base type */
+ if (OidIsValid(xfn1))
+ {
+ basetype = aggform->aggbasetype;
+ if (nodeTag(target) == T_Var)
+ vartype = ((Var *) target)->vartype;
+ else
+ vartype = ((Expr *) target)->typeOid;
+
+ if (basetype != vartype)
+ {
+ Type tp1,
+ tp2;
+
+ tp1 = get_id_type(basetype);
+ tp2 = get_id_type(vartype);
+ elog(NOTICE, "Aggregate type mismatch:");
+ elog(WARN, "%s works on %s, not %s", aggname,
+ tname(tp1), tname(tp2));
+ }
+ }
+
+ aggreg = makeNode(Aggreg);
+ aggreg->aggname = pstrdup(aggname);
+ aggreg->basetype = aggform->aggbasetype;
+ aggreg->aggtype = fintype;
+
+ aggreg->target = target;
+
+ return aggreg;
+}