]> granicus.if.org Git - postgresql/blob - src/backend/parser/parser.c
Remove WIN32 defines. They never worked.
[postgresql] / src / backend / parser / parser.c
1 /*-------------------------------------------------------------------------
2  *
3  * parser.c--
4  *
5  * Copyright (c) 1994, Regents of the University of California
6  *
7  *
8  * IDENTIFICATION
9  *    $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.18 1997/02/14 04:15:49 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13 #include <string.h>
14 #include <stdio.h>
15 #include <pwd.h>
16 #include <sys/param.h>          /* for MAXPATHLEN */
17
18 #include "postgres.h"
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" 
38
39 void init_io(); /* from scan.l */
40 void parser_init(Oid *typev, int nargs); /* from gram.y */
41 int yyparse(); /* from gram.c */
42
43 char *parseString; /* the char* which holds the string to be parsed */
44 char *parseCh;     /* a pointer used during parsing to walk down ParseString*/
45
46 List *parsetree = NIL;
47
48 #ifdef SETS_FIXED
49 static void fixupsets();
50 static void define_sets();
51 #endif
52 /*
53  * parser-- returns a list of parse trees
54  * 
55  *  CALLER is responsible for free'ing the list returned 
56  */
57 QueryTreeList *
58 parser(char *str, Oid *typev, int nargs)
59 {
60     QueryTreeList* queryList;
61     int yyresult;
62
63 #if defined(FLEX_SCANNER)
64     extern void DeleteBuffer(void);
65 #endif  /* FLEX_SCANNER */
66     
67     init_io();
68     
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);
72     
73     parser_init(typev, nargs);
74     yyresult = yyparse();
75
76 #if defined(FLEX_SCANNER)
77     DeleteBuffer();
78 #endif  /* FLEX_SCANNER */
79     
80     clearerr(stdin);
81     
82     if (yyresult) {     /* error */
83         return((QueryTreeList*)NULL);
84     }
85
86     queryList = parse_analyze(parsetree);
87     
88 #ifdef SETS_FIXED
89     /* Fixing up sets calls the parser, so it reassigns the global
90      * variable parsetree. So save the real parsetree.
91      */
92     savetree = parsetree;
93     foreach (parse, savetree) {  /* savetree is really a list of parses */
94
95         /* find set definitions embedded in query */
96         fixupsets((Query *)lfirst(parse));  
97
98     }
99     return savetree;
100 #endif    
101
102     return queryList;
103 }
104
105 #ifdef SETS_FIXED
106 static void
107 fixupsets(Query *parse)
108 {
109     if (parse == NULL)
110         return;
111     if (parse->commandType==CMD_UTILITY)  /* utility */
112         return;
113     if (parse->commandType!=CMD_INSERT)
114         return;
115     define_sets(parse);
116 }
117
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.
122  */
123 static void
124 define_sets(Node *clause)
125 {
126     Oid setoid;
127     Type t = type("oid");
128     Oid typeoid = typeid(t);
129     Size oidsize = tlen(t);
130     bool oidbyval = tbyval(t);
131     
132     if (clause==NULL) {
133         return;
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)) {
140             return;
141         }
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)) {
151         return;
152     } else if (or_clause(clause)) {
153         List *temp;
154         /* mapcan */
155         foreach (temp, ((Expr*)clause)->args) {
156             define_sets(lfirst(temp));
157         }
158     } else if (is_funcclause (clause)) {
159         List *temp;
160         /* mapcan */
161         foreach(temp, ((Expr*)clause)->args) {
162             define_sets(lfirst(temp));
163         }
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));
171     }
172 }
173 #endif
174
175 #define    PSIZE(PTR)      (*((int32 *)(PTR) - 1))
176 Node *
177 parser_typecast(Value *expr, TypeName *typename, int typlen)
178 {
179     /* check for passing non-ints */
180     Const *adt;
181     Datum lcp;
182     Type tp;
183     char type_string[16];
184     int32 len;
185     char *cp = NULL;
186     char *const_string = NULL; 
187     bool string_palloced = false;
188
189     switch(nodeTag(expr)) {
190     case T_String:
191         const_string = DatumGetPointer(expr->val.str);
192         break;
193     case T_Integer:
194         const_string = (char *) palloc(256);
195         string_palloced = true;
196         sprintf(const_string, "%ld", expr->val.ival);
197         break;
198     default:
199         elog(WARN,
200              "parser_typecast: cannot cast this expression to type \"%s\"",
201              typename->name);
202     }
203
204     if (typename->arrayBounds != NIL) {
205         sprintf(type_string,"_%s", typename->name);
206         tp = (Type) type(type_string);
207     } else {
208         tp = (Type) type(typename->name);
209     }
210     
211     len = tlen(tp);
212     
213 #if 0 /* fix me */
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);
219         break;
220         
221     case NAMEOID: /* char16 */
222         const_string = (char *) palloc(256);
223         string_palloced = true;
224         sprintf(const_string,"%s", ((Const*)lnext(expr))->constvalue);
225         break;
226         
227     case CHAROID: /* char */
228         const_string = (char *) palloc(256);
229         string_palloced = true;
230         sprintf(const_string,"%c", ((Const)lnext(expr))->constvalue);
231         break;
232         
233     case FLOAT8OID:/* float8 */
234         const_string = (char *) palloc(256);
235         string_palloced = true;
236         sprintf(const_string,"%f", ((Const)lnext(expr))->constvalue);
237         break;
238         
239     case TEXTOID: /* text */
240         const_string = DatumGetPointer(((Const)lnext(expr))->constvalue);
241         const_string = (char *) textout((struct varlena *)const_string);
242         break;
243         
244     case UNKNOWNOID: /* unknown */
245         const_string = DatumGetPointer(((Const)lnext(expr))->constvalue);
246         const_string = (char *) textout((struct varlena *)const_string);
247         break;
248         
249     default:
250         elog(WARN,"unknown type %d", CInteger(lfirst(expr)));
251     }
252 #endif
253
254     cp = instr2 (tp, const_string, typlen);
255     
256     if (!tbyvalue(tp)) {
257         if (len >= 0 && len != PSIZE(cp)) {
258             char *pp;
259             pp = (char *) palloc(len);
260             memmove(pp, cp, len);
261             cp = pp;
262         }
263         lcp = PointerGetDatum(cp);
264     } else {
265         switch(len) {
266         case 1:
267             lcp = Int8GetDatum(cp);
268             break;
269         case 2:
270             lcp = Int16GetDatum(cp);
271             break;
272         case 4:
273             lcp = Int32GetDatum(cp);
274             break;
275         default:
276             lcp = PointerGetDatum(cp);
277             break;
278         }
279     }
280     
281     adt = makeConst(typeid(tp),
282                     len,
283                     (Datum)lcp ,
284                     false,
285                     tbyvalue(tp), 
286                     false, /* not a set */
287                     true /* is cast */);
288     
289     if (string_palloced)
290         pfree(const_string);
291     
292     return (Node*)adt;
293 }
294
295 Node *
296 parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
297 {
298     /* check for passing non-ints */
299     Const *adt;
300     Datum lcp;
301     int32 len = tlen(tp);
302     char *cp = NULL;
303     
304     char *const_string = NULL; 
305     bool string_palloced = false;
306
307     Assert(IsA(expr,Const));
308     
309     switch (exprType) {
310       case 0: /* NULL */
311         break;
312     case INT4OID: /* int4 */
313         const_string = (char *) palloc(256);
314         string_palloced = true;
315         sprintf(const_string,"%d",
316                 (int) ((Const*)expr)->constvalue);
317         break;
318     case NAMEOID: /* char16 */
319         const_string = (char *) palloc(256);
320         string_palloced = true;
321         sprintf(const_string,"%s",
322                 (char*) ((Const*)expr)->constvalue);
323         break;
324     case CHAROID: /* char */
325         const_string = (char *) palloc(256);
326         string_palloced = true;
327         sprintf(const_string,"%c",
328                 (char) ((Const*)expr)->constvalue);
329         break;
330     case FLOAT4OID:     /* float4 */
331         {
332             float32 floatVal = 
333                 DatumGetFloat32(((Const*)expr)->constvalue);
334             const_string = (char *) palloc(256);
335             string_palloced = true;
336             sprintf(const_string,"%f", *floatVal);
337             break;
338         }
339     case FLOAT8OID:/* float8 */
340         {
341             float64 floatVal = 
342                 DatumGetFloat64(((Const*)expr)->constvalue);
343             const_string = (char *) palloc(256);
344             string_palloced = true;
345             sprintf(const_string,"%f", *floatVal);
346             break;
347         }
348     case TEXTOID: /* text */
349         const_string = 
350             DatumGetPointer(((Const*)expr)->constvalue );
351         const_string = (char *) textout((struct varlena *)const_string);
352         break;
353     case UNKNOWNOID: /* unknown */
354         const_string =
355             DatumGetPointer(((Const*)expr)->constvalue );
356         const_string = (char *) textout((struct varlena *)const_string);
357         break;
358     default:
359         elog(WARN,"unknown type %u ",exprType);
360     }
361     
362     if (!exprType) {
363         adt = makeConst(typeid(tp),
364                         (Size) 0,
365                         (Datum) NULL,
366                         true,   /* isnull */
367                         false,  /* was omitted */
368                         false,  /* not a set */
369                         true    /* is cast */);
370         return ((Node*) adt);
371     }
372
373     cp = instr2 (tp, const_string, typlen);
374     
375     
376     if (!tbyvalue(tp)) {
377         if (len >= 0 && len != PSIZE(cp)) {
378             char *pp;
379             pp = (char *) palloc(len);
380             memmove(pp, cp, len);
381             cp = pp;
382         }
383         lcp = PointerGetDatum(cp);
384     } else {
385         switch(len) {
386         case 1:
387             lcp = Int8GetDatum(cp);
388             break;
389         case 2:
390             lcp = Int16GetDatum(cp);
391             break;
392         case 4:
393             lcp = Int32GetDatum(cp);
394             break;
395         default:
396             lcp = PointerGetDatum(cp);
397             break;
398         }
399     }
400     
401     adt = makeConst(typeid(tp),
402                     (Size)len,
403                     (Datum)lcp,
404                     false, 
405                     false, /*was omitted*/
406                     false, /* not a set */
407                     true   /* is cast */);
408     /*
409       printf("adt %s : %u %d %d\n",CString(expr),typeid(tp) ,
410       len,cp);
411       */
412     if (string_palloced) pfree(const_string);
413
414     return ((Node*) adt);
415 }
416
417 Aggreg *
418 ParseAgg(char *aggname, Oid basetype, Node *target)
419 {
420     Oid fintype;
421     Oid vartype;
422     Oid xfn1;
423     Form_pg_aggregate aggform;
424     Aggreg *aggreg;
425     HeapTuple theAggTuple;
426     
427     theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
428                                       ObjectIdGetDatum(basetype), 
429                                       0, 0); 
430     if (!HeapTupleIsValid(theAggTuple)) {
431         elog(WARN, "aggregate %s does not exist", aggname);
432     }
433     
434     aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
435     fintype = aggform->aggfinaltype;
436     xfn1 = aggform->aggtransfn1;
437     
438     if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
439         elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
440
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;
446         else
447             vartype = ((Expr*)target)->typeOid;
448
449         if (basetype != vartype) {
450             Type tp1, tp2, get_id_type();
451             
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));
457         }
458     }
459
460     aggreg = makeNode(Aggreg);
461     aggreg->aggname = pstrdup(aggname);
462     aggreg->basetype = aggform->aggbasetype;
463     aggreg->aggtype = fintype;
464
465     aggreg->target = target;
466
467     return aggreg;
468 }
469