Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9685afb

Browse files
committed
Add default expressions to INSERTs during planning, not during parse
analysis. This keeps stored rules from prematurely absorbing defaultinformation, which is necessary for ALTER TABLE SET DEFAULT to workunsurprisingly with rules. See pgsql-bugs discussion 24-Oct-01.
1 parenta9b6691 commit9685afb

File tree

3 files changed

+161
-135
lines changed

3 files changed

+161
-135
lines changed

‎src/backend/catalog/heap.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.179 2001/10/25 05:49:22 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.180 2001/11/02 20:23:02 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1651,9 +1651,9 @@ AddRelationRawConstraints(Relation rel,
16511651
* column's type. We store the expression without coercion,
16521652
* however, to avoid premature coercion in cases like
16531653
*
1654-
* CREATE TABLE tbl (fld datetime DEFAULT 'now');
1654+
* CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
16551655
*
1656-
* NB: this should match the code inupdateTargetListEntry() that
1656+
* NB: this should match the code inoptimizer/prep/preptlist.c that
16571657
* will actually do the coercion, to ensure we don't accept an
16581658
* unusable default expression.
16591659
*/

‎src/backend/optimizer/prep/preptlist.c

Lines changed: 154 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
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
*/
@@ -27,6 +27,10 @@
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,
3539
staticTargetEntry*process_matched_tle(TargetEntry*src_tle,
3640
TargetEntry*prior_tle,
3741
intattrno);
42+
staticNode*build_column_default(Relationrel,intattrno);
3843

3944

4045
/*
@@ -168,6 +173,7 @@ expand_targetlist(List *tlist, int command_type,
168173
{
169174
new_tle=process_matched_tle(old_tle,new_tle,attrno);
170175
tlistentry_used[old_tlist_index]= true;
176+
/* keep scanning to detect multiple assignments to attr */
171177
}
172178
old_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
*/
186191
Oidatttype=att_tup->atttypid;
187192
int32atttypmod=att_tup->atttypmod;
193+
Node*new_expr;
188194

189195
switch (command_type)
190196
{
191197
caseCMD_INSERT:
192-
{
193-
boolhasdefault;
194-
Datumtypedefault;
195-
int16typlen;
196-
booltypbyval;
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;
244200
caseCMD_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;
267212
default:
268213
elog(ERROR,"expand_targetlist: unexpected command_type");
214+
new_expr=NULL;/* keep compiler quiet */
269215
break;
270216
}
217+
218+
new_tle=makeTargetEntry(makeResdom(attrno,
219+
atttype,
220+
atttypmod,
221+
pstrdup(attrname),
222+
false),
223+
new_expr);
271224
}
272225

273226
new_tlist=lappend(new_tlist,new_tle);
@@ -385,3 +338,129 @@ process_matched_tle(TargetEntry *src_tle,
385338
resdom->resno=attrno;
386339
returnmakeTargetEntry(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+
staticNode*
352+
build_column_default(Relationrel,intattrno)
353+
{
354+
TupleDescrd_att=rel->rd_att;
355+
Form_pg_attributeatt_tup=rd_att->attrs[attrno-1];
356+
Oidatttype=att_tup->atttypid;
357+
int32atttypmod=att_tup->atttypmod;
358+
boolhasdefault;
359+
Datumtypedefault;
360+
int16typlen;
361+
booltypbyval;
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+
intndef=rd_att->constr->num_defval;
371+
372+
while (--ndef >=0)
373+
{
374+
if (attrno==defval[ndef].adnum)
375+
{
376+
Oidtype_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+
returnexpr;
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+
returnexpr;
466+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp