|
34 | 34 | #include "commands/tablespace.h" |
35 | 35 | #include "mb/pg_wchar.h" |
36 | 36 | #include "miscadmin.h" |
37 | | -#include "funcapi.h" |
38 | 37 | #include "nodes/nodeFuncs.h" |
39 | 38 | #include "optimizer/clauses.h" |
40 | 39 | #include "optimizer/planner.h" |
|
53 | 52 | #include "utils/snapmgr.h" |
54 | 53 | #include "utils/syscache.h" |
55 | 54 | #include "utils/tqual.h" |
56 | | -#include "utils/ruleutils.h" |
57 | | -#include "executor/executor.h" |
58 | | -#include "executor/spi.h" |
59 | 55 |
|
60 | 56 |
|
61 | 57 | /* non-export function prototypes */ |
@@ -284,160 +280,6 @@ CheckIndexCompatible(Oid oldId, |
284 | 280 | return ret; |
285 | 281 | } |
286 | 282 |
|
287 | | -static void |
288 | | -UpdateIndex(Oid indexRelationId, Node* whereClause) |
289 | | -{ |
290 | | - Datum values[Natts_pg_index]; |
291 | | - bool isnull[Natts_pg_index]; |
292 | | - HeapTuple oldTuple; |
293 | | - HeapTuple newTuple; |
294 | | - Relation pg_index; |
295 | | - |
296 | | - pg_index = heap_open(IndexRelationId, RowExclusiveLock); |
297 | | - oldTuple = SearchSysCacheCopy1(INDEXRELID, ObjectIdGetDatum(indexRelationId)); |
298 | | - if (!HeapTupleIsValid(oldTuple)) |
299 | | - elog(ERROR, "cache lookup failed for index %u", indexRelationId); |
300 | | - |
301 | | - heap_deform_tuple(oldTuple, RelationGetDescr(pg_index), values, isnull); |
302 | | - values[Anum_pg_index_indpred - 1] = CStringGetTextDatum(nodeToString(whereClause)); |
303 | | - isnull[Anum_pg_index_indpred - 1] = false; |
304 | | - newTuple = heap_form_tuple(RelationGetDescr(pg_index), values, isnull); |
305 | | - simple_heap_update(pg_index, &oldTuple->t_self, newTuple); |
306 | | - CatalogUpdateIndexes(pg_index, newTuple); |
307 | | - heap_freetuple(newTuple); |
308 | | - heap_freetuple(oldTuple); |
309 | | - heap_close(pg_index, NoLock); |
310 | | -} |
311 | | - |
312 | | -void |
313 | | -AlterIndex(Oid indexRelationId, IndexStmt *stmt) |
314 | | -{ |
315 | | - char* select; |
316 | | - Oid heapRelationId; |
317 | | - IndexUniqueCheck checkUnique; |
318 | | - Datum values[INDEX_MAX_KEYS]; |
319 | | - bool isnull[INDEX_MAX_KEYS]; |
320 | | - Relation heapRelation; |
321 | | - Relation indexRelation; |
322 | | - SPIPlanPtr plan; |
323 | | - Portal portal; |
324 | | - HeapTuple tuple; |
325 | | - TupleTableSlot *slot; |
326 | | - ItemPointer tupleid; |
327 | | - IndexInfo *indexInfo; |
328 | | - EState *estate; |
329 | | - Oid namespaceId; |
330 | | - List* deparseCtx; |
331 | | - char* oldIndexPredicate; |
332 | | - char* newIndexPredicate; |
333 | | - char* relationName; |
334 | | - |
335 | | - Assert(stmt->whereClause); |
336 | | - CheckPredicate((Expr *) stmt->whereClause); |
337 | | - |
338 | | - /* Open and lock the parent heap relation */ |
339 | | - heapRelationId = IndexGetRelation(indexRelationId, false); |
340 | | - heapRelation = heap_open(heapRelationId, AccessShareLock); |
341 | | - |
342 | | - /* Open the target index relation */ |
343 | | - /* indexRelation = index_open(indexRelationId, RowExclusiveLock); */ |
344 | | - indexRelation = index_open(indexRelationId, ShareUpdateExclusiveLock); |
345 | | - /* indexRelation = index_open(indexRelationId, AccessShareLock); */ |
346 | | - namespaceId = RelationGetNamespace(indexRelation); |
347 | | - |
348 | | - indexInfo = BuildIndexInfo(indexRelation); |
349 | | - Assert(!indexInfo->ii_ExclusionOps); |
350 | | - |
351 | | - /* |
352 | | - * Generate the constraint and default execution states |
353 | | - */ |
354 | | - estate = CreateExecutorState(); |
355 | | - |
356 | | - checkUnique = indexRelation->rd_index->indisunique ? UNIQUE_CHECK_YES : UNIQUE_CHECK_NO; |
357 | | - |
358 | | - slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation)); |
359 | | - |
360 | | - deparseCtx = deparse_context_for(RelationGetRelationName(heapRelation), heapRelationId); |
361 | | - relationName = quote_qualified_identifier(get_namespace_name(namespaceId), |
362 | | - get_rel_name(heapRelationId)), |
363 | | - newIndexPredicate = deparse_expression(stmt->whereClause, deparseCtx, false, false); |
364 | | - oldIndexPredicate = indexInfo->ii_Predicate |
365 | | - ? deparse_expression((Node*)make_ands_explicit(indexInfo->ii_Predicate), deparseCtx, false, false) |
366 | | - : "true"; |
367 | | - |
368 | | - SPI_connect(); |
369 | | - |
370 | | - select = psprintf("select * from %s where %s and not (%s) limit 1", |
371 | | - relationName, oldIndexPredicate, newIndexPredicate); |
372 | | - if (SPI_execute(select, true, 1) != SPI_OK_SELECT) |
373 | | - { |
374 | | - ereport(ERROR, |
375 | | - (errcode(ERRCODE_INVALID_CURSOR_STATE), |
376 | | - errmsg("Failed to execute statement %s", select))); |
377 | | - } |
378 | | - if (SPI_processed) { |
379 | | - /* There is no way in Postgres to exclude records from index, so we have to completelty rebuild index in this case */ |
380 | | - bool relpersistence = indexRelation->rd_rel->relpersistence; |
381 | | - index_close(indexRelation, NoLock); |
382 | | - indexRelation->rd_indpred = make_ands_implicit((Expr *) stmt->whereClause); |
383 | | - indexRelation = NULL; |
384 | | - UpdateIndex(indexRelationId, stmt->whereClause); |
385 | | - reindex_index(indexRelationId, false, relpersistence, 0); |
386 | | - } else { |
387 | | - select = psprintf("select * from %s where %s and not (%s)", |
388 | | - relationName, newIndexPredicate, oldIndexPredicate); |
389 | | - plan = SPI_prepare(select, 0, NULL); |
390 | | - if (plan == NULL) { |
391 | | - ereport(ERROR, |
392 | | - (errcode(ERRCODE_INVALID_CURSOR_STATE), |
393 | | - errmsg("Failed to preapre statement %s", select))); |
394 | | - } |
395 | | - portal = SPI_cursor_open(NULL, plan, NULL, NULL, true); |
396 | | - if (portal == NULL) { |
397 | | - ereport(ERROR, |
398 | | - (errcode(ERRCODE_INVALID_CURSOR_STATE), |
399 | | - errmsg("Failed to open cursor for %s", select))); |
400 | | - } |
401 | | - while (true) |
402 | | - { |
403 | | - SPI_cursor_fetch(portal, true, 1); |
404 | | - if (!SPI_processed) { |
405 | | - break; |
406 | | - } |
407 | | - tuple = SPI_tuptable->vals[0]; |
408 | | - tupleid = &tuple->t_data->t_ctid; |
409 | | - ExecStoreTuple(tuple, slot, InvalidBuffer, false); |
410 | | - |
411 | | - FormIndexDatum(indexInfo, |
412 | | - slot, |
413 | | - estate, |
414 | | - values, |
415 | | - isnull); |
416 | | - index_insert(indexRelation, /* index relation */ |
417 | | - values, /* array of index Datums */ |
418 | | - isnull, /* null flags */ |
419 | | - tupleid, /* tid of heap tuple */ |
420 | | - heapRelation, /* heap relation */ |
421 | | - checkUnique); /* type of uniqueness check to do */ |
422 | | - |
423 | | - SPI_freetuple(tuple); |
424 | | - SPI_freetuptable(SPI_tuptable); |
425 | | - } |
426 | | - SPI_cursor_close(portal); |
427 | | - |
428 | | - UpdateIndex(indexRelationId, stmt->whereClause); |
429 | | - } |
430 | | - SPI_finish(); |
431 | | - |
432 | | - ExecDropSingleTupleTableSlot(slot); |
433 | | - FreeExecutorState(estate); |
434 | | - |
435 | | - heap_close(heapRelation, NoLock); |
436 | | - if (indexRelation) { |
437 | | - index_close(indexRelation, NoLock); |
438 | | - } |
439 | | -} |
440 | | - |
441 | 283 | /* |
442 | 284 | * DefineIndex |
443 | 285 | * Creates a new index. |
|
0 commit comments