3434#include "commands/tablespace.h"
3535#include "mb/pg_wchar.h"
3636#include "miscadmin.h"
37+ #include "funcapi.h"
3738#include "nodes/nodeFuncs.h"
3839#include "optimizer/clauses.h"
3940#include "optimizer/planner.h"
5253#include "utils/snapmgr.h"
5354#include "utils/syscache.h"
5455#include "utils/tqual.h"
56+ #include "utils/ruleutils.h"
57+ #include "executor/executor.h"
58+ #include "executor/spi.h"
5559
5660
5761/* non-export function prototypes */
@@ -280,33 +284,40 @@ CheckIndexCompatible(Oid oldId,
280284 return ret ;
281285}
282286
283- #if 0
284287void
285- AlterIndex (Oid relationId , IndexStmt * stmt , Oid indexRelationId )
288+ AlterIndex (Oid indexRelationId , IndexStmt * stmt )
286289{
287290 char * select ;
291+ Oid heapRelationId ;
288292 IndexUniqueCheck checkUnique ;
289- bool satisfiesConstraint ;
290293 Datum values [INDEX_MAX_KEYS ];
291294 bool isnull [INDEX_MAX_KEYS ];
292295 Relation heapRelation ;
293296 Relation indexRelation ;
294297 SPIPlanPtr plan ;
295298 Portal portal ;
296299 HeapTuple tuple ;
297- TupleDesc tupdesc ;
300+ HeapTuple updatedTuple ;
298301 TupleTableSlot * slot ;
299302 ItemPointer tupleid ;
300303 IndexInfo * indexInfo ;
301304 EState * estate ;
305+ Oid namespaceId ;
306+ Relation pg_index ;
307+ List * deparseCtx ;
302308
303309 Assert (stmt -> whereClause );
310+ CheckPredicate ((Expr * ) stmt -> whereClause );
311+
312+ /* Open the target index relation */
313+ indexRelation = index_open (indexRelationId , RowExclusiveLock );
314+ namespaceId = RelationGetNamespace (indexRelation );
304315
305316 /* Open and lock the parent heap relation */
306- heapRelation = heap_openrv (stmt -> relation , ShareUpdateExclusiveLock );
317+ heapRelationId = IndexGetRelation (indexRelationId , false);
318+ heapRelation = heap_open (heapRelationId , ShareLock );
307319
308- /* And the target index relation */
309- indexRelation = index_open (indexRelationId , RowExclusiveLock );
320+ pg_index = heap_open (IndexRelationId , RowExclusiveLock );
310321
311322 indexInfo = BuildIndexInfo (indexRelation );
312323 Assert (indexInfo -> ii_Predicate );
@@ -319,58 +330,40 @@ AlterIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId)
319330
320331 checkUnique = indexRelation -> rd_index -> indisunique ? UNIQUE_CHECK_YES : UNIQUE_CHECK_NO ;
321332
322- SPI_connect ();
323- select = psprintf ("select * from %s where %s and not (%s)" ,
324- quote_qualified_identifier (get_namespace_name (RelationGetNamespace (heapRelation )),
325- get_rel_name (relationId )),
326- nodeToString (indexInfo -> ii_Predicate ),
327- nodeToString (stmt -> whereClause )
328- );
329- plan = SPI_parepare (select , 0 , NULL );
330- if (plan == NULL ) {
331- ereport (ERROR ,
332- (errcode (ERRCODE_INVALID_CURSOR_STATE ),
333- errmsg ("Failed to preapre statement " , select )));
334- }
335- portal = SPI_cursor_open (NULL , plan , NULL , NULL , true);
336- if (portal == NULL ) {
337- ereport (ERROR ,
338- (errcode (ERRCODE_INVALID_CURSOR_STATE ),
339- errmsg ("Failed to open cursor for " , select )));
340- }
341- while (true)
342- {
343- SPI_cursor_fetch (portal , true, 1 );
344- if (!SPI_processed ) {
345- break ;
346- }
347- tuple = SPI_tuptable -> vals [0 ];
348- tupdesc = SPI_tuptable -> tupdesc ;
349- slot = TupleDescGetSlot (tupdesc );
350- tupleid = & tuple -> t_datat -> t_ctid ;
333+ /* Update pg_index tuple */
334+ tuple = SearchSysCacheCopy1 (INDEXRELID , ObjectIdGetDatum (indexRelationId ));
335+ if (!HeapTupleIsValid (tuple ))
336+ elog (ERROR , "cache lookup failed for index %u" , indexRelationId );
351337
352- /* delete tuple from index */
353- }
354- SPI_cursor_close (portal );
338+ Assert (Natts_pg_index <= INDEX_MAX_KEYS );
339+ heap_deform_tuple (tuple , RelationGetDescr (pg_index ), values , isnull );
340+ values [Anum_pg_index_indpred - 1 ] = CStringGetTextDatum (nodeToString (stmt -> whereClause ));
341+ updatedTuple = heap_form_tuple (RelationGetDescr (pg_index ), values , isnull );
342+ simple_heap_update (pg_index , & tuple -> t_self , updatedTuple );
343+ CatalogUpdateIndexes (pg_index , updatedTuple );
344+ heap_freetuple (updatedTuple );
345+ heap_freetuple (tuple );
355346
347+ slot = MakeSingleTupleTableSlot (RelationGetDescr (heapRelation ));
356348
349+ SPI_connect ();
350+ deparseCtx = deparse_context_for (RelationGetRelationName (heapRelation ), heapRelationId );
357351 select = psprintf ("select * from %s where %s and not (%s)" ,
358- quote_qualified_identifier (get_namespace_name (RelationGetNamespace (heapRelation )),
359- get_rel_name (relationId )),
360- nodeToString (stmt -> whereClause ),
361- nodeToString (indexInfo -> ii_Predicate )
362- );
363- plan = SPI_parepare (select , 0 , NULL );
352+ quote_qualified_identifier (get_namespace_name (namespaceId ),
353+ get_rel_name (heapRelationId )),
354+ deparse_expression (stmt -> whereClause , deparseCtx , false, false),
355+ deparse_expression ((Node * )make_ands_explicit (indexInfo -> ii_Predicate ), deparseCtx , false, false));
356+ plan = SPI_prepare (select , 0 , NULL );
364357 if (plan == NULL ) {
365358 ereport (ERROR ,
366359 (errcode (ERRCODE_INVALID_CURSOR_STATE ),
367- errmsg ("Failed to preapre statement " , select )));
360+ errmsg ("Failed to preapre statement %s " , select )));
368361 }
369362 portal = SPI_cursor_open (NULL , plan , NULL , NULL , true);
370363 if (portal == NULL ) {
371364 ereport (ERROR ,
372365 (errcode (ERRCODE_INVALID_CURSOR_STATE ),
373- errmsg ("Failed to open cursor for " , select )));
366+ errmsg ("Failed to open cursor for %s " , select )));
374367 }
375368 while (true)
376369 {
@@ -379,40 +372,34 @@ AlterIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId)
379372 break ;
380373 }
381374 tuple = SPI_tuptable -> vals [0 ];
382- tupdesc = SPI_tuptable -> tupdesc ;
383- slot = TupleDescGetSlot (tupdesc );
384- tupleid = & tuple -> t_datat -> t_ctid ;
375+ tupleid = & tuple -> t_data -> t_ctid ;
376+ ExecStoreTuple (tuple , slot , InvalidBuffer , false);
385377
386378 FormIndexDatum (indexInfo ,
387379 slot ,
388380 estate ,
389381 values ,
390382 isnull );
391- satisfiesConstraint =
392- index_insert (indexRelation , /* index relation */
393- values , /* array of index Datums */
394- isnull , /* null flags */
395- tupleid , /* tid of heap tuple */
396- heapRelation , /* heap relation */
397- checkUnique ); /* type of uniqueness check to do */
398-
399- if (!satisfiesConstraint )
400- {
401- ereport (ERROR ,
402- (errcode (ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION ),
403- errmsg ("Index constraint violation" )));
404- }
383+ index_insert (indexRelation , /* index relation */
384+ values , /* array of index Datums */
385+ isnull , /* null flags */
386+ tupleid , /* tid of heap tuple */
387+ heapRelation , /* heap relation */
388+ checkUnique ); /* type of uniqueness check to do */
389+
405390 SPI_freetuple (tuple );
406391 SPI_freetuptable (SPI_tuptable );
407392 }
408393 SPI_cursor_close (portal );
409394 SPI_finish ();
410395
411- /* Close both the relations, but keep the locks */
396+ ExecDropSingleTupleTableSlot (slot );
397+ FreeExecutorState (estate );
398+
399+ heap_close (pg_index , NoLock );
412400 heap_close (heapRelation , NoLock );
413401 index_close (indexRelation , NoLock );
414402}
415- #endif
416403
417404/*
418405 * DefineIndex
0 commit comments