1 /*-------------------------------------------------------------------------
5 * Copyright (c) 1994, Regents of the University of California
9 * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.18 1997/02/14 04:15:49 momjian Exp $
11 *-------------------------------------------------------------------------
16 #include <sys/param.h> /* for MAXPATHLEN */
19 #include "parser/catalog_utils.h"
20 #include "parser/gramparse.h"
21 #include "parser/parse_query.h"
22 #include "nodes/pg_list.h"
23 #include "nodes/execnodes.h"
24 #include "nodes/makefuncs.h"
25 #include "nodes/primnodes.h"
26 #include "nodes/plannodes.h"
27 #include "nodes/relation.h"
28 #include "utils/builtins.h"
29 #include "utils/exc.h"
30 #include "utils/excid.h"
31 #include "utils/lsyscache.h"
32 #include "utils/palloc.h"
33 #include "utils/syscache.h"
34 #include "catalog/pg_aggregate.h"
35 #include "catalog/pg_type.h"
36 #include "access/heapam.h"
37 #include "optimizer/clauses.h"
39 void init_io(); /* from scan.l */
40 void parser_init(Oid *typev, int nargs); /* from gram.y */
41 int yyparse(); /* from gram.c */
43 char *parseString; /* the char* which holds the string to be parsed */
44 char *parseCh; /* a pointer used during parsing to walk down ParseString*/
46 List *parsetree = NIL;
49 static void fixupsets();
50 static void define_sets();
53 * parser-- returns a list of parse trees
55 * CALLER is responsible for free'ing the list returned
58 parser(char *str, Oid *typev, int nargs)
60 QueryTreeList* queryList;
63 #if defined(FLEX_SCANNER)
64 extern void DeleteBuffer(void);
65 #endif /* FLEX_SCANNER */
69 /* Set things up to read from the string, if there is one */
70 parseString = (char *) palloc(strlen(str) + 1);
71 memmove(parseString,str,strlen(str)+1);
73 parser_init(typev, nargs);
76 #if defined(FLEX_SCANNER)
78 #endif /* FLEX_SCANNER */
82 if (yyresult) { /* error */
83 return((QueryTreeList*)NULL);
86 queryList = parse_analyze(parsetree);
89 /* Fixing up sets calls the parser, so it reassigns the global
90 * variable parsetree. So save the real parsetree.
93 foreach (parse, savetree) { /* savetree is really a list of parses */
95 /* find set definitions embedded in query */
96 fixupsets((Query *)lfirst(parse));
107 fixupsets(Query *parse)
111 if (parse->commandType==CMD_UTILITY) /* utility */
113 if (parse->commandType!=CMD_INSERT)
118 /* Recursively find all of the Consts in the parsetree. Some of
119 * these may represent a set. The value of the Const will be the
120 * query (a string) which defines the set. Call SetDefine to define
121 * the set, and store the OID of the new set in the Const instead.
124 define_sets(Node *clause)
127 Type t = type("oid");
128 Oid typeoid = typeid(t);
129 Size oidsize = tlen(t);
130 bool oidbyval = tbyval(t);
134 } else if (IsA(clause,LispList)) {
135 define_sets(lfirst(clause));
136 define_sets(lnext(clause));
137 } else if (IsA(clause,Const)) {
138 if (get_constisnull((Const)clause) ||
139 !get_constisset((Const)clause)) {
142 setoid = SetDefine(((Const*)clause)->constvalue,
143 get_id_typname(((Const*)clause)->consttype));
144 set_constvalue((Const)clause, setoid);
145 set_consttype((Const)clause,typeoid);
146 set_constlen((Const)clause,oidsize);
147 set_constbyval((Const)clause,oidbyval);
148 } else if ( IsA(clause,Iter) ) {
149 define_sets(((Iter*)clause)->iterexpr);
150 } else if (single_node (clause)) {
152 } else if (or_clause(clause)) {
155 foreach (temp, ((Expr*)clause)->args) {
156 define_sets(lfirst(temp));
158 } else if (is_funcclause (clause)) {
161 foreach(temp, ((Expr*)clause)->args) {
162 define_sets(lfirst(temp));
164 } else if (IsA(clause,ArrayRef)) {
165 define_sets(((ArrayRef*)clause)->refassgnexpr);
166 } else if (not_clause (clause)) {
167 define_sets (get_notclausearg (clause));
168 } else if (is_opclause (clause)) {
169 define_sets(get_leftop (clause));
170 define_sets(get_rightop (clause));
175 #define PSIZE(PTR) (*((int32 *)(PTR) - 1))
177 parser_typecast(Value *expr, TypeName *typename, int typlen)
179 /* check for passing non-ints */
183 char type_string[16];
186 char *const_string = NULL;
187 bool string_palloced = false;
189 switch(nodeTag(expr)) {
191 const_string = DatumGetPointer(expr->val.str);
194 const_string = (char *) palloc(256);
195 string_palloced = true;
196 sprintf(const_string, "%ld", expr->val.ival);
200 "parser_typecast: cannot cast this expression to type \"%s\"",
204 if (typename->arrayBounds != NIL) {
205 sprintf(type_string,"_%s", typename->name);
206 tp = (Type) type(type_string);
208 tp = (Type) type(typename->name);
214 switch ( CInteger(lfirst(expr)) ) {
215 case INT4OID: /* int4 */
216 const_string = (char *) palloc(256);
217 string_palloced = true;
218 sprintf(const_string,"%d", ((Const*)lnext(expr))->constvalue);
221 case NAMEOID: /* char16 */
222 const_string = (char *) palloc(256);
223 string_palloced = true;
224 sprintf(const_string,"%s", ((Const*)lnext(expr))->constvalue);
227 case CHAROID: /* char */
228 const_string = (char *) palloc(256);
229 string_palloced = true;
230 sprintf(const_string,"%c", ((Const)lnext(expr))->constvalue);
233 case FLOAT8OID:/* float8 */
234 const_string = (char *) palloc(256);
235 string_palloced = true;
236 sprintf(const_string,"%f", ((Const)lnext(expr))->constvalue);
239 case TEXTOID: /* text */
240 const_string = DatumGetPointer(((Const)lnext(expr))->constvalue);
241 const_string = (char *) textout((struct varlena *)const_string);
244 case UNKNOWNOID: /* unknown */
245 const_string = DatumGetPointer(((Const)lnext(expr))->constvalue);
246 const_string = (char *) textout((struct varlena *)const_string);
250 elog(WARN,"unknown type %d", CInteger(lfirst(expr)));
254 cp = instr2 (tp, const_string, typlen);
257 if (len >= 0 && len != PSIZE(cp)) {
259 pp = (char *) palloc(len);
260 memmove(pp, cp, len);
263 lcp = PointerGetDatum(cp);
267 lcp = Int8GetDatum(cp);
270 lcp = Int16GetDatum(cp);
273 lcp = Int32GetDatum(cp);
276 lcp = PointerGetDatum(cp);
281 adt = makeConst(typeid(tp),
286 false, /* not a set */
296 parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
298 /* check for passing non-ints */
301 int32 len = tlen(tp);
304 char *const_string = NULL;
305 bool string_palloced = false;
307 Assert(IsA(expr,Const));
312 case INT4OID: /* int4 */
313 const_string = (char *) palloc(256);
314 string_palloced = true;
315 sprintf(const_string,"%d",
316 (int) ((Const*)expr)->constvalue);
318 case NAMEOID: /* char16 */
319 const_string = (char *) palloc(256);
320 string_palloced = true;
321 sprintf(const_string,"%s",
322 (char*) ((Const*)expr)->constvalue);
324 case CHAROID: /* char */
325 const_string = (char *) palloc(256);
326 string_palloced = true;
327 sprintf(const_string,"%c",
328 (char) ((Const*)expr)->constvalue);
330 case FLOAT4OID: /* float4 */
333 DatumGetFloat32(((Const*)expr)->constvalue);
334 const_string = (char *) palloc(256);
335 string_palloced = true;
336 sprintf(const_string,"%f", *floatVal);
339 case FLOAT8OID:/* float8 */
342 DatumGetFloat64(((Const*)expr)->constvalue);
343 const_string = (char *) palloc(256);
344 string_palloced = true;
345 sprintf(const_string,"%f", *floatVal);
348 case TEXTOID: /* text */
350 DatumGetPointer(((Const*)expr)->constvalue );
351 const_string = (char *) textout((struct varlena *)const_string);
353 case UNKNOWNOID: /* unknown */
355 DatumGetPointer(((Const*)expr)->constvalue );
356 const_string = (char *) textout((struct varlena *)const_string);
359 elog(WARN,"unknown type %u ",exprType);
363 adt = makeConst(typeid(tp),
367 false, /* was omitted */
368 false, /* not a set */
370 return ((Node*) adt);
373 cp = instr2 (tp, const_string, typlen);
377 if (len >= 0 && len != PSIZE(cp)) {
379 pp = (char *) palloc(len);
380 memmove(pp, cp, len);
383 lcp = PointerGetDatum(cp);
387 lcp = Int8GetDatum(cp);
390 lcp = Int16GetDatum(cp);
393 lcp = Int32GetDatum(cp);
396 lcp = PointerGetDatum(cp);
401 adt = makeConst(typeid(tp),
405 false, /*was omitted*/
406 false, /* not a set */
409 printf("adt %s : %u %d %d\n",CString(expr),typeid(tp) ,
412 if (string_palloced) pfree(const_string);
414 return ((Node*) adt);
418 ParseAgg(char *aggname, Oid basetype, Node *target)
423 Form_pg_aggregate aggform;
425 HeapTuple theAggTuple;
427 theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
428 ObjectIdGetDatum(basetype),
430 if (!HeapTupleIsValid(theAggTuple)) {
431 elog(WARN, "aggregate %s does not exist", aggname);
434 aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
435 fintype = aggform->aggfinaltype;
436 xfn1 = aggform->aggtransfn1;
438 if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
439 elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
441 /* only aggregates with transfn1 need a base type */
442 if (OidIsValid(xfn1)) {
443 basetype = aggform->aggbasetype;
444 if (nodeTag(target) == T_Var)
445 vartype = ((Var*)target)->vartype;
447 vartype = ((Expr*)target)->typeOid;
449 if (basetype != vartype) {
450 Type tp1, tp2, get_id_type();
452 tp1 = get_id_type(basetype);
453 tp2 = get_id_type(vartype);
454 elog(NOTICE, "Aggregate type mismatch:");
455 elog(WARN, "%s works on %s, not %s", aggname,
456 tname(tp1), tname(tp2));
460 aggreg = makeNode(Aggreg);
461 aggreg->aggname = pstrdup(aggname);
462 aggreg->basetype = aggform->aggbasetype;
463 aggreg->aggtype = fintype;
465 aggreg->target = target;