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

Commitae93e5f

Browse files
committed
Make the world very nearly safe for composite-type columns in tables.
1. Solve the problem of not having TOAST references hiding inside compositevalues by establishing the rule that toasting only goes one level deep:a tuple can contain toasted fields, but a composite-type datum that isto be inserted into a tuple cannot. Enforcing this in heap_formtupleis relatively cheap and it avoids a large increase in the cost of runningthe tuptoaster during final storage of a row.2. Fix some interesting problems in expansion of inherited queries thatreference whole-row variables. We never really did this correctly before,but it's now relatively painless to solve by expanding the parent'swhole-row Var into a RowExpr() selecting the proper columns from thechild.If you dike out the preventive check in CheckAttributeType(),composite-type columns now seem to actually work. However, we surelycannot ship them like this --- without I/O for composite types, youcan't get pg_dump to dump tables containing them. So a little morework still to do.
1 parent8f2ea8b commitae93e5f

File tree

12 files changed

+376
-67
lines changed

12 files changed

+376
-67
lines changed

‎src/backend/access/common/heaptuple.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.91 2004/06/04 20:35:21 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.92 2004/06/05 01:55:04 tgl Exp $
1313
*
1414
* NOTES
1515
* The old interface functions have been converted to macros
@@ -21,6 +21,7 @@
2121
#include"postgres.h"
2222

2323
#include"access/heapam.h"
24+
#include"access/tuptoaster.h"
2425
#include"catalog/pg_type.h"
2526

2627

@@ -567,8 +568,9 @@ heap_formtuple(TupleDesc tupleDescriptor,
567568
unsigned longlen;
568569
inthoff;
569570
boolhasnull= false;
570-
inti;
571+
Form_pg_attribute*att=tupleDescriptor->attrs;
571572
intnumberOfAttributes=tupleDescriptor->natts;
573+
inti;
572574

573575
if (numberOfAttributes>MaxTupleAttributeNumber)
574576
ereport(ERROR,
@@ -577,17 +579,34 @@ heap_formtuple(TupleDesc tupleDescriptor,
577579
numberOfAttributes,MaxTupleAttributeNumber)));
578580

579581
/*
580-
* Determine total space needed
582+
* Check for nulls and embedded tuples; expand any toasted attributes
583+
* in embedded tuples. This preserves the invariant that toasting can
584+
* only go one level deep.
585+
*
586+
* We can skip calling toast_flatten_tuple_attribute() if the attribute
587+
* couldn't possibly be of composite type. All composite datums are
588+
* varlena and have alignment 'd'; furthermore they aren't arrays.
589+
* Also, if an attribute is already toasted, it must have been sent to
590+
* disk already and so cannot contain toasted attributes.
581591
*/
582592
for (i=0;i<numberOfAttributes;i++)
583593
{
584594
if (nulls[i]!=' ')
585-
{
586595
hasnull= true;
587-
break;
596+
elseif (att[i]->attlen==-1&&
597+
att[i]->attalign=='d'&&
598+
att[i]->attndims==0&&
599+
!VARATT_IS_EXTENDED(values[i]))
600+
{
601+
values[i]=toast_flatten_tuple_attribute(values[i],
602+
att[i]->atttypid,
603+
att[i]->atttypmod);
588604
}
589605
}
590606

607+
/*
608+
* Determine total space needed
609+
*/
591610
len= offsetof(HeapTupleHeaderData,t_bits);
592611

593612
if (hasnull)
@@ -744,7 +763,11 @@ heap_deformtuple(HeapTuple tuple,
744763
boolslow= false;/* can we use/set attcacheoff? */
745764

746765
natts=tup->t_natts;
747-
/* This min() operation is pure paranoia */
766+
/*
767+
* In inheritance situations, it is possible that the given tuple actually
768+
* has more fields than the caller is expecting. Don't run off the end
769+
* of the caller's arrays.
770+
*/
748771
natts=Min(natts,tdesc_natts);
749772

750773
tp= (char*)tup+tup->t_hoff;

‎src/backend/access/heap/tuptoaster.c

Lines changed: 128 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.42 2004/06/04 20:35:21 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.43 2004/06/05 01:55:04 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -35,6 +35,7 @@
3535
#include"utils/builtins.h"
3636
#include"utils/fmgroids.h"
3737
#include"utils/pg_lzcompress.h"
38+
#include"utils/typcache.h"
3839

3940

4041
#undef TOAST_DEBUG
@@ -458,10 +459,10 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
458459
* still in the tuple must be someone else's we cannot reuse.
459460
* Expand it to plain (and, probably, toast it again below).
460461
*/
461-
if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i])))
462+
if (VARATT_IS_EXTERNAL(new_value))
462463
{
463-
toast_values[i]=PointerGetDatum(heap_tuple_untoast_attr(
464-
(varattrib*)DatumGetPointer(toast_values[i])));
464+
new_value=heap_tuple_untoast_attr(new_value);
465+
toast_values[i]=PointerGetDatum(new_value);
465466
toast_free[i]= true;
466467
need_change= true;
467468
need_free= true;
@@ -470,7 +471,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
470471
/*
471472
* Remember the size of this attribute
472473
*/
473-
toast_sizes[i]=VARATT_SIZE(DatumGetPointer(toast_values[i]));
474+
toast_sizes[i]=VARATT_SIZE(new_value);
474475
}
475476
else
476477
{
@@ -785,6 +786,128 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
785786
}
786787

787788

789+
/* ----------
790+
* toast_flatten_tuple_attribute -
791+
*
792+
*If a Datum is of composite type, "flatten" it to contain no toasted fields.
793+
*This must be invoked on any potentially-composite field that is to be
794+
*inserted into a tuple. Doing this preserves the invariant that toasting
795+
*goes only one level deep in a tuple.
796+
* ----------
797+
*/
798+
Datum
799+
toast_flatten_tuple_attribute(Datumvalue,
800+
OidtypeId,int32typeMod)
801+
{
802+
TupleDesctupleDesc;
803+
HeapTupleHeaderolddata;
804+
HeapTupleHeadernew_data;
805+
int32new_len;
806+
HeapTupleDatatmptup;
807+
Form_pg_attribute*att;
808+
intnumAttrs;
809+
inti;
810+
boolneed_change= false;
811+
boolhas_nulls= false;
812+
Datumtoast_values[MaxTupleAttributeNumber];
813+
chartoast_nulls[MaxTupleAttributeNumber];
814+
booltoast_free[MaxTupleAttributeNumber];
815+
816+
/*
817+
* See if it's a composite type, and get the tupdesc if so.
818+
*/
819+
tupleDesc=lookup_rowtype_tupdesc_noerror(typeId,typeMod, true);
820+
if (tupleDesc==NULL)
821+
returnvalue;/* not a composite type */
822+
823+
att=tupleDesc->attrs;
824+
numAttrs=tupleDesc->natts;
825+
826+
/*
827+
* Break down the tuple into fields.
828+
*/
829+
olddata=DatumGetHeapTupleHeader(value);
830+
Assert(typeId==HeapTupleHeaderGetTypeId(olddata));
831+
Assert(typeMod==HeapTupleHeaderGetTypMod(olddata));
832+
/* Build a temporary HeapTuple control structure */
833+
tmptup.t_len=HeapTupleHeaderGetDatumLength(olddata);
834+
ItemPointerSetInvalid(&(tmptup.t_self));
835+
tmptup.t_tableOid=InvalidOid;
836+
tmptup.t_data=olddata;
837+
838+
Assert(numAttrs <=MaxTupleAttributeNumber);
839+
heap_deformtuple(&tmptup,tupleDesc,toast_values,toast_nulls);
840+
841+
memset(toast_free,0,numAttrs*sizeof(bool));
842+
843+
for (i=0;i<numAttrs;i++)
844+
{
845+
/*
846+
* Look at non-null varlena attributes
847+
*/
848+
if (toast_nulls[i]=='n')
849+
has_nulls= true;
850+
elseif (att[i]->attlen==-1)
851+
{
852+
varattrib*new_value;
853+
854+
new_value= (varattrib*)DatumGetPointer(toast_values[i]);
855+
if (VARATT_IS_EXTENDED(new_value))
856+
{
857+
new_value=heap_tuple_untoast_attr(new_value);
858+
toast_values[i]=PointerGetDatum(new_value);
859+
toast_free[i]= true;
860+
need_change= true;
861+
}
862+
}
863+
}
864+
865+
/*
866+
* If nothing to untoast, just return the original tuple.
867+
*/
868+
if (!need_change)
869+
returnvalue;
870+
871+
/*
872+
* Calculate the new size of the tuple. Header size should not
873+
* change, but data size might.
874+
*/
875+
new_len= offsetof(HeapTupleHeaderData,t_bits);
876+
if (has_nulls)
877+
new_len+=BITMAPLEN(numAttrs);
878+
if (olddata->t_infomask&HEAP_HASOID)
879+
new_len+=sizeof(Oid);
880+
new_len=MAXALIGN(new_len);
881+
Assert(new_len==olddata->t_hoff);
882+
new_len+=ComputeDataSize(tupleDesc,toast_values,toast_nulls);
883+
884+
new_data= (HeapTupleHeader)palloc0(new_len);
885+
886+
/*
887+
* Put the tuple header and the changed values into place
888+
*/
889+
memcpy(new_data,olddata,olddata->t_hoff);
890+
891+
HeapTupleHeaderSetDatumLength(new_data,new_len);
892+
893+
DataFill((char*)new_data+olddata->t_hoff,
894+
tupleDesc,
895+
toast_values,
896+
toast_nulls,
897+
&(new_data->t_infomask),
898+
has_nulls ?new_data->t_bits :NULL);
899+
900+
/*
901+
* Free allocated temp values
902+
*/
903+
for (i=0;i<numAttrs;i++)
904+
if (toast_free[i])
905+
pfree(DatumGetPointer(toast_values[i]));
906+
907+
returnPointerGetDatum(new_data);
908+
}
909+
910+
788911
/* ----------
789912
* toast_compress_datum -
790913
*

‎src/backend/optimizer/path/allpaths.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.117 2004/06/01 03:02:51 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.118 2004/06/05 01:55:04 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -302,11 +302,15 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
302302
{
303303
Var*parentvar= (Var*)lfirst(parentvars);
304304
Var*childvar= (Var*)lfirst(childvars);
305-
intparentndx=parentvar->varattno-rel->min_attr;
306-
intchildndx=childvar->varattno-childrel->min_attr;
307305

308-
if (childrel->attr_widths[childndx]>rel->attr_widths[parentndx])
309-
rel->attr_widths[parentndx]=childrel->attr_widths[childndx];
306+
if (IsA(parentvar,Var)&&IsA(childvar,Var))
307+
{
308+
intpndx=parentvar->varattno-rel->min_attr;
309+
intcndx=childvar->varattno-childrel->min_attr;
310+
311+
if (childrel->attr_widths[cndx]>rel->attr_widths[pndx])
312+
rel->attr_widths[pndx]=childrel->attr_widths[cndx];
313+
}
310314
}
311315
}
312316

‎src/backend/optimizer/path/costsize.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* Portions Copyright (c) 1994, Regents of the University of California
5050
*
5151
* IDENTIFICATION
52-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.129 2004/06/01 03:02:52 tgl Exp $
52+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.130 2004/06/05 01:55:04 tgl Exp $
5353
*
5454
*-------------------------------------------------------------------------
5555
*/
@@ -1704,11 +1704,18 @@ set_rel_width(Query *root, RelOptInfo *rel)
17041704
foreach(tllist,rel->reltargetlist)
17051705
{
17061706
Var*var= (Var*)lfirst(tllist);
1707-
intndx=var->varattno-rel->min_attr;
1707+
intndx;
17081708
Oidrelid;
17091709
int32item_width;
17101710

1711-
Assert(IsA(var,Var));
1711+
/* For now, punt on whole-row child Vars */
1712+
if (!IsA(var,Var))
1713+
{
1714+
tuple_width+=32;/* arbitrary */
1715+
continue;
1716+
}
1717+
1718+
ndx=var->varattno-rel->min_attr;
17121719

17131720
/*
17141721
* The width probably hasn't been cached yet, but may as well

‎src/backend/optimizer/path/pathkeys.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.59 2004/06/01 03:02:52 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.60 2004/06/05 01:55:04 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -725,7 +725,8 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
725725
{
726726
Var*var= (Var*)lfirst(temp);
727727

728-
if (var->varattno==varattno)
728+
if (IsA(var,Var)&&
729+
var->varattno==varattno)
729730
returnvar;
730731
}
731732

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp