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

Commita90641e

Browse files
committed
Revert "Rewrite some RI code to avoid using SPI"
This reverts commit99392cd.We'd rather rewrite ri_triggers.c as a whole rather than piecemeal.Discussion:https://postgr.es/m/E1ncXX2-000mFt-Pe@gemulon.postgresql.org
1 parent3e707fb commita90641e

File tree

7 files changed

+317
-605
lines changed

7 files changed

+317
-605
lines changed

‎src/backend/executor/execPartition.c

Lines changed: 6 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,8 @@ static void FormPartitionKeyDatum(PartitionDispatch pd,
176176
EState*estate,
177177
Datum*values,
178178
bool*isnull);
179-
staticintget_partition_for_tuple(PartitionKeykey,
180-
PartitionDescpartdesc,
181-
Datum*values,bool*isnull);
179+
staticintget_partition_for_tuple(PartitionDispatchpd,Datum*values,
180+
bool*isnull);
182181
staticchar*ExecBuildSlotPartitionKeyDescription(Relationrel,
183182
Datum*values,
184183
bool*isnull,
@@ -319,9 +318,7 @@ ExecFindPartition(ModifyTableState *mtstate,
319318
* these values, error out.
320319
*/
321320
if (partdesc->nparts==0||
322-
(partidx=get_partition_for_tuple(dispatch->key,
323-
dispatch->partdesc,
324-
values,isnull))<0)
321+
(partidx=get_partition_for_tuple(dispatch,values,isnull))<0)
325322
{
326323
char*val_desc;
327324

@@ -1344,12 +1341,12 @@ FormPartitionKeyDatum(PartitionDispatch pd,
13441341
* found or -1 if none found.
13451342
*/
13461343
staticint
1347-
get_partition_for_tuple(PartitionKeykey,
1348-
PartitionDescpartdesc,
1349-
Datum*values,bool*isnull)
1344+
get_partition_for_tuple(PartitionDispatchpd,Datum*values,bool*isnull)
13501345
{
13511346
intbound_offset;
13521347
intpart_index=-1;
1348+
PartitionKeykey=pd->key;
1349+
PartitionDescpartdesc=pd->partdesc;
13531350
PartitionBoundInfoboundinfo=partdesc->boundinfo;
13541351

13551352
/* Route as appropriate based on partitioning strategy. */
@@ -1441,165 +1438,6 @@ get_partition_for_tuple(PartitionKey key,
14411438
returnpart_index;
14421439
}
14431440

1444-
/*
1445-
* ExecGetLeafPartitionForKey
1446-
*Finds the leaf partition of partitioned table 'root_rel' that would
1447-
*contain the specified key tuple.
1448-
*
1449-
* A subset of the table's columns (including all of the partition key columns)
1450-
* must be specified:
1451-
* - 'key_natts' indicats the number of columns contained in the key
1452-
* - 'key_attnums' indicates their attribute numbers as defined in 'root_rel'
1453-
* - 'key_vals' and 'key_nulls' specify the key tuple
1454-
*
1455-
* Returns the leaf partition, locked with the given lockmode, or NULL if
1456-
* there isn't one. Caller is responsibly for closing it. All intermediate
1457-
* partitions are also locked with the same lockmode. Caller must have locked
1458-
* the root already.
1459-
*
1460-
* In addition, the OID of the index of a unique constraint on the root table
1461-
* must be given as 'root_idxoid'; *leaf_idxoid will be set to the OID of the
1462-
* corresponding index on the returned leaf partition. (This can be used by
1463-
* caller to search for a tuple matching the key in the leaf partition.)
1464-
*
1465-
* This works because the unique key defined on the root relation is required
1466-
* to contain the partition key columns of all of the ancestors that lead up to
1467-
* a given leaf partition.
1468-
*/
1469-
Relation
1470-
ExecGetLeafPartitionForKey(Relationroot_rel,intkey_natts,
1471-
constAttrNumber*key_attnums,
1472-
Datum*key_vals,char*key_nulls,
1473-
Oidroot_idxoid,intlockmode,
1474-
Oid*leaf_idxoid)
1475-
{
1476-
Relationfound_leafpart=NULL;
1477-
Relationrel=root_rel;
1478-
Oidconstr_idxoid=root_idxoid;
1479-
PartitionDirectorypartdir;
1480-
1481-
Assert(root_rel->rd_rel->relkind==RELKIND_PARTITIONED_TABLE);
1482-
1483-
*leaf_idxoid=InvalidOid;
1484-
1485-
partdir=CreatePartitionDirectory(CurrentMemoryContext, true);
1486-
1487-
/*
1488-
* Descend through partitioned parents to find the leaf partition that
1489-
* would accept a row with the provided key values, starting with the root
1490-
* parent.
1491-
*/
1492-
for (;;)
1493-
{
1494-
PartitionKeypartkey=RelationGetPartitionKey(rel);
1495-
PartitionDescpartdesc;
1496-
Datumpartkey_vals[PARTITION_MAX_KEYS];
1497-
boolpartkey_isnull[PARTITION_MAX_KEYS];
1498-
AttrNumber*root_partattrs=partkey->partattrs;
1499-
intfound_att;
1500-
intpartidx;
1501-
Oidpartoid;
1502-
1503-
CHECK_FOR_INTERRUPTS();
1504-
1505-
/*
1506-
* Collect partition key values from the unique key.
1507-
*
1508-
* Because we only have the root table's copy of pk_attnums, must map
1509-
* any non-root table's partition key attribute numbers to the root
1510-
* table's.
1511-
*/
1512-
if (rel!=root_rel)
1513-
{
1514-
/*
1515-
* map->attnums will contain root table attribute numbers for each
1516-
* attribute of the current partitioned relation.
1517-
*/
1518-
AttrMap*map;
1519-
1520-
map=build_attrmap_by_name_if_req(RelationGetDescr(root_rel),
1521-
RelationGetDescr(rel));
1522-
if (map)
1523-
{
1524-
root_partattrs=palloc(partkey->partnatts*
1525-
sizeof(AttrNumber));
1526-
for (intatt=0;att<partkey->partnatts;att++)
1527-
{
1528-
AttrNumberpartattno=partkey->partattrs[att];
1529-
1530-
root_partattrs[att]=map->attnums[partattno-1];
1531-
}
1532-
1533-
free_attrmap(map);
1534-
}
1535-
}
1536-
1537-
/*
1538-
* Map the values/isnulls to match the partition description, as
1539-
* necessary.
1540-
*
1541-
* (Referenced key specification does not allow expressions, so there
1542-
* would not be expressions in the partition keys either.)
1543-
*/
1544-
Assert(partkey->partexprs==NIL);
1545-
found_att=0;
1546-
for (intkeyatt=0;keyatt<key_natts;keyatt++)
1547-
{
1548-
for (intatt=0;att<partkey->partnatts;att++)
1549-
{
1550-
if (root_partattrs[att]==key_attnums[keyatt])
1551-
{
1552-
partkey_vals[found_att]=key_vals[keyatt];
1553-
partkey_isnull[found_att]= (key_nulls[keyatt]=='n');
1554-
found_att++;
1555-
break;
1556-
}
1557-
}
1558-
}
1559-
/* We had better have found values for all partition keys */
1560-
Assert(found_att==partkey->partnatts);
1561-
1562-
if (root_partattrs!=partkey->partattrs)
1563-
pfree(root_partattrs);
1564-
1565-
/* Get the PartitionDesc using the partition directory machinery. */
1566-
partdesc=PartitionDirectoryLookup(partdir,rel);
1567-
if (partdesc->nparts==0)
1568-
break;
1569-
1570-
/* Find the partition for the key. */
1571-
partidx=get_partition_for_tuple(partkey,partdesc,
1572-
partkey_vals,partkey_isnull);
1573-
Assert(partidx<0||partidx<partdesc->nparts);
1574-
1575-
/* close the previous parent if any, but keep lock */
1576-
if (rel!=root_rel)
1577-
table_close(rel,NoLock);
1578-
1579-
/* No partition found. */
1580-
if (partidx<0)
1581-
break;
1582-
1583-
partoid=partdesc->oids[partidx];
1584-
rel=table_open(partoid,lockmode);
1585-
constr_idxoid=index_get_partition(rel,constr_idxoid);
1586-
1587-
/*
1588-
* We're done if the partition is a leaf, else find its partition in
1589-
* the next iteration.
1590-
*/
1591-
if (partdesc->is_leaf[partidx])
1592-
{
1593-
*leaf_idxoid=constr_idxoid;
1594-
found_leafpart=rel;
1595-
break;
1596-
}
1597-
}
1598-
1599-
DestroyPartitionDirectory(partdir);
1600-
returnfound_leafpart;
1601-
}
1602-
16031441
/*
16041442
* ExecBuildSlotPartitionKeyDescription
16051443
*

‎src/backend/executor/nodeLockRows.c

Lines changed: 71 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ ExecLockRows(PlanState *pstate)
7979
Datumdatum;
8080
boolisNull;
8181
ItemPointerDatatid;
82+
TM_FailureDatatmfd;
8283
LockTupleModelockmode;
84+
intlockflags=0;
85+
TM_Resulttest;
8386
TupleTableSlot*markSlot;
8487

8588
/* clear any leftover test tuple for this rel */
@@ -176,11 +179,74 @@ ExecLockRows(PlanState *pstate)
176179
break;
177180
}
178181

179-
/* skip tuple if it couldn't be locked */
180-
if (!ExecLockTableTuple(erm->relation,&tid,markSlot,
181-
estate->es_snapshot,estate->es_output_cid,
182-
lockmode,erm->waitPolicy,&epq_needed))
183-
gotolnext;
182+
lockflags=TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS;
183+
if (!IsolationUsesXactSnapshot())
184+
lockflags |=TUPLE_LOCK_FLAG_FIND_LAST_VERSION;
185+
186+
test=table_tuple_lock(erm->relation,&tid,estate->es_snapshot,
187+
markSlot,estate->es_output_cid,
188+
lockmode,erm->waitPolicy,
189+
lockflags,
190+
&tmfd);
191+
192+
switch (test)
193+
{
194+
caseTM_WouldBlock:
195+
/* couldn't lock tuple in SKIP LOCKED mode */
196+
gotolnext;
197+
198+
caseTM_SelfModified:
199+
200+
/*
201+
* The target tuple was already updated or deleted by the
202+
* current command, or by a later command in the current
203+
* transaction. We *must* ignore the tuple in the former
204+
* case, so as to avoid the "Halloween problem" of repeated
205+
* update attempts. In the latter case it might be sensible
206+
* to fetch the updated tuple instead, but doing so would
207+
* require changing heap_update and heap_delete to not
208+
* complain about updating "invisible" tuples, which seems
209+
* pretty scary (table_tuple_lock will not complain, but few
210+
* callers expect TM_Invisible, and we're not one of them). So
211+
* for now, treat the tuple as deleted and do not process.
212+
*/
213+
gotolnext;
214+
215+
caseTM_Ok:
216+
217+
/*
218+
* Got the lock successfully, the locked tuple saved in
219+
* markSlot for, if needed, EvalPlanQual testing below.
220+
*/
221+
if (tmfd.traversed)
222+
epq_needed= true;
223+
break;
224+
225+
caseTM_Updated:
226+
if (IsolationUsesXactSnapshot())
227+
ereport(ERROR,
228+
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
229+
errmsg("could not serialize access due to concurrent update")));
230+
elog(ERROR,"unexpected table_tuple_lock status: %u",
231+
test);
232+
break;
233+
234+
caseTM_Deleted:
235+
if (IsolationUsesXactSnapshot())
236+
ereport(ERROR,
237+
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
238+
errmsg("could not serialize access due to concurrent update")));
239+
/* tuple was deleted so don't return it */
240+
gotolnext;
241+
242+
caseTM_Invisible:
243+
elog(ERROR,"attempted to lock invisible tuple");
244+
break;
245+
246+
default:
247+
elog(ERROR,"unrecognized table_tuple_lock status: %u",
248+
test);
249+
}
184250

185251
/* Remember locked tuple's TID for EPQ testing and WHERE CURRENT OF */
186252
erm->curCtid=tid;
@@ -215,91 +281,6 @@ ExecLockRows(PlanState *pstate)
215281
returnslot;
216282
}
217283

218-
/*
219-
* ExecLockTableTuple
220-
* Locks tuple with the specified TID in lockmode following given wait
221-
* policy
222-
*
223-
* Returns true if the tuple was successfully locked. Locked tuple is loaded
224-
* into provided slot.
225-
*/
226-
bool
227-
ExecLockTableTuple(Relationrelation,ItemPointertid,TupleTableSlot*slot,
228-
Snapshotsnapshot,CommandIdcid,
229-
LockTupleModelockmode,LockWaitPolicywaitPolicy,
230-
bool*epq_needed)
231-
{
232-
TM_FailureDatatmfd;
233-
intlockflags=TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS;
234-
TM_Resulttest;
235-
236-
if (!IsolationUsesXactSnapshot())
237-
lockflags |=TUPLE_LOCK_FLAG_FIND_LAST_VERSION;
238-
239-
test=table_tuple_lock(relation,tid,snapshot,slot,cid,lockmode,
240-
waitPolicy,lockflags,&tmfd);
241-
242-
switch (test)
243-
{
244-
caseTM_WouldBlock:
245-
/* couldn't lock tuple in SKIP LOCKED mode */
246-
return false;
247-
248-
caseTM_SelfModified:
249-
250-
/*
251-
* The target tuple was already updated or deleted by the current
252-
* command, or by a later command in the current transaction. We
253-
* *must* ignore the tuple in the former case, so as to avoid the
254-
* "Halloween problem" of repeated update attempts. In the latter
255-
* case it might be sensible to fetch the updated tuple instead,
256-
* but doing so would require changing heap_update and heap_delete
257-
* to not complain about updating "invisible" tuples, which seems
258-
* pretty scary (table_tuple_lock will not complain, but few
259-
* callers expect TM_Invisible, and we're not one of them). So for
260-
* now, treat the tuple as deleted and do not process.
261-
*/
262-
return false;
263-
264-
caseTM_Ok:
265-
266-
/*
267-
* Got the lock successfully, the locked tuple saved in slot for
268-
* EvalPlanQual, if asked by the caller.
269-
*/
270-
if (tmfd.traversed&&epq_needed)
271-
*epq_needed= true;
272-
break;
273-
274-
caseTM_Updated:
275-
if (IsolationUsesXactSnapshot())
276-
ereport(ERROR,
277-
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
278-
errmsg("could not serialize access due to concurrent update")));
279-
elog(ERROR,"unexpected table_tuple_lock status: %u",
280-
test);
281-
break;
282-
283-
caseTM_Deleted:
284-
if (IsolationUsesXactSnapshot())
285-
ereport(ERROR,
286-
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
287-
errmsg("could not serialize access due to concurrent update")));
288-
/* tuple was deleted so don't return it */
289-
return false;
290-
291-
caseTM_Invisible:
292-
elog(ERROR,"attempted to lock invisible tuple");
293-
return false;
294-
295-
default:
296-
elog(ERROR,"unrecognized table_tuple_lock status: %u",test);
297-
return false;
298-
}
299-
300-
return true;
301-
}
302-
303284
/* ----------------------------------------------------------------
304285
*ExecInitLockRows
305286
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp