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

Commit5a73e17

Browse files
committed
Improve error reporting for tuple-routing failures.
Currently, the whole row is shown without column names. Instead,adopt a style similar to _bt_check_unique() in ExecFindPartition()and show the failing key: (key1, ...) = (val1, ...).Amit Langote, per a complaint from Simon Riggs. Reviewed by me;I also adjusted the grammar in one of the comments.Discussion:http://postgr.es/m/9f9dc7ae-14f0-4a25-5485-964d9bfc19bd@lab.ntt.co.jp
1 parentbe6ed64 commit5a73e17

File tree

8 files changed

+231
-50
lines changed

8 files changed

+231
-50
lines changed

‎src/backend/access/index/genam.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ IndexScanEnd(IndexScanDesc scan)
168168
* The passed-in values/nulls arrays are the "raw" input to the index AM,
169169
* e.g. results of FormIndexDatum --- this is not necessarily what is stored
170170
* in the index, but it's what the user perceives to be stored.
171+
*
172+
* Note: if you change anything here, check whether
173+
* ExecBuildSlotPartitionKeyDescription() in execMain.c needs a similar
174+
* change.
171175
*/
172176
char*
173177
BuildIndexValueDescription(RelationindexRelation,

‎src/backend/catalog/partition.c

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,6 @@ static int partition_bound_bsearch(PartitionKey key,
140140
PartitionBoundInfoboundinfo,
141141
void*probe,boolprobe_is_bound,bool*is_equal);
142142

143-
/* Support get_partition_for_tuple() */
144-
staticvoidFormPartitionKeyDatum(PartitionDispatchpd,
145-
TupleTableSlot*slot,
146-
EState*estate,
147-
Datum*values,
148-
bool*isnull);
149-
150143
/*
151144
* RelationBuildPartitionDesc
152145
*Form rel's partition descriptor
@@ -1608,7 +1601,7 @@ generate_partition_qual(Relation rel)
16081601
* the heap tuple passed in.
16091602
* ----------------
16101603
*/
1611-
staticvoid
1604+
void
16121605
FormPartitionKeyDatum(PartitionDispatchpd,
16131606
TupleTableSlot*slot,
16141607
EState*estate,
@@ -1672,7 +1665,8 @@ int
16721665
get_partition_for_tuple(PartitionDispatch*pd,
16731666
TupleTableSlot*slot,
16741667
EState*estate,
1675-
Oid*failed_at)
1668+
PartitionDispatchData**failed_at,
1669+
TupleTableSlot**failed_slot)
16761670
{
16771671
PartitionDispatchparent;
16781672
Datumvalues[PARTITION_MAX_KEYS];
@@ -1693,13 +1687,6 @@ get_partition_for_tuple(PartitionDispatch *pd,
16931687
TupleTableSlot*myslot=parent->tupslot;
16941688
TupleConversionMap*map=parent->tupmap;
16951689

1696-
/* Quick exit */
1697-
if (partdesc->nparts==0)
1698-
{
1699-
*failed_at=RelationGetRelid(parent->reldesc);
1700-
return-1;
1701-
}
1702-
17031690
if (myslot!=NULL&&map!=NULL)
17041691
{
17051692
HeapTupletuple=ExecFetchSlotTuple(slot);
@@ -1710,6 +1697,14 @@ get_partition_for_tuple(PartitionDispatch *pd,
17101697
slot=myslot;
17111698
}
17121699

1700+
/* Quick exit */
1701+
if (partdesc->nparts==0)
1702+
{
1703+
*failed_at=parent;
1704+
*failed_slot=slot;
1705+
return-1;
1706+
}
1707+
17131708
/*
17141709
* Extract partition key from tuple. Expression evaluation machinery
17151710
* that FormPartitionKeyDatum() invokes expects ecxt_scantuple to
@@ -1774,7 +1769,8 @@ get_partition_for_tuple(PartitionDispatch *pd,
17741769
if (cur_index<0)
17751770
{
17761771
result=-1;
1777-
*failed_at=RelationGetRelid(parent->reldesc);
1772+
*failed_at=parent;
1773+
*failed_slot=slot;
17781774
break;
17791775
}
17801776
elseif (parent->indexes[cur_index] >=0)

‎src/backend/executor/execMain.c

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include"utils/lsyscache.h"
6161
#include"utils/memutils.h"
6262
#include"utils/rls.h"
63+
#include"utils/ruleutils.h"
6364
#include"utils/snapmgr.h"
6465
#include"utils/tqual.h"
6566

@@ -95,6 +96,10 @@ static char *ExecBuildSlotValueDescription(Oid reloid,
9596
TupleDesctupdesc,
9697
Bitmapset*modifiedCols,
9798
intmaxfieldlen);
99+
staticchar*ExecBuildSlotPartitionKeyDescription(Relationrel,
100+
Datum*values,
101+
bool*isnull,
102+
intmaxfieldlen);
98103
staticvoidEvalPlanQualStart(EPQState*epqstate,EState*parentestate,
99104
Plan*planTree);
100105

@@ -3189,33 +3194,122 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
31893194
TupleTableSlot*slot,EState*estate)
31903195
{
31913196
intresult;
3192-
Oidfailed_at;
3197+
PartitionDispatchData*failed_at;
3198+
TupleTableSlot*failed_slot;
31933199

3194-
result=get_partition_for_tuple(pd,slot,estate,&failed_at);
3200+
result=get_partition_for_tuple(pd,slot,estate,
3201+
&failed_at,&failed_slot);
31953202
if (result<0)
31963203
{
3197-
Relationrel=resultRelInfo->ri_RelationDesc;
3204+
Relationfailed_rel;
3205+
Datumkey_values[PARTITION_MAX_KEYS];
3206+
boolkey_isnull[PARTITION_MAX_KEYS];
31983207
char*val_desc;
3199-
Bitmapset*insertedCols,
3200-
*updatedCols,
3201-
*modifiedCols;
3202-
TupleDesctupDesc=RelationGetDescr(rel);
3203-
3204-
insertedCols=GetInsertedColumns(resultRelInfo,estate);
3205-
updatedCols=GetUpdatedColumns(resultRelInfo,estate);
3206-
modifiedCols=bms_union(insertedCols,updatedCols);
3207-
val_desc=ExecBuildSlotValueDescription(RelationGetRelid(rel),
3208-
slot,
3209-
tupDesc,
3210-
modifiedCols,
3211-
64);
3212-
Assert(OidIsValid(failed_at));
3208+
ExprContext*ecxt=GetPerTupleExprContext(estate);
3209+
3210+
failed_rel=failed_at->reldesc;
3211+
ecxt->ecxt_scantuple=failed_slot;
3212+
FormPartitionKeyDatum(failed_at,failed_slot,estate,
3213+
key_values,key_isnull);
3214+
val_desc=ExecBuildSlotPartitionKeyDescription(failed_rel,
3215+
key_values,
3216+
key_isnull,
3217+
64);
3218+
Assert(OidIsValid(RelationGetRelid(failed_rel)));
32133219
ereport(ERROR,
32143220
(errcode(ERRCODE_CHECK_VIOLATION),
32153221
errmsg("no partition of relation \"%s\" found for row",
3216-
get_rel_name(failed_at)),
3217-
val_desc ?errdetail("Failing row contains %s.",val_desc) :0));
3222+
RelationGetRelationName(failed_rel)),
3223+
val_desc ?errdetail("Partition key of the failing row contains %s.",val_desc) :0));
32183224
}
32193225

32203226
returnresult;
32213227
}
3228+
3229+
/*
3230+
* BuildSlotPartitionKeyDescription
3231+
*
3232+
* This works very much like BuildIndexValueDescription() and is currently
3233+
* used for building error messages when ExecFindPartition() fails to find
3234+
* partition for a row.
3235+
*/
3236+
staticchar*
3237+
ExecBuildSlotPartitionKeyDescription(Relationrel,
3238+
Datum*values,
3239+
bool*isnull,
3240+
intmaxfieldlen)
3241+
{
3242+
StringInfoDatabuf;
3243+
PartitionKeykey=RelationGetPartitionKey(rel);
3244+
intpartnatts=get_partition_natts(key);
3245+
inti;
3246+
Oidrelid=RelationGetRelid(rel);
3247+
AclResultaclresult;
3248+
3249+
if (check_enable_rls(relid,InvalidOid, true)==RLS_ENABLED)
3250+
returnNULL;
3251+
3252+
/* If the user has table-level access, just go build the description. */
3253+
aclresult=pg_class_aclcheck(relid,GetUserId(),ACL_SELECT);
3254+
if (aclresult!=ACLCHECK_OK)
3255+
{
3256+
/*
3257+
* Step through the columns of the partition key and make sure the
3258+
* user has SELECT rights on all of them.
3259+
*/
3260+
for (i=0;i<partnatts;i++)
3261+
{
3262+
AttrNumberattnum=get_partition_col_attnum(key,i);
3263+
3264+
/*
3265+
* If this partition key column is an expression, we return no
3266+
* detail rather than try to figure out what column(s) the
3267+
* expression includes and if the user has SELECT rights on them.
3268+
*/
3269+
if (attnum==InvalidAttrNumber||
3270+
pg_attribute_aclcheck(relid,attnum,GetUserId(),
3271+
ACL_SELECT)!=ACLCHECK_OK)
3272+
returnNULL;
3273+
}
3274+
}
3275+
3276+
initStringInfo(&buf);
3277+
appendStringInfo(&buf,"(%s) = (",
3278+
pg_get_partkeydef_columns(relid, true));
3279+
3280+
for (i=0;i<partnatts;i++)
3281+
{
3282+
char*val;
3283+
intvallen;
3284+
3285+
if (isnull[i])
3286+
val="null";
3287+
else
3288+
{
3289+
Oidfoutoid;
3290+
booltypisvarlena;
3291+
3292+
getTypeOutputInfo(get_partition_col_typid(key,i),
3293+
&foutoid,&typisvarlena);
3294+
val=OidOutputFunctionCall(foutoid,values[i]);
3295+
}
3296+
3297+
if (i>0)
3298+
appendStringInfoString(&buf,", ");
3299+
3300+
/* truncate if needed */
3301+
vallen=strlen(val);
3302+
if (vallen <=maxfieldlen)
3303+
appendStringInfoString(&buf,val);
3304+
else
3305+
{
3306+
vallen=pg_mbcliplen(val,vallen,maxfieldlen);
3307+
appendBinaryStringInfo(&buf,val,vallen);
3308+
appendStringInfoString(&buf,"...");
3309+
}
3310+
}
3311+
3312+
appendStringInfoChar(&buf,')');
3313+
3314+
returnbuf.data;
3315+
}

‎src/backend/utils/adt/ruleutils.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,8 @@ static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
317317
constOid*excludeOps,
318318
boolattrsOnly,boolshowTblSpc,
319319
intprettyFlags,boolmissing_ok);
320-
staticchar*pg_get_partkeydef_worker(Oidrelid,intprettyFlags);
320+
staticchar*pg_get_partkeydef_worker(Oidrelid,intprettyFlags,
321+
boolattrsOnly);
321322
staticchar*pg_get_constraintdef_worker(OidconstraintId,boolfullCommand,
322323
intprettyFlags,boolmissing_ok);
323324
statictext*pg_get_expr_worker(text*expr,Oidrelid,constchar*relname,
@@ -1431,14 +1432,26 @@ pg_get_partkeydef(PG_FUNCTION_ARGS)
14311432
Oidrelid=PG_GETARG_OID(0);
14321433

14331434
PG_RETURN_TEXT_P(string_to_text(pg_get_partkeydef_worker(relid,
1434-
PRETTYFLAG_INDENT)));
1435+
PRETTYFLAG_INDENT,
1436+
false)));
1437+
}
1438+
1439+
/* Internal version that just reports the column definitions */
1440+
char*
1441+
pg_get_partkeydef_columns(Oidrelid,boolpretty)
1442+
{
1443+
intprettyFlags;
1444+
1445+
prettyFlags=pretty ?PRETTYFLAG_PAREN |PRETTYFLAG_INDENT :PRETTYFLAG_INDENT;
1446+
returnpg_get_partkeydef_worker(relid,prettyFlags, true);
14351447
}
14361448

14371449
/*
14381450
* Internal workhorse to decompile a partition key definition.
14391451
*/
14401452
staticchar*
1441-
pg_get_partkeydef_worker(Oidrelid,intprettyFlags)
1453+
pg_get_partkeydef_worker(Oidrelid,intprettyFlags,
1454+
boolattrsOnly)
14421455
{
14431456
Form_pg_partitioned_tableform;
14441457
HeapTupletuple;
@@ -1508,17 +1521,20 @@ pg_get_partkeydef_worker(Oid relid, int prettyFlags)
15081521
switch (form->partstrat)
15091522
{
15101523
casePARTITION_STRATEGY_LIST:
1511-
appendStringInfo(&buf,"LIST");
1524+
if (!attrsOnly)
1525+
appendStringInfo(&buf,"LIST");
15121526
break;
15131527
casePARTITION_STRATEGY_RANGE:
1514-
appendStringInfo(&buf,"RANGE");
1528+
if (!attrsOnly)
1529+
appendStringInfo(&buf,"RANGE");
15151530
break;
15161531
default:
15171532
elog(ERROR,"unexpected partition strategy: %d",
15181533
(int)form->partstrat);
15191534
}
15201535

1521-
appendStringInfo(&buf," (");
1536+
if (!attrsOnly)
1537+
appendStringInfo(&buf," (");
15221538
sep="";
15231539
for (keyno=0;keyno<form->partnatts;keyno++)
15241540
{
@@ -1561,14 +1577,17 @@ pg_get_partkeydef_worker(Oid relid, int prettyFlags)
15611577

15621578
/* Add collation, if not default for column */
15631579
partcoll=partcollation->values[keyno];
1564-
if (OidIsValid(partcoll)&&partcoll!=keycolcollation)
1580+
if (!attrsOnly&&OidIsValid(partcoll)&&partcoll!=keycolcollation)
15651581
appendStringInfo(&buf," COLLATE %s",
15661582
generate_collation_name((partcoll)));
15671583

15681584
/* Add the operator class name, if not default */
1569-
get_opclass_name(partclass->values[keyno],keycoltype,&buf);
1585+
if (!attrsOnly)
1586+
get_opclass_name(partclass->values[keyno],keycoltype,&buf);
15701587
}
1571-
appendStringInfoChar(&buf,')');
1588+
1589+
if (!attrsOnly)
1590+
appendStringInfoChar(&buf,')');
15721591

15731592
/* Clean up */
15741593
ReleaseSysCache(tuple);

‎src/include/catalog/partition.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,14 @@ extern List *RelationGetPartitionQual(Relation rel);
8585
externPartitionDispatch*RelationGetPartitionDispatchInfo(Relationrel,
8686
intlockmode,int*num_parted,
8787
List**leaf_part_oids);
88+
externvoidFormPartitionKeyDatum(PartitionDispatchpd,
89+
TupleTableSlot*slot,
90+
EState*estate,
91+
Datum*values,
92+
bool*isnull);
8893
externintget_partition_for_tuple(PartitionDispatch*pd,
8994
TupleTableSlot*slot,
9095
EState*estate,
91-
Oid*failed_at);
96+
PartitionDispatchData**failed_at,
97+
TupleTableSlot**failed_slot);
9298
#endif/* PARTITION_H */

‎src/include/utils/ruleutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
externchar*pg_get_indexdef_string(Oidindexrelid);
2222
externchar*pg_get_indexdef_columns(Oidindexrelid,boolpretty);
2323

24+
externchar*pg_get_partkeydef_columns(Oidrelid,boolpretty);
25+
2426
externchar*pg_get_constraintdef_command(OidconstraintId);
2527
externchar*deparse_expression(Node*expr,List*dpcontext,
2628
boolforceprefix,boolshowimplicit);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp