void case_heap_repalce() { struct heap *heap = heap(heap_cmp); int a = 3, b = 2, c = 5, d = 7, e = 4, f = 6, g = 1, h = 4; assert(heap_push(heap, (void *)&a) == HEAP_OK); assert(heap_push(heap, (void *)&b) == HEAP_OK); assert(heap_push(heap, (void *)&c) == HEAP_OK); assert(heap_push(heap, (void *)&d) == HEAP_OK); assert(heap_push(heap, (void *)&e) == HEAP_OK); assert(heap_push(heap, (void *)&f) == HEAP_OK); assert(heap_push(heap, (void *)&g) == HEAP_OK); assert(1 == *(int *)heap_replace(heap, (void *)&h)); assert(2 == *(int *)heap_pop(heap)); assert(3 == *(int *)heap_pop(heap)); assert(4 == *(int *)heap_pop(heap)); heap_free(heap); }
int32 RelationPurge(char *relationName, char *absoluteTimeString, char *relativeTimeString) { register i; AbsoluteTime absoluteTime = INVALID_ABSTIME; RelativeTime relativeTime = INVALID_RELTIME; bits8 dateTag; Relation relation; HeapScanDesc scan; static ScanKeyData key[1] = { { 0, Anum_pg_class_relname, F_NAMEEQ } }; Buffer buffer; HeapTuple newTuple, oldTuple; AbsoluteTime currentTime; char *values[Natts_pg_class]; char nulls[Natts_pg_class]; char replace[Natts_pg_class]; Relation idescs[Num_pg_class_indices]; /* * XXX for some reason getmyrelids (in inval.c) barfs when * you heap_replace tuples from these classes. i thought * setheapoverride would fix it but it didn't. for now, * just disallow purge on these classes. */ if (strcmp(RelationRelationName, relationName) == 0 || strcmp(AttributeRelationName, relationName) == 0 || strcmp(AccessMethodRelationName, relationName) == 0 || strcmp(AccessMethodOperatorRelationName, relationName) == 0) { elog(WARN, "%s: cannot purge catalog \"%s\"", cmdname, relationName); } if (PointerIsValid(absoluteTimeString)) { absoluteTime = (int32) nabstimein(absoluteTimeString); absoluteTimeString[0] = '\0'; if (absoluteTime == INVALID_ABSTIME) { elog(NOTICE, "%s: bad absolute time string \"%s\"", cmdname, absoluteTimeString); elog(WARN, "purge not executed"); } } #ifdef PURGEDEBUG elog(DEBUG, "%s: absolute time `%s' is %d.", cmdname, absoluteTimeString, absoluteTime); #endif /* defined(PURGEDEBUG) */ if (PointerIsValid(relativeTimeString)) { if (isreltime(relativeTimeString, NULL, NULL, NULL) != 1) { elog(WARN, "%s: bad relative time string \"%s\"", cmdname, relativeTimeString); } relativeTime = reltimein(relativeTimeString); #ifdef PURGEDEBUG elog(DEBUG, "%s: relative time `%s' is %d.", cmdname, relativeTimeString, relativeTime); #endif /* defined(PURGEDEBUG) */ } /* * Find the RELATION relation tuple for the given relation. */ relation = heap_openr(RelationRelationName); key[0].sk_argument = PointerGetDatum(relationName); fmgr_info(key[0].sk_procedure, &key[0].sk_func, &key[0].sk_nargs); scan = heap_beginscan(relation, 0, NowTimeQual, 1, key); oldTuple = heap_getnext(scan, 0, &buffer); if (!HeapTupleIsValid(oldTuple)) { heap_endscan(scan); heap_close(relation); elog(WARN, "%s: no such relation: %s", cmdname, relationName); return(0); } /* * Dig around in the tuple. */ currentTime = GetCurrentTransactionStartTime(); if (!RelativeTimeIsValid(relativeTime)) { dateTag = ABSOLUTE; if (!AbsoluteTimeIsValid(absoluteTime)) absoluteTime = currentTime; } else if (!AbsoluteTimeIsValid(absoluteTime)) dateTag = RELATIVE; else dateTag = ABSOLUTE | RELATIVE; for (i = 0; i < Natts_pg_class; ++i) { nulls[i] = heap_attisnull(oldTuple, i+1) ? 'n' : ' '; values[i] = NULL; replace[i] = ' '; } if (dateTag & ABSOLUTE) { values[Anum_pg_class_relexpires-1] = (char *) UInt32GetDatum(absoluteTime); replace[Anum_pg_class_relexpires-1] = 'r'; } if (dateTag & RELATIVE) { values[Anum_pg_class_relpreserved-1] = (char *) UInt32GetDatum(relativeTime); replace[Anum_pg_class_relpreserved-1] = 'r'; } /* * Change the RELATION relation tuple for the given relation. */ newTuple = heap_modifytuple(oldTuple, buffer, relation, (Datum*)values, nulls, replace); /* XXX How do you detect an insertion error?? */ (void) heap_replace(relation, &newTuple->t_ctid, newTuple); /* keep the system catalog indices current */ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); CatalogIndexInsert(idescs, Num_pg_class_indices, relation, newTuple); CatalogCloseIndices(Num_pg_class_indices, idescs); pfree(newTuple); heap_endscan(scan); heap_close(relation); return(1); }