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

Commit137c068

Browse files
committed
Support more restricted predicate in ALTER INDEX clause
1 parentce6c567 commit137c068

File tree

1 file changed

+92
-59
lines changed

1 file changed

+92
-59
lines changed

‎src/backend/commands/indexcmds.c‎

Lines changed: 92 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,30 @@ CheckIndexCompatible(Oid oldId,
279279
returnret;
280280
}
281281

282+
staticvoid
283+
UpdateIndex(OidindexRelationId,Node*whereClause)
284+
{
285+
Datumvalues[Natts_pg_index];
286+
boolisnull[Natts_pg_index];
287+
HeapTupleoldTuple;
288+
HeapTuplenewTuple;
289+
Relationpg_index;
290+
291+
pg_index=heap_open(IndexRelationId,RowExclusiveLock);
292+
oldTuple=SearchSysCacheCopy1(INDEXRELID,ObjectIdGetDatum(indexRelationId));
293+
if (!HeapTupleIsValid(oldTuple))
294+
elog(ERROR,"cache lookup failed for index %u",indexRelationId);
295+
296+
heap_deform_tuple(oldTuple,RelationGetDescr(pg_index),values,isnull);
297+
values[Anum_pg_index_indpred-1]=CStringGetTextDatum(nodeToString(whereClause));
298+
newTuple=heap_form_tuple(RelationGetDescr(pg_index),values,isnull);
299+
simple_heap_update(pg_index,&oldTuple->t_self,newTuple);
300+
CatalogUpdateIndexes(pg_index,newTuple);
301+
heap_freetuple(newTuple);
302+
heap_freetuple(oldTuple);
303+
heap_close(pg_index,NoLock);
304+
}
305+
282306
void
283307
AlterIndex(OidindexRelationId,IndexStmt*stmt)
284308
{
@@ -292,14 +316,15 @@ AlterIndex(Oid indexRelationId, IndexStmt *stmt)
292316
SPIPlanPtrplan;
293317
Portalportal;
294318
HeapTupletuple;
295-
HeapTupleupdatedTuple;
296319
TupleTableSlot*slot;
297320
ItemPointertupleid;
298321
IndexInfo*indexInfo;
299322
EState*estate;
300323
OidnamespaceId;
301-
Relationpg_index;
302324
List*deparseCtx;
325+
char*oldIndexPredicate;
326+
char*newIndexPredicate;
327+
char*relationName;
303328

304329
Assert(stmt->whereClause);
305330
CheckPredicate((Expr*)stmt->whereClause);
@@ -314,8 +339,6 @@ AlterIndex(Oid indexRelationId, IndexStmt *stmt)
314339
/* indexRelation = index_open(indexRelationId, AccessShareLock); */
315340
namespaceId=RelationGetNamespace(indexRelation);
316341

317-
pg_index=heap_open(IndexRelationId,RowExclusiveLock);
318-
319342
indexInfo=BuildIndexInfo(indexRelation);
320343
Assert(indexInfo->ii_Predicate);
321344
Assert(!indexInfo->ii_ExclusionOps);
@@ -327,75 +350,85 @@ AlterIndex(Oid indexRelationId, IndexStmt *stmt)
327350

328351
checkUnique=indexRelation->rd_index->indisunique ?UNIQUE_CHECK_YES :UNIQUE_CHECK_NO;
329352

330-
/* Update pg_index tuple */
331-
tuple=SearchSysCacheCopy1(INDEXRELID,ObjectIdGetDatum(indexRelationId));
332-
if (!HeapTupleIsValid(tuple))
333-
elog(ERROR,"cache lookup failed for index %u",indexRelationId);
334-
335-
Assert(Natts_pg_index <=INDEX_MAX_KEYS);
336-
heap_deform_tuple(tuple,RelationGetDescr(pg_index),values,isnull);
337-
values[Anum_pg_index_indpred-1]=CStringGetTextDatum(nodeToString(stmt->whereClause));
338-
updatedTuple=heap_form_tuple(RelationGetDescr(pg_index),values,isnull);
339-
simple_heap_update(pg_index,&tuple->t_self,updatedTuple);
340-
CatalogUpdateIndexes(pg_index,updatedTuple);
341-
heap_freetuple(updatedTuple);
342-
heap_freetuple(tuple);
343-
heap_close(pg_index,NoLock);
344-
345353
slot=MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
354+
355+
deparseCtx=deparse_context_for(RelationGetRelationName(heapRelation),heapRelationId);
356+
relationName=quote_qualified_identifier(get_namespace_name(namespaceId),
357+
get_rel_name(heapRelationId)),
358+
newIndexPredicate=deparse_expression(stmt->whereClause,deparseCtx, false, false);
359+
oldIndexPredicate=deparse_expression((Node*)make_ands_explicit(indexInfo->ii_Predicate),deparseCtx, false, false);
346360

347361
SPI_connect();
348-
deparseCtx=deparse_context_for(RelationGetRelationName(heapRelation),heapRelationId);
349-
select=psprintf("select * from %s where %s and not (%s)",
350-
quote_qualified_identifier(get_namespace_name(namespaceId),
351-
get_rel_name(heapRelationId)),
352-
deparse_expression(stmt->whereClause,deparseCtx, false, false),
353-
deparse_expression((Node*)make_ands_explicit(indexInfo->ii_Predicate),deparseCtx, false, false));
354-
plan=SPI_prepare(select,0,NULL);
355-
if (plan==NULL) {
356-
ereport(ERROR,
357-
(errcode(ERRCODE_INVALID_CURSOR_STATE),
358-
errmsg("Failed to preapre statement %s",select)));
359-
}
360-
portal=SPI_cursor_open(NULL,plan,NULL,NULL, true);
361-
if (portal==NULL) {
362+
363+
select=psprintf("select * from %s where %s and not (%s) limit 1",
364+
relationName,oldIndexPredicate,newIndexPredicate);
365+
if (SPI_execute(select, true,1)!=SPI_OK_SELECT)
366+
{
362367
ereport(ERROR,
363368
(errcode(ERRCODE_INVALID_CURSOR_STATE),
364-
errmsg("Failed toopen cursor for%s",select)));
369+
errmsg("Failed toexecute statement%s",select)));
365370
}
366-
while (true)
367-
{
368-
SPI_cursor_fetch(portal, true,1);
369-
if (!SPI_processed) {
370-
break;
371-
}
372-
tuple=SPI_tuptable->vals[0];
373-
tupleid=&tuple->t_data->t_ctid;
374-
ExecStoreTuple(tuple,slot,InvalidBuffer, false);
371+
if (SPI_processed) {
372+
/* There is no way in Postgres to exclude records from index, so we have to completelty rebuild index in this case */
373+
boolrelpersistence=indexRelation->rd_rel->relpersistence;
374+
index_close(indexRelation,NoLock);
375+
indexRelation->rd_indpred=make_ands_implicit((Expr*)stmt->whereClause);
376+
indexRelation=NULL;
377+
UpdateIndex(indexRelationId,stmt->whereClause);
378+
reindex_index(indexRelationId, false,relpersistence,0);
379+
}else {
380+
select=psprintf("select * from %s where %s and not (%s)",
381+
relationName,newIndexPredicate,oldIndexPredicate);
382+
plan=SPI_prepare(select,0,NULL);
383+
if (plan==NULL) {
384+
ereport(ERROR,
385+
(errcode(ERRCODE_INVALID_CURSOR_STATE),
386+
errmsg("Failed to preapre statement %s",select)));
387+
}
388+
portal=SPI_cursor_open(NULL,plan,NULL,NULL, true);
389+
if (portal==NULL) {
390+
ereport(ERROR,
391+
(errcode(ERRCODE_INVALID_CURSOR_STATE),
392+
errmsg("Failed to open cursor for %s",select)));
393+
}
394+
while (true)
395+
{
396+
SPI_cursor_fetch(portal, true,1);
397+
if (!SPI_processed) {
398+
break;
399+
}
400+
tuple=SPI_tuptable->vals[0];
401+
tupleid=&tuple->t_data->t_ctid;
402+
ExecStoreTuple(tuple,slot,InvalidBuffer, false);
403+
404+
FormIndexDatum(indexInfo,
405+
slot,
406+
estate,
407+
values,
408+
isnull);
409+
index_insert(indexRelation,/* index relation */
410+
values,/* array of index Datums */
411+
isnull,/* null flags */
412+
tupleid,/* tid of heap tuple */
413+
heapRelation,/* heap relation */
414+
checkUnique);/* type of uniqueness check to do */
375415

376-
FormIndexDatum(indexInfo,
377-
slot,
378-
estate,
379-
values,
380-
isnull);
381-
index_insert(indexRelation,/* index relation */
382-
values,/* array of index Datums */
383-
isnull,/* null flags */
384-
tupleid,/* tid of heap tuple */
385-
heapRelation,/* heap relation */
386-
checkUnique);/* type of uniqueness check to do */
387-
388-
SPI_freetuple(tuple);
389-
SPI_freetuptable(SPI_tuptable);
416+
SPI_freetuple(tuple);
417+
SPI_freetuptable(SPI_tuptable);
418+
}
419+
SPI_cursor_close(portal);
420+
421+
UpdateIndex(indexRelationId,stmt->whereClause);
390422
}
391-
SPI_cursor_close(portal);
392423
SPI_finish();
393424

394425
ExecDropSingleTupleTableSlot(slot);
395426
FreeExecutorState(estate);
396427

397428
heap_close(heapRelation,NoLock);
398-
index_close(indexRelation,NoLock);
429+
if (indexRelation) {
430+
index_close(indexRelation,NoLock);
431+
}
399432
}
400433

401434
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp