1515 * Portions Copyright (c) 1994, Regents of the University of California
1616 *
1717 * IDENTIFICATION
18- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.44 2001/10/25 05:49:33 momjian Exp $
18+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.45 2001/11/02 20:23:02 tgl Exp $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
2727#include "nodes/makefuncs.h"
2828#include "optimizer/prep.h"
2929#include "parser/parsetree.h"
30+ #include "parser/parse_coerce.h"
31+ #include "parser/parse_expr.h"
32+ #include "parser/parse_target.h"
33+ #include "utils/builtins.h"
3034#include "utils/lsyscache.h"
3135
3236
@@ -35,6 +39,7 @@ static List *expand_targetlist(List *tlist, int command_type,
3539static TargetEntry * process_matched_tle (TargetEntry * src_tle ,
3640TargetEntry * prior_tle ,
3741int attrno );
42+ static Node * build_column_default (Relation rel ,int attrno );
3843
3944
4045/*
@@ -168,6 +173,7 @@ expand_targetlist(List *tlist, int command_type,
168173{
169174new_tle = process_matched_tle (old_tle ,new_tle ,attrno );
170175tlistentry_used [old_tlist_index ]= true;
176+ /* keep scanning to detect multiple assignments to attr */
171177}
172178old_tlist_index ++ ;
173179}
@@ -177,97 +183,44 @@ expand_targetlist(List *tlist, int command_type,
177183/*
178184 * Didn't find a matching tlist entry, so make one.
179185 *
180- * For INSERT, generate a constant of the default value for the
181- * attribute type, or NULL if no default value.
186+ * For INSERT, generate an appropriate default value.
182187 *
183188 * For UPDATE, generate a Var reference to the existing value of
184189 * the attribute, so that it gets copied to the new tuple.
185190 */
186191Oid atttype = att_tup -> atttypid ;
187192int32 atttypmod = att_tup -> atttypmod ;
193+ Node * new_expr ;
188194
189195switch (command_type )
190196{
191197case CMD_INSERT :
192- {
193- bool hasdefault ;
194- Datum typedefault ;
195- int16 typlen ;
196- bool typbyval ;
197- Const * def_const ;
198-
199- if (att_tup -> attisset )
200- {
201- /*
202- * Set attributes are represented as OIDs no
203- * matter what the set element type is, and
204- * the element type's default is irrelevant
205- * too.
206- */
207- hasdefault = false;
208- typedefault = (Datum )0 ;
209- typlen = sizeof (Oid );
210- typbyval = true;
211- }
212- else
213- {
214- #ifdef _DROP_COLUMN_HACK__
215- if (COLUMN_IS_DROPPED (att_tup ))
216- {
217- hasdefault = false;
218- typedefault = (Datum )0 ;
219- }
220- else
221- #endif /* _DROP_COLUMN_HACK__ */
222- hasdefault = get_typdefault (atttype ,
223- & typedefault );
224-
225- get_typlenbyval (atttype ,& typlen ,& typbyval );
226- }
227-
228- def_const = makeConst (atttype ,
229- typlen ,
230- typedefault ,
231- !hasdefault ,
232- typbyval ,
233- false,/* not a set */
234- false);
235-
236- new_tle = makeTargetEntry (makeResdom (attrno ,
237- atttype ,
238- -1 ,
239- pstrdup (attrname ),
240- false),
241- (Node * )def_const );
242- break ;
243- }
198+ new_expr = build_column_default (rel ,attrno );
199+ break ;
244200case CMD_UPDATE :
245- {
246- Var * temp_var ;
247-
248201#ifdef _DROP_COLUMN_HACK__
249- if (COLUMN_IS_DROPPED (att_tup ))
250- temp_var = (Var * )makeNullConst (atttype );
251- else
202+ if (COLUMN_IS_DROPPED (att_tup ))
203+ new_expr = (Node * )makeNullConst (atttype );
204+ else
252205#endif /* _DROP_COLUMN_HACK__ */
253- temp_var = makeVar (result_relation ,
254- attrno ,
255- atttype ,
256- atttypmod ,
257- 0 );
258-
259- new_tle = makeTargetEntry (makeResdom (attrno ,
260- atttype ,
261- atttypmod ,
262- pstrdup (attrname ),
263- false),
264- (Node * )temp_var );
265- break ;
266- }
206+ new_expr = (Node * )makeVar (result_relation ,
207+ attrno ,
208+ atttype ,
209+ atttypmod ,
210+ 0 );
211+ break ;
267212default :
268213elog (ERROR ,"expand_targetlist: unexpected command_type" );
214+ new_expr = NULL ;/* keep compiler quiet */
269215break ;
270216}
217+
218+ new_tle = makeTargetEntry (makeResdom (attrno ,
219+ atttype ,
220+ atttypmod ,
221+ pstrdup (attrname ),
222+ false),
223+ new_expr );
271224}
272225
273226new_tlist = lappend (new_tlist ,new_tle );
@@ -385,3 +338,129 @@ process_matched_tle(TargetEntry *src_tle,
385338resdom -> resno = attrno ;
386339return makeTargetEntry (resdom , (Node * )newexpr );
387340}
341+
342+
343+ /*
344+ * Make an expression tree for the default value for a column.
345+ *
346+ * This is used to fill in missing attributes in an INSERT targetlist.
347+ * We look first to see if the column has a default value expression.
348+ * If not, generate a constant of the default value for the attribute type,
349+ * or a NULL if the type has no default value either.
350+ */
351+ static Node *
352+ build_column_default (Relation rel ,int attrno )
353+ {
354+ TupleDesc rd_att = rel -> rd_att ;
355+ Form_pg_attribute att_tup = rd_att -> attrs [attrno - 1 ];
356+ Oid atttype = att_tup -> atttypid ;
357+ int32 atttypmod = att_tup -> atttypmod ;
358+ bool hasdefault ;
359+ Datum typedefault ;
360+ int16 typlen ;
361+ bool typbyval ;
362+ Node * expr ;
363+
364+ /*
365+ * Scan to see if relation has a default for this column.
366+ */
367+ if (rd_att -> constr && rd_att -> constr -> num_defval > 0 )
368+ {
369+ AttrDefault * defval = rd_att -> constr -> defval ;
370+ int ndef = rd_att -> constr -> num_defval ;
371+
372+ while (-- ndef >=0 )
373+ {
374+ if (attrno == defval [ndef ].adnum )
375+ {
376+ Oid type_id ;
377+
378+ /*
379+ * Found it, convert string representation to node tree.
380+ */
381+ expr = stringToNode (defval [ndef ].adbin );
382+
383+ /*
384+ * Make sure the value is coerced to the target column type
385+ * (might not be right type yet if it's not a constant!)
386+ * This should match the parser's processing of non-defaulted
387+ * expressions --- see updateTargetListEntry().
388+ */
389+ type_id = exprType (expr );
390+
391+ if (type_id != atttype )
392+ {
393+ expr = CoerceTargetExpr (NULL ,expr ,type_id ,
394+ atttype ,atttypmod );
395+ /*
396+ * This really shouldn't fail; should have checked the
397+ * default's type when it was created ...
398+ */
399+ if (expr == NULL )
400+ elog (ERROR ,"Column \"%s\" is of type %s"
401+ " but default expression is of type %s"
402+ "\n\tYou will need to rewrite or cast the expression" ,
403+ NameStr (att_tup -> attname ),
404+ format_type_be (atttype ),
405+ format_type_be (type_id ));
406+ }
407+
408+ /*
409+ * If the column is a fixed-length type, it may need a
410+ * length coercion as well as a type coercion.
411+ */
412+ expr = coerce_type_typmod (NULL ,expr ,
413+ atttype ,atttypmod );
414+ return expr ;
415+ }
416+ }
417+ }
418+
419+ /*
420+ * No per-column default, so look for a default for the type itself.
421+ * If there isn't one, we generate a NULL constant of the correct type.
422+ */
423+ if (att_tup -> attisset )
424+ {
425+ /*
426+ * Set attributes are represented as OIDs no matter what the set
427+ * element type is, and the element type's default is irrelevant too.
428+ */
429+ hasdefault = false;
430+ typedefault = (Datum )0 ;
431+ typlen = sizeof (Oid );
432+ typbyval = true;
433+ }
434+ else
435+ {
436+ #ifdef _DROP_COLUMN_HACK__
437+ if (COLUMN_IS_DROPPED (att_tup ))
438+ {
439+ hasdefault = false;
440+ typedefault = (Datum )0 ;
441+ }
442+ else
443+ #endif /* _DROP_COLUMN_HACK__ */
444+ hasdefault = get_typdefault (atttype ,& typedefault );
445+
446+ get_typlenbyval (atttype ,& typlen ,& typbyval );
447+ }
448+
449+ expr = (Node * )makeConst (atttype ,
450+ typlen ,
451+ typedefault ,
452+ !hasdefault ,
453+ typbyval ,
454+ false,/* not a set */
455+ false);
456+
457+ /*
458+ * If the column is a fixed-length type, it may need a length coercion
459+ * as well as a type coercion. But NULLs don't need that.
460+ */
461+ if (hasdefault )
462+ expr = coerce_type_typmod (NULL ,expr ,
463+ atttype ,atttypmod );
464+
465+ return expr ;
466+ }