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

Commit2e6d2f8

Browse files
committed
try reloading cached 'prel' entry when about to spawn a new partition for INSERT (issue #57), extract function perform_type_cast(), select_partition_for_insert() & find_partitions_for_value() now take 'value_type', improve handle_const(), xact_lock_partitioned_rel() and xact_lock_rel_exclusive() return LockAcquireResult
1 parent681aa43 commit2e6d2f8

12 files changed

+238
-134
lines changed

‎src/copy_stmt_hooking.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
508508
/* Search for a matching partition */
509509
rri_holder_child=select_partition_for_insert(prel,&parts_storage,
510510
values[prel->attnum-1],
511+
prel->atttype,
511512
estate, true);
512513
child_result_rel=rri_holder_child->result_rel_info;
513514
estate->es_result_relation_info=child_result_rel;

‎src/init.c

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include"catalog/pg_type.h"
2828
#include"miscadmin.h"
2929
#include"optimizer/clauses.h"
30-
#include"parser/parse_coerce.h"
3130
#include"utils/datum.h"
3231
#include"utils/inval.h"
3332
#include"utils/builtins.h"
@@ -925,6 +924,7 @@ read_opexpr_const(const OpExpr *opexpr,
925924
constNode*right;
926925
constVar*part_attr;/* partitioned column */
927926
constConst*constant;
927+
boolcast_success;
928928

929929
if (list_length(opexpr->args)!=2)
930930
return false;
@@ -960,52 +960,18 @@ read_opexpr_const(const OpExpr *opexpr,
960960

961961
constant= (Const*)right;
962962

963-
/* Check that types are binary coercible */
964-
if (IsBinaryCoercible(constant->consttype,prel->atttype))
965-
{
966-
*val=constant->constvalue;
967-
}
968-
/* If not, try to perfrom a type cast */
969-
else
970-
{
971-
CoercionPathTyperet;
972-
Oidcastfunc=InvalidOid;
973-
974-
ret=find_coercion_pathway(prel->atttype,constant->consttype,
975-
COERCION_EXPLICIT,&castfunc);
976-
977-
switch (ret)
978-
{
979-
/* There's a function */
980-
caseCOERCION_PATH_FUNC:
981-
{
982-
/* Perform conversion */
983-
Assert(castfunc!=InvalidOid);
984-
*val=OidFunctionCall1(castfunc,constant->constvalue);
985-
}
986-
break;
963+
/* Cast Const to a proper type if needed */
964+
*val=perform_type_cast(constant->constvalue,
965+
getBaseType(constant->consttype),
966+
getBaseType(prel->atttype),
967+
&cast_success);
987968

988-
/* Types are binary compatible (no implicit cast) */
989-
caseCOERCION_PATH_RELABELTYPE:
990-
{
991-
/* We don't perform any checks here */
992-
*val=constant->constvalue;
993-
}
994-
break;
995-
996-
/* TODO: implement these if needed */
997-
caseCOERCION_PATH_ARRAYCOERCE:
998-
caseCOERCION_PATH_COERCEVIAIO:
969+
if (!cast_success)
970+
{
971+
elog(WARNING,"Constant type in some check constraint "
972+
"does not match the partitioned column's type");
999973

1000-
/* There's no cast available */
1001-
caseCOERCION_PATH_NONE:
1002-
default:
1003-
{
1004-
elog(WARNING,"Constant type in some check constraint "
1005-
"does not match the partitioned column's type");
1006-
return false;
1007-
}
1008-
}
974+
return false;
1009975
}
1010976

1011977
return true;

‎src/partition_filter.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,9 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
282282
* Find matching partitions for 'value' using PartRelationInfo.
283283
*/
284284
Oid*
285-
find_partitions_for_value(Datumvalue,constPartRelationInfo*prel,
286-
ExprContext*econtext,int*nparts)
285+
find_partitions_for_value(Datumvalue,Oidvalue_type,
286+
constPartRelationInfo*prel,
287+
int*nparts)
287288
{
288289
#defineCopyToTempConst(const_field,attr_field) \
289290
( temp_const.const_field = prel->attr_field )
@@ -308,7 +309,7 @@ find_partitions_for_value(Datum value, const PartRelationInfo *prel,
308309
CopyToTempConst(constbyval,attbyval);
309310

310311
/* We use 0 since varno doesn't matter for Const */
311-
InitWalkerContext(&wcxt,0,prel,econtext, true);
312+
InitWalkerContext(&wcxt,0,prel,NULL, true);
312313
ranges=walk_expr_tree((Expr*)&temp_const,&wcxt)->rangeset;
313314
returnget_partition_oids(ranges,nparts,prel, false);
314315
}
@@ -429,9 +430,9 @@ partition_filter_exec(CustomScanState *node)
429430
old_cxt=MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
430431

431432
/* Search for a matching partition */
432-
rri_holder=select_partition_for_insert(prel,
433-
&state->result_parts,
434-
value,estate, true);
433+
rri_holder=select_partition_for_insert(prel,&state->result_parts,
434+
value,prel->atttype,
435+
estate, true);
435436
estate->es_result_relation_info=rri_holder->result_rel_info;
436437

437438
/* Switch back and clean up per-tuple context */
@@ -475,20 +476,18 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
475476
ResultRelInfoHolder*
476477
select_partition_for_insert(constPartRelationInfo*prel,
477478
ResultPartsStorage*parts_storage,
478-
Datumvalue,EState*estate,
479+
Datumvalue,Oidvalue_type,
480+
EState*estate,
479481
boolspawn_partitions)
480482
{
481483
MemoryContextold_cxt;
482-
ExprContext*econtext;
483484
ResultRelInfoHolder*rri_holder;
484485
Oidselected_partid=InvalidOid;
485486
Oid*parts;
486487
intnparts;
487488

488-
econtext=GetPerTupleExprContext(estate);
489-
490489
/* Search for matching partitions */
491-
parts=find_partitions_for_value(value,prel,econtext,&nparts);
490+
parts=find_partitions_for_value(value,value_type,prel,&nparts);
492491

493492
if (nparts>1)
494493
elog(ERROR,ERR_PART_ATTR_MULTIPLE);

‎src/partition_filter.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@ ResultRelInfoHolder * scan_result_parts_storage(Oid partid,
106106
ResultPartsStorage*storage);
107107

108108
/* Find suitable partition using 'value' */
109-
Oid*find_partitions_for_value(Datumvalue,constPartRelationInfo*prel,
110-
ExprContext*econtext,int*nparts);
109+
Oid*find_partitions_for_value(Datumvalue,Oidvalue_type,
110+
constPartRelationInfo*prel,
111+
int*nparts);
111112

112113
Plan*make_partition_filter(Plan*subplan,
113114
Oidpartitioned_table,
@@ -131,7 +132,8 @@ void partition_filter_explain(CustomScanState *node,
131132

132133
ResultRelInfoHolder*select_partition_for_insert(constPartRelationInfo*prel,
133134
ResultPartsStorage*parts_storage,
134-
Datumvalue,EState*estate,
135+
Datumvalue,Oidvalue_type,
136+
EState*estate,
135137
boolspawn_partitions);
136138

137139
#endif

‎src/pathman_workers.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ partition_table_concurrently(PG_FUNCTION_ARGS)
610610
/* Check if relation is a partitioned table */
611611
shout_if_prel_is_invalid(relid,
612612
/* We also lock the parent relation */
613-
get_pathman_relation_info_after_lock(relid, true),
613+
get_pathman_relation_info_after_lock(relid, true,NULL),
614614
/* Partitioning type does not matter here */
615615
PT_INDIFFERENT);
616616
/*

‎src/pg_pathman.c

Lines changed: 100 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ create_partitions_internal(Oid relid, Datum value, Oid value_type)
704704
PG_TRY();
705705
{
706706
constPartRelationInfo*prel;
707+
LockAcquireResultlock_result;/* could we lock the parent? */
707708
Datumvalues[Natts_pathman_config];
708709
boolisnull[Natts_pathman_config];
709710

@@ -713,57 +714,91 @@ create_partitions_internal(Oid relid, Datum value, Oid value_type)
713714
Oidbase_atttype;/* base type of prel->atttype */
714715
Oidbase_value_type;/* base type of value_type */
715716

716-
Datummin_rvalue,/* absolute MIN */
717-
max_rvalue;/* absolute MAX */
718-
719-
Oidinterval_type=InvalidOid;
720-
Datuminterval_binary,/* assigned 'width' of a single partition */
721-
interval_text;
722-
723-
FmgrInfointerval_type_cmp;
724-
725717
/* Fetch PartRelationInfo by 'relid' */
726-
prel=get_pathman_relation_info(relid);
718+
prel=get_pathman_relation_info_after_lock(relid, true,&lock_result);
727719
shout_if_prel_is_invalid(relid,prel,PT_RANGE);
728720

729721
/* Fetch base types of prel->atttype & value_type */
730722
base_atttype=getBaseType(prel->atttype);
731723
base_value_type=getBaseType(value_type);
732724

733-
/* Read max & min range values from PartRelationInfo */
734-
min_rvalue=PrelGetRangesArray(prel)[0].min;
735-
max_rvalue=PrelGetRangesArray(prel)[PrelLastChild(prel)].max;
736-
737-
/* Copy datums on order to protect them from cache invalidation */
738-
min_rvalue=datumCopy(min_rvalue,prel->attbyval,prel->attlen);
739-
max_rvalue=datumCopy(max_rvalue,prel->attbyval,prel->attlen);
725+
/* Search for a suitable partition if we didn't hold it */
726+
Assert(lock_result!=LOCKACQUIRE_NOT_AVAIL);
727+
if (lock_result==LOCKACQUIRE_OK)
728+
{
729+
Oid*parts;
730+
intnparts;
740731

741-
/*Retrieve interval as TEXT from tuple */
742-
interval_text=values[Anum_pathman_config_range_interval-1];
732+
/*Search for matching partitions */
733+
parts=find_partitions_for_value(value,value_type,prel,&nparts);
743734

744-
/* Convert interval to binary representation */
745-
interval_binary=extract_binary_interval_from_text(interval_text,
746-
base_atttype,
747-
&interval_type);
735+
/* Shout if there's more than one */
736+
if (nparts>1)
737+
elog(ERROR,ERR_PART_ATTR_MULTIPLE);
748738

749-
/* Fill the FmgrInfo struct with a cmp(value, part_attribute) function */
750-
fill_type_cmp_fmgr_info(&interval_type_cmp,base_value_type,base_atttype);
739+
/* It seems that we got a partition! */
740+
elseif (nparts==1)
741+
{
742+
/* Unlock the parent (we're not going to spawn) */
743+
xact_unlock_partitioned_rel(relid);
751744

752-
if (SPI_connect()!=SPI_OK_CONNECT)
753-
elog(ERROR,"could not connect using SPI");
745+
/* Simply return the suitable partition */
746+
partid=parts[0];
747+
}
754748

755-
/* while (value >= MAX) ... */
756-
spawn_partitions(PrelParentRelid(prel),value,max_rvalue,
757-
base_atttype,&interval_type_cmp,interval_binary,
758-
interval_type, true,&partid);
749+
/* Don't forget to free */
750+
pfree(parts);
751+
}
759752

760-
/*while (value < MIN) ... */
753+
/*Else spawn a new one (we hold a lock on the parent) */
761754
if (partid==InvalidOid)
762-
spawn_partitions(PrelParentRelid(prel),value,min_rvalue,
763-
base_atttype,&interval_type_cmp,interval_binary,
764-
interval_type, false,&partid);
755+
{
756+
Datummin_rvalue,/* absolute MIN */
757+
max_rvalue;/* absolute MAX */
758+
759+
Oidinterval_type=InvalidOid;
760+
Datuminterval_binary,/* assigned 'width' of one partition */
761+
interval_text;
762+
763+
FmgrInfointerval_type_cmp;
764+
765+
/* Read max & min range values from PartRelationInfo */
766+
min_rvalue=PrelGetRangesArray(prel)[0].min;
767+
max_rvalue=PrelGetRangesArray(prel)[PrelLastChild(prel)].max;
768+
769+
/* Copy datums on order to protect them from cache invalidation */
770+
min_rvalue=datumCopy(min_rvalue,prel->attbyval,prel->attlen);
771+
max_rvalue=datumCopy(max_rvalue,prel->attbyval,prel->attlen);
772+
773+
/* Retrieve interval as TEXT from tuple */
774+
interval_text=values[Anum_pathman_config_range_interval-1];
765775

766-
SPI_finish();/* close SPI connection */
776+
/* Convert interval to binary representation */
777+
interval_binary=extract_binary_interval_from_text(interval_text,
778+
base_atttype,
779+
&interval_type);
780+
781+
/* Fill the FmgrInfo struct with a cmp(value, part_attribute) */
782+
fill_type_cmp_fmgr_info(&interval_type_cmp,
783+
base_value_type,
784+
base_atttype);
785+
786+
if (SPI_connect()!=SPI_OK_CONNECT)
787+
elog(ERROR,"could not connect using SPI");
788+
789+
/* while (value >= MAX) ... */
790+
spawn_partitions(PrelParentRelid(prel),value,max_rvalue,
791+
base_atttype,&interval_type_cmp,
792+
interval_binary,interval_type, true,&partid);
793+
794+
/* while (value < MIN) ... */
795+
if (partid==InvalidOid)
796+
spawn_partitions(PrelParentRelid(prel),value,min_rvalue,
797+
base_atttype,&interval_type_cmp,
798+
interval_binary,interval_type, false,&partid);
799+
800+
SPI_finish();/* close SPI connection */
801+
}
767802
}
768803
else
769804
elog(ERROR,"pg_pathman's config does not contain relation \"%s\"",
@@ -1082,7 +1117,7 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
10821117
PrelGetRangesArray(context->prel),
10831118
PrelChildrenCount(context->prel),
10841119
strategy,
1085-
result);
1120+
result);/* output */
10861121

10871122
result->paramsel=estimate_paramsel_using_prel(prel,strategy);
10881123

@@ -1169,7 +1204,7 @@ search_range_partition_eq(const Datum value,
11691204
ranges,
11701205
nranges,
11711206
BTEqualStrategyNumber,
1172-
&result);
1207+
&result);/* output */
11731208

11741209
if (result.found_gap)
11751210
{
@@ -1220,7 +1255,7 @@ handle_const(const Const *c, WalkerContext *context)
12201255

12211256
/*
12221257
* Had to add this check for queries like:
1223-
*select * from test.hash_rel where txt = NULL;
1258+
*select * from test.hash_rel where txt = NULL;
12241259
*/
12251260
if (!context->for_insert||c->constisnull)
12261261
{
@@ -1234,9 +1269,30 @@ handle_const(const Const *c, WalkerContext *context)
12341269
{
12351270
casePT_HASH:
12361271
{
1237-
Datumvalue=OidFunctionCall1(prel->hash_proc,c->constvalue);
1238-
uint32idx=hash_to_part_index(DatumGetInt32(value),
1239-
PrelChildrenCount(prel));
1272+
Datumvalue,/* value to be hashed */
1273+
hash;/* 32-bit hash */
1274+
uint32idx;/* index of partition */
1275+
boolcast_success;
1276+
1277+
/* Peform type cast if types mismatch */
1278+
if (prel->atttype!=c->consttype)
1279+
{
1280+
value=perform_type_cast(c->constvalue,
1281+
getBaseType(c->consttype),
1282+
getBaseType(prel->atttype),
1283+
&cast_success);
1284+
1285+
if (!cast_success)
1286+
elog(ERROR,"Cannot select partition: "
1287+
"unable to perform type cast");
1288+
}
1289+
/* Else use the Const's value */
1290+
elsevalue=c->constvalue;
1291+
1292+
/* Calculate 32-bit hash of 'value' and corresponding index */
1293+
hash=OidFunctionCall1(prel->hash_proc,value);
1294+
idx=hash_to_part_index(DatumGetInt32(hash),
1295+
PrelChildrenCount(prel));
12401296

12411297
result->paramsel=estimate_paramsel_using_prel(prel,strategy);
12421298
result->rangeset=list_make1_irange(make_irange(idx,idx,IR_LOSSY));
@@ -1245,7 +1301,7 @@ handle_const(const Const *c, WalkerContext *context)
12451301

12461302
casePT_RANGE:
12471303
{
1248-
FmgrInfocmp_finfo;
1304+
FmgrInfocmp_finfo;
12491305

12501306
fill_type_cmp_fmgr_info(&cmp_finfo,
12511307
getBaseType(c->consttype),
@@ -1256,7 +1312,7 @@ handle_const(const Const *c, WalkerContext *context)
12561312
PrelGetRangesArray(context->prel),
12571313
PrelChildrenCount(context->prel),
12581314
strategy,
1259-
result);
1315+
result);/* output */
12601316

12611317
result->paramsel=estimate_paramsel_using_prel(prel,strategy);
12621318
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp