blob: 2e0ae975f6773e13f215f3fe78bc2c5f2e04531a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*-------------------------------------------------------------------------
*
* cdbpgdatabase.c
* Set-returning function to view pgdatabase table.
*
* IDENTIFICATION
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "funcapi.h"
#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "cdb/cdbutil.h"
#include "cdb/cdbfts.h"
Datum gp_pgdatabase__(PG_FUNCTION_ARGS);
/* Working status for pg_prepared_xact */
typedef struct
{
Segment *master;
Segment *standby;
List *segments;
int idx;
} Working_State;
PG_FUNCTION_INFO_V1(gp_pgdatabase__);
/*
* pgdatabasev - produce a view of pgdatabase to include transient state
*/
Datum
gp_pgdatabase__(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
Working_State *mystatus;
if (SRF_IS_FIRSTCALL())
{
TupleDesc tupdesc;
MemoryContext oldcontext;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
/*
* switch to memory context appropriate for multiple function
* calls
*/
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* build tupdesc for result tuples */
/* this had better match pg_prepared_xacts view in system_views.sql */
tupdesc = CreateTemplateTupleDesc(5, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "dbid",
INT2OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "isprimary",
BOOLOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "content",
INT2OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "valid",
BOOLOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "definedprimary",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
/*
* Collect all the locking information that we will format and
* send out as a result set.
*/
mystatus = (Working_State *) palloc(sizeof(Working_State));
funcctx->user_fctx = (void *) mystatus;
mystatus->master = GetMasterSegment();
mystatus->standby = GetStandbySegment();
mystatus->segments = GetSegmentList();
mystatus->idx = 0;
MemoryContextSwitchTo(oldcontext);
}
funcctx = SRF_PERCALL_SETUP();
mystatus = (Working_State *) funcctx->user_fctx;
while (mystatus->master || mystatus->standby || (mystatus->idx < list_length(mystatus->segments)))
{
Datum values[6];
bool nulls[6];
HeapTuple tuple;
Datum result;
Segment *current = NULL;
if (mystatus->master)
{
current = mystatus->master;
mystatus->master = NULL;
}
else if (mystatus->standby)
{
current = mystatus->standby;
mystatus->standby = NULL;
}
else
{
current = list_nth(mystatus->segments, mystatus->idx);
mystatus->idx++;
}
/*
* Form tuple with appropriate data.
*/
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
//values[0] = UInt16GetDatum(current->dbid);
values[1] = current->standby ? false : true;;
values[2] = UInt16GetDatum(current->segindex);
values[3] = BoolGetDatum(true);
values[4] = values[1];
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
SRF_RETURN_NEXT(funcctx, result);
}
SRF_RETURN_DONE(funcctx);
}