7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.44 1997/09/18 20:20:58 momjian Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.45 1997/10/12 07:09:20 vadim Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -303,6 +303,7 @@ static Query *
303
303
transformInsertStmt (ParseState * pstate , AppendStmt * stmt )
304
304
{
305
305
Query * qry = makeNode (Query ); /* make a new query tree */
306
+ List * icolumns ;
306
307
307
308
qry -> commandType = CMD_INSERT ;
308
309
pstate -> p_is_insert = true;
@@ -313,10 +314,74 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
313
314
qry -> uniqueFlag = NULL ;
314
315
315
316
/* fix the target list */
316
- pstate -> p_insert_columns = makeTargetNames (pstate , stmt -> cols );
317
-
317
+ icolumns = pstate -> p_insert_columns = makeTargetNames (pstate , stmt -> cols );
318
+
318
319
qry -> targetList = transformTargetList (pstate , stmt -> targetList );
319
-
320
+
321
+ /* DEFAULT handling */
322
+ if (length (qry -> targetList ) < pstate -> p_target_relation -> rd_att -> natts &&
323
+ pstate -> p_target_relation -> rd_att -> constr &&
324
+ pstate -> p_target_relation -> rd_att -> constr -> num_defval > 0 )
325
+ {
326
+ AttributeTupleForm * att = pstate -> p_target_relation -> rd_att -> attrs ;
327
+ AttrDefault * defval = pstate -> p_target_relation -> rd_att -> constr -> defval ;
328
+ int ndef = pstate -> p_target_relation -> rd_att -> constr -> num_defval ;
329
+
330
+ /*
331
+ * if stmt->cols == NIL then makeTargetNames returns list of all
332
+ * attrs: have to shorter icolumns list...
333
+ */
334
+ if (stmt -> cols == NIL )
335
+ {
336
+ List * extrl ;
337
+ int i = length (qry -> targetList );
338
+
339
+ foreach (extrl , icolumns )
340
+ {
341
+ if (-- i <= 0 )
342
+ break ;
343
+ }
344
+ freeList (lnext (extrl ));
345
+ lnext (extrl ) = NIL ;
346
+ }
347
+
348
+ while (ndef -- > 0 )
349
+ {
350
+ List * tl ;
351
+ Ident * id ;
352
+ TargetEntry * te ;
353
+
354
+ foreach (tl , icolumns )
355
+ {
356
+ id = (Ident * ) lfirst (tl );
357
+ if (!namestrcmp (& (att [defval [ndef ].adnum - 1 ]-> attname ), id -> name ))
358
+ break ;
359
+ }
360
+ if (tl != NIL ) /* something given for this attr */
361
+ continue ;
362
+ /*
363
+ * Nothing given for this attr with DEFAULT expr, so
364
+ * add new TargetEntry to qry->targetList.
365
+ * Note, that we set resno to defval[ndef].adnum:
366
+ * it's what transformTargetList()->make_targetlist_expr()
367
+ * does for INSERT ... SELECT. But for INSERT ... VALUES
368
+ * pstate->p_last_resno is used. It doesn't matter for
369
+ * "normal" using (planner creates proper target list
370
+ * in preptlist.c), but may break RULEs in some way.
371
+ * It seems better to create proper target list here...
372
+ */
373
+ te = makeNode (TargetEntry );
374
+ te -> resdom = makeResdom (defval [ndef ].adnum ,
375
+ att [defval [ndef ].adnum - 1 ]-> atttypid ,
376
+ att [defval [ndef ].adnum - 1 ]-> attlen ,
377
+ pstrdup (nameout (& (att [defval [ndef ].adnum - 1 ]-> attname ))),
378
+ 0 , 0 , 0 );
379
+ te -> fjoin = NULL ;
380
+ te -> expr = (Node * ) stringToNode (defval [ndef ].adbin );
381
+ qry -> targetList = lappend (qry -> targetList , te );
382
+ }
383
+ }
384
+
320
385
/* fix where clause */
321
386
qry -> qual = transformWhereClause (pstate , stmt -> whereClause );
322
387
@@ -1098,10 +1163,20 @@ makeTargetNames(ParseState *pstate, List *cols)
1098
1163
}
1099
1164
}
1100
1165
else
1166
+ {
1101
1167
foreach (tl , cols )
1102
- /* elog on failure */
1103
- varattno (pstate -> p_target_relation , ((Ident * ) lfirst (tl ))-> name );
1104
-
1168
+ {
1169
+ List * nxt ;
1170
+ char * name = ((Ident * ) lfirst (tl ))-> name ;
1171
+
1172
+ /* elog on failure */
1173
+ varattno (pstate -> p_target_relation , name );
1174
+ foreach (nxt , lnext (tl ))
1175
+ if (!strcmp (name , ((Ident * ) lfirst (nxt ))-> name ))
1176
+ elog (WARN , "Attribute %s should be specified only once" , name );
1177
+ }
1178
+ }
1179
+
1105
1180
return cols ;
1106
1181
}
1107
1182
0 commit comments