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