3232#include "commands/tablespace.h"
3333#include "mb/pg_wchar.h"
3434#include "miscadmin.h"
35+ #include "funcapi.h"
3536#include "nodes/nodeFuncs.h"
3637#include "optimizer/clauses.h"
3738#include "optimizer/planner.h"
5051#include "utils/snapmgr.h"
5152#include "utils/syscache.h"
5253#include "utils/tqual.h"
54+ #include "utils/ruleutils.h"
55+ #include "executor/executor.h"
56+ #include "executor/spi.h"
5357
5458
5559/* non-export function prototypes */
@@ -275,33 +279,40 @@ CheckIndexCompatible(Oid oldId,
275279 return ret ;
276280}
277281
278- #if 0
279282void
280- AlterIndex (Oid relationId , IndexStmt * stmt , Oid indexRelationId )
283+ AlterIndex (Oid indexRelationId , IndexStmt * stmt )
281284{
282285 char * select ;
286+ Oid heapRelationId ;
283287 IndexUniqueCheck checkUnique ;
284- bool satisfiesConstraint ;
285288 Datum values [INDEX_MAX_KEYS ];
286289 bool isnull [INDEX_MAX_KEYS ];
287290 Relation heapRelation ;
288291 Relation indexRelation ;
289292 SPIPlanPtr plan ;
290293 Portal portal ;
291294 HeapTuple tuple ;
292- TupleDesc tupdesc ;
295+ HeapTuple updatedTuple ;
293296 TupleTableSlot * slot ;
294297 ItemPointer tupleid ;
295298 IndexInfo * indexInfo ;
296299 EState * estate ;
300+ Oid namespaceId ;
301+ Relation pg_index ;
302+ List * deparseCtx ;
297303
298304 Assert (stmt -> whereClause );
305+ CheckPredicate ((Expr * ) stmt -> whereClause );
306+
307+ /* Open the target index relation */
308+ indexRelation = index_open (indexRelationId , RowExclusiveLock );
309+ namespaceId = RelationGetNamespace (indexRelation );
299310
300311 /* Open and lock the parent heap relation */
301- heapRelation = heap_openrv (stmt -> relation , ShareUpdateExclusiveLock );
312+ heapRelationId = IndexGetRelation (indexRelationId , false);
313+ heapRelation = heap_open (heapRelationId , ShareLock );
302314
303- /* And the target index relation */
304- indexRelation = index_open (indexRelationId , RowExclusiveLock );
315+ pg_index = heap_open (IndexRelationId , RowExclusiveLock );
305316
306317 indexInfo = BuildIndexInfo (indexRelation );
307318 Assert (indexInfo -> ii_Predicate );
@@ -314,58 +325,40 @@ AlterIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId)
314325
315326 checkUnique = indexRelation -> rd_index -> indisunique ? UNIQUE_CHECK_YES : UNIQUE_CHECK_NO ;
316327
317- SPI_connect ();
318- select = psprintf ("select * from %s where %s and not (%s)" ,
319- quote_qualified_identifier (get_namespace_name (RelationGetNamespace (heapRelation )),
320- get_rel_name (relationId )),
321- nodeToString (indexInfo -> ii_Predicate ),
322- nodeToString (stmt -> whereClause )
323- );
324- plan = SPI_parepare (select , 0 , NULL );
325- if (plan == NULL ) {
326- ereport (ERROR ,
327- (errcode (ERRCODE_INVALID_CURSOR_STATE ),
328- errmsg ("Failed to preapre statement " , select )));
329- }
330- portal = SPI_cursor_open (NULL , plan , NULL , NULL , true);
331- if (portal == NULL ) {
332- ereport (ERROR ,
333- (errcode (ERRCODE_INVALID_CURSOR_STATE ),
334- errmsg ("Failed to open cursor for " , select )));
335- }
336- while (true)
337- {
338- SPI_cursor_fetch (portal , true, 1 );
339- if (!SPI_processed ) {
340- break ;
341- }
342- tuple = SPI_tuptable -> vals [0 ];
343- tupdesc = SPI_tuptable -> tupdesc ;
344- slot = TupleDescGetSlot (tupdesc );
345- tupleid = & tuple -> t_datat -> t_ctid ;
328+ /* Update pg_index tuple */
329+ tuple = SearchSysCacheCopy1 (INDEXRELID , ObjectIdGetDatum (indexRelationId ));
330+ if (!HeapTupleIsValid (tuple ))
331+ elog (ERROR , "cache lookup failed for index %u" , indexRelationId );
346332
347- /* delete tuple from index */
348- }
349- SPI_cursor_close (portal );
333+ Assert (Natts_pg_index <= INDEX_MAX_KEYS );
334+ heap_deform_tuple (tuple , RelationGetDescr (pg_index ), values , isnull );
335+ values [Anum_pg_index_indpred - 1 ] = CStringGetTextDatum (nodeToString (stmt -> whereClause ));
336+ updatedTuple = heap_form_tuple (RelationGetDescr (pg_index ), values , isnull );
337+ simple_heap_update (pg_index , & tuple -> t_self , updatedTuple );
338+ CatalogUpdateIndexes (pg_index , updatedTuple );
339+ heap_freetuple (updatedTuple );
340+ heap_freetuple (tuple );
350341
342+ slot = MakeSingleTupleTableSlot (RelationGetDescr (heapRelation ));
351343
344+ SPI_connect ();
345+ deparseCtx = deparse_context_for (RelationGetRelationName (heapRelation ), heapRelationId );
352346 select = psprintf ("select * from %s where %s and not (%s)" ,
353- quote_qualified_identifier (get_namespace_name (RelationGetNamespace (heapRelation )),
354- get_rel_name (relationId )),
355- nodeToString (stmt -> whereClause ),
356- nodeToString (indexInfo -> ii_Predicate )
357- );
358- plan = SPI_parepare (select , 0 , NULL );
347+ quote_qualified_identifier (get_namespace_name (namespaceId ),
348+ get_rel_name (heapRelationId )),
349+ deparse_expression (stmt -> whereClause , deparseCtx , false, false),
350+ deparse_expression ((Node * )make_ands_explicit (indexInfo -> ii_Predicate ), deparseCtx , false, false));
351+ plan = SPI_prepare (select , 0 , NULL );
359352 if (plan == NULL ) {
360353 ereport (ERROR ,
361354 (errcode (ERRCODE_INVALID_CURSOR_STATE ),
362- errmsg ("Failed to preapre statement " , select )));
355+ errmsg ("Failed to preapre statement %s " , select )));
363356 }
364357 portal = SPI_cursor_open (NULL , plan , NULL , NULL , true);
365358 if (portal == NULL ) {
366359 ereport (ERROR ,
367360 (errcode (ERRCODE_INVALID_CURSOR_STATE ),
368- errmsg ("Failed to open cursor for " , select )));
361+ errmsg ("Failed to open cursor for %s " , select )));
369362 }
370363 while (true)
371364 {
@@ -374,40 +367,34 @@ AlterIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId)
374367 break ;
375368 }
376369 tuple = SPI_tuptable -> vals [0 ];
377- tupdesc = SPI_tuptable -> tupdesc ;
378- slot = TupleDescGetSlot (tupdesc );
379- tupleid = & tuple -> t_datat -> t_ctid ;
370+ tupleid = & tuple -> t_data -> t_ctid ;
371+ ExecStoreTuple (tuple , slot , InvalidBuffer , false);
380372
381373 FormIndexDatum (indexInfo ,
382374 slot ,
383375 estate ,
384376 values ,
385377 isnull );
386- satisfiesConstraint =
387- index_insert (indexRelation , /* index relation */
388- values , /* array of index Datums */
389- isnull , /* null flags */
390- tupleid , /* tid of heap tuple */
391- heapRelation , /* heap relation */
392- checkUnique ); /* type of uniqueness check to do */
393-
394- if (!satisfiesConstraint )
395- {
396- ereport (ERROR ,
397- (errcode (ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION ),
398- errmsg ("Index constraint violation" )));
399- }
378+ index_insert (indexRelation , /* index relation */
379+ values , /* array of index Datums */
380+ isnull , /* null flags */
381+ tupleid , /* tid of heap tuple */
382+ heapRelation , /* heap relation */
383+ checkUnique ); /* type of uniqueness check to do */
384+
400385 SPI_freetuple (tuple );
401386 SPI_freetuptable (SPI_tuptable );
402387 }
403388 SPI_cursor_close (portal );
404389 SPI_finish ();
405390
406- /* Close both the relations, but keep the locks */
391+ ExecDropSingleTupleTableSlot (slot );
392+ FreeExecutorState (estate );
393+
394+ heap_close (pg_index , NoLock );
407395 heap_close (heapRelation , NoLock );
408396 index_close (indexRelation , NoLock );
409397}
410- #endif
411398
412399/*
413400 * DefineIndex
0 commit comments