34
34
#include "commands/tablespace.h"
35
35
#include "mb/pg_wchar.h"
36
36
#include "miscadmin.h"
37
+ #include "funcapi.h"
37
38
#include "nodes/nodeFuncs.h"
38
39
#include "optimizer/clauses.h"
39
40
#include "optimizer/planner.h"
52
53
#include "utils/snapmgr.h"
53
54
#include "utils/syscache.h"
54
55
#include "utils/tqual.h"
56
+ #include "utils/ruleutils.h"
57
+ #include "executor/executor.h"
58
+ #include "executor/spi.h"
55
59
56
60
57
61
/* non-export function prototypes */
@@ -280,33 +284,40 @@ CheckIndexCompatible(Oid oldId,
280
284
return ret ;
281
285
}
282
286
283
- #if 0
284
287
void
285
- AlterIndex (Oid relationId , IndexStmt * stmt , Oid indexRelationId )
288
+ AlterIndex (Oid indexRelationId , IndexStmt * stmt )
286
289
{
287
290
char * select ;
291
+ Oid heapRelationId ;
288
292
IndexUniqueCheck checkUnique ;
289
- bool satisfiesConstraint ;
290
293
Datum values [INDEX_MAX_KEYS ];
291
294
bool isnull [INDEX_MAX_KEYS ];
292
295
Relation heapRelation ;
293
296
Relation indexRelation ;
294
297
SPIPlanPtr plan ;
295
298
Portal portal ;
296
299
HeapTuple tuple ;
297
- TupleDesc tupdesc ;
300
+ HeapTuple updatedTuple ;
298
301
TupleTableSlot * slot ;
299
302
ItemPointer tupleid ;
300
303
IndexInfo * indexInfo ;
301
304
EState * estate ;
305
+ Oid namespaceId ;
306
+ Relation pg_index ;
307
+ List * deparseCtx ;
302
308
303
309
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 );
304
315
305
316
/* 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 );
307
319
308
- /* And the target index relation */
309
- indexRelation = index_open (indexRelationId , RowExclusiveLock );
320
+ pg_index = heap_open (IndexRelationId , RowExclusiveLock );
310
321
311
322
indexInfo = BuildIndexInfo (indexRelation );
312
323
Assert (indexInfo -> ii_Predicate );
@@ -319,58 +330,40 @@ AlterIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId)
319
330
320
331
checkUnique = indexRelation -> rd_index -> indisunique ? UNIQUE_CHECK_YES : UNIQUE_CHECK_NO ;
321
332
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 );
351
337
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 );
355
346
347
+ slot = MakeSingleTupleTableSlot (RelationGetDescr (heapRelation ));
356
348
349
+ SPI_connect ();
350
+ deparseCtx = deparse_context_for (RelationGetRelationName (heapRelation ), heapRelationId );
357
351
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 );
364
357
if (plan == NULL ) {
365
358
ereport (ERROR ,
366
359
(errcode (ERRCODE_INVALID_CURSOR_STATE ),
367
- errmsg ("Failed to preapre statement " , select )));
360
+ errmsg ("Failed to preapre statement %s " , select )));
368
361
}
369
362
portal = SPI_cursor_open (NULL , plan , NULL , NULL , true);
370
363
if (portal == NULL ) {
371
364
ereport (ERROR ,
372
365
(errcode (ERRCODE_INVALID_CURSOR_STATE ),
373
- errmsg ("Failed to open cursor for " , select )));
366
+ errmsg ("Failed to open cursor for %s " , select )));
374
367
}
375
368
while (true)
376
369
{
@@ -379,40 +372,34 @@ AlterIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId)
379
372
break ;
380
373
}
381
374
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);
385
377
386
378
FormIndexDatum (indexInfo ,
387
379
slot ,
388
380
estate ,
389
381
values ,
390
382
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
+
405
390
SPI_freetuple (tuple );
406
391
SPI_freetuptable (SPI_tuptable );
407
392
}
408
393
SPI_cursor_close (portal );
409
394
SPI_finish ();
410
395
411
- /* Close both the relations, but keep the locks */
396
+ ExecDropSingleTupleTableSlot (slot );
397
+ FreeExecutorState (estate );
398
+
399
+ heap_close (pg_index , NoLock );
412
400
heap_close (heapRelation , NoLock );
413
401
index_close (indexRelation , NoLock );
414
402
}
415
- #endif
416
403
417
404
/*
418
405
* DefineIndex
0 commit comments