1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1996-12-07 05:38:11 +01:00
|
|
|
* parser.c--
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
1997-09-12 06:09:08 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.26 1997/09/12 04:08:01 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <pwd.h>
|
1997-09-07 07:04:48 +02:00
|
|
|
#include <sys/param.h> /* for MAXPATHLEN */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-10-31 12:09:44 +01:00
|
|
|
#include "postgres.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "parser/catalog_utils.h"
|
1996-11-08 21:46:33 +01:00
|
|
|
#include "parser/gramparse.h"
|
|
|
|
#include "parser/parse_query.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "nodes/pg_list.h"
|
1996-11-08 21:46:33 +01:00
|
|
|
#include "nodes/execnodes.h"
|
|
|
|
#include "nodes/makefuncs.h"
|
|
|
|
#include "nodes/primnodes.h"
|
|
|
|
#include "nodes/plannodes.h"
|
|
|
|
#include "nodes/relation.h"
|
|
|
|
#include "utils/builtins.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "utils/exc.h"
|
|
|
|
#include "utils/excid.h"
|
1996-11-08 21:46:33 +01:00
|
|
|
#include "utils/lsyscache.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "utils/palloc.h"
|
1996-11-06 07:52:23 +01:00
|
|
|
#include "utils/syscache.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "catalog/pg_aggregate.h"
|
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
#include "access/heapam.h"
|
1997-09-07 07:04:48 +02:00
|
|
|
#include "optimizer/clauses.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
void init_io(); /* from scan.l */
|
1997-09-08 23:56:23 +02:00
|
|
|
void parser_init(Oid *typev, int nargs); /* from gram.y */
|
1997-09-08 04:41:22 +02:00
|
|
|
int yyparse(); /* from gram.c */
|
1996-11-08 07:02:30 +01:00
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
char *parseString; /* the char* which holds the string to be
|
1997-09-07 07:04:48 +02:00
|
|
|
* parsed */
|
1997-09-08 04:41:22 +02:00
|
|
|
char *parseCh; /* a pointer used during parsing to walk
|
1997-09-07 07:04:48 +02:00
|
|
|
* down ParseString */
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
List *parsetree = NIL;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-08 07:02:30 +01:00
|
|
|
#ifdef SETS_FIXED
|
1997-09-08 04:41:22 +02:00
|
|
|
static void fixupsets();
|
|
|
|
static void define_sets();
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-11-10 03:27:15 +01:00
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* parser-- returns a list of parse trees
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
|
|
|
* CALLER is responsible for free'ing the list returned
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-08 04:41:22 +02:00
|
|
|
QueryTreeList *
|
1997-09-08 23:56:23 +02:00
|
|
|
parser(char *str, Oid *typev, int nargs)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
QueryTreeList *queryList;
|
|
|
|
int yyresult;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#if defined(FLEX_SCANNER)
|
1997-09-08 04:41:22 +02:00
|
|
|
extern void DeleteBuffer(void);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
#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();
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
#if defined(FLEX_SCANNER)
|
1997-09-07 07:04:48 +02:00
|
|
|
DeleteBuffer();
|
|
|
|
#endif /* FLEX_SCANNER */
|
|
|
|
|
|
|
|
clearerr(stdin);
|
|
|
|
|
|
|
|
if (yyresult)
|
|
|
|
{ /* error */
|
|
|
|
return ((QueryTreeList *) NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
queryList = parse_analyze(parsetree);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#ifdef SETS_FIXED
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
|
|
|
* 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));
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
return savetree;
|
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
return queryList;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1996-11-08 07:02:30 +01:00
|
|
|
#ifdef SETS_FIXED
|
1996-07-09 08:22:35 +02:00
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
fixupsets(Query *parse)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
if (parse == NULL)
|
|
|
|
return;
|
|
|
|
if (parse->commandType == CMD_UTILITY) /* utility */
|
|
|
|
return;
|
|
|
|
if (parse->commandType != CMD_INSERT)
|
|
|
|
return;
|
|
|
|
define_sets(parse);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Recursively find all of the Consts in the parsetree. Some of
|
|
|
|
* these may represent a set. The value of the Const will be the
|
1997-09-07 07:04:48 +02:00
|
|
|
* query (a string) which defines the set. Call SetDefine to define
|
1996-07-09 08:22:35 +02:00
|
|
|
* the set, and store the OID of the new set in the Const instead.
|
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
define_sets(Node *clause)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Oid setoid;
|
|
|
|
Type t = type("oid");
|
|
|
|
Oid typeoid = typeid(t);
|
|
|
|
Size oidsize = tlen(t);
|
|
|
|
bool oidbyval = tbyval(t);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
List *temp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/* mapcan */
|
|
|
|
foreach(temp, ((Expr *) clause)->args)
|
|
|
|
{
|
|
|
|
define_sets(lfirst(temp));
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else if (is_funcclause(clause))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
List *temp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/* mapcan */
|
|
|
|
foreach(temp, ((Expr *) clause)->args)
|
|
|
|
{
|
|
|
|
define_sets(lfirst(temp));
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
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));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-11-10 04:06:38 +01:00
|
|
|
#endif
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-08-03 04:28:10 +02:00
|
|
|
/* not used
|
1997-09-07 07:04:48 +02:00
|
|
|
#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
|
1997-08-03 04:28:10 +02:00
|
|
|
*/
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
Node *
|
1997-09-08 23:56:23 +02:00
|
|
|
parser_typecast(Value *expr, TypeName *typename, int typlen)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
/* check for passing non-ints */
|
1997-09-08 04:41:22 +02:00
|
|
|
Const *adt;
|
|
|
|
Datum lcp;
|
|
|
|
Type tp;
|
|
|
|
char type_string[16];
|
|
|
|
int32 len;
|
|
|
|
char *cp = NULL;
|
|
|
|
char *const_string = NULL;
|
|
|
|
bool string_palloced = false;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
switch (nodeTag(expr))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_String:
|
|
|
|
const_string = DatumGetPointer(expr->val.str);
|
|
|
|
break;
|
|
|
|
case T_Integer:
|
|
|
|
const_string = (char *) palloc(256);
|
|
|
|
string_palloced = true;
|
1997-09-12 06:09:08 +02:00
|
|
|
sprintf(const_string, "%ld", expr->val.ival);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elog(WARN,
|
|
|
|
"parser_typecast: cannot cast this expression to type \"%s\"",
|
|
|
|
typename->name);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
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)));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
#endif
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
cp = instr2(tp, const_string, typlen);
|
|
|
|
|
|
|
|
if (!tbyvalue(tp))
|
|
|
|
{
|
1997-08-03 04:28:10 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
if (len >= 0 && len != PSIZE(cp)) {
|
|
|
|
char *pp;
|
|
|
|
pp = (char *) palloc(len);
|
|
|
|
memmove(pp, cp, len);
|
|
|
|
cp = pp;
|
|
|
|
}
|
1997-08-03 04:28:10 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
lcp = PointerGetDatum(cp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (len)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case 1:
|
|
|
|
lcp = Int8GetDatum(cp);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
lcp = Int16GetDatum(cp);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
lcp = Int32GetDatum(cp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
lcp = PointerGetDatum(cp);
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
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;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
Node *
|
1997-09-08 23:56:23 +02:00
|
|
|
parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
/* check for passing non-ints */
|
1997-09-08 04:41:22 +02:00
|
|
|
Const *adt;
|
|
|
|
Datum lcp;
|
|
|
|
int32 len = tlen(tp);
|
|
|
|
char *cp = NULL;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
char *const_string = NULL;
|
|
|
|
bool string_palloced = false;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
Assert(IsA(expr, Const));
|
|
|
|
|
|
|
|
switch (exprType)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case 0: /* NULL */
|
|
|
|
break;
|
|
|
|
case INT4OID: /* int4 */
|
1997-09-07 07:04:48 +02:00
|
|
|
const_string = (char *) palloc(256);
|
|
|
|
string_palloced = true;
|
1997-09-08 04:41:22 +02:00
|
|
|
sprintf(const_string, "%d",
|
|
|
|
(int) ((Const *) expr)->constvalue);
|
1997-09-07 07:04:48 +02:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
case NAMEOID: /* char16 */
|
1997-09-07 07:04:48 +02:00
|
|
|
const_string = (char *) palloc(256);
|
|
|
|
string_palloced = true;
|
1997-09-08 04:41:22 +02:00
|
|
|
sprintf(const_string, "%s",
|
|
|
|
(char *) ((Const *) expr)->constvalue);
|
1997-09-07 07:04:48 +02:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
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;
|
1997-09-12 06:09:08 +02:00
|
|
|
sprintf(const_string, "%ld",
|
1997-09-08 04:41:22 +02:00
|
|
|
(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);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (!exprType)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
adt = makeConst(typeid(tp),
|
|
|
|
(Size) 0,
|
|
|
|
(Datum) NULL,
|
|
|
|
true, /* isnull */
|
|
|
|
false, /* was omitted */
|
|
|
|
false, /* not a set */
|
|
|
|
true /* is cast */ );
|
|
|
|
return ((Node *) adt);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
cp = instr2(tp, const_string, typlen);
|
|
|
|
|
|
|
|
|
|
|
|
if (!tbyvalue(tp))
|
|
|
|
{
|
1997-08-03 04:28:10 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
if (len >= 0 && len != PSIZE(cp)) {
|
|
|
|
char *pp;
|
|
|
|
pp = (char *) palloc(len);
|
|
|
|
memmove(pp, cp, len);
|
|
|
|
cp = pp;
|
|
|
|
}
|
1997-08-03 04:28:10 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
lcp = PointerGetDatum(cp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (len)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case 1:
|
|
|
|
lcp = Int8GetDatum(cp);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
lcp = Int16GetDatum(cp);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
lcp = Int32GetDatum(cp);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
lcp = PointerGetDatum(cp);
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
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);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
Aggreg *
|
1997-09-08 23:56:23 +02:00
|
|
|
ParseAgg(char *aggname, Oid basetype, Node *target)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Oid fintype;
|
|
|
|
Oid vartype;
|
|
|
|
Oid xfn1;
|
1997-09-07 07:04:48 +02:00
|
|
|
Form_pg_aggregate aggform;
|
1997-09-08 04:41:22 +02:00
|
|
|
Aggreg *aggreg;
|
|
|
|
HeapTuple theAggTuple;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
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)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Type tp1,
|
|
|
|
tp2;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|