On 02/28/2016 05:16 AM, Michael Paquier wrote: > + Returns information about current controldata file state. > s/controldata/control data? > > + <tgroup cols="2"> > + <thead> > + <row> > + <entry>Column Name</entry> > + <entry>Data Type</entry> > + </row> > + </thead> > + > Having a description of each field would be nice.
Might be nice, but the pg_controldata section of the docs does not have any description either, and I don't feel compelled to improve on that just for the sake of this patch. I'll put it on my TODO to improve both at some point though. > + * pg_controldata.c > + * Expose select pg_controldata output, except via SQL functions > I am not much getting the meaning of this sentence. What about the following: > "Set of routines exposing the contents of the control data file in a > set of SQL functions". Ok, reworded to something similar. > + /* Populate the values and null arrays */ > + values[0] = LSNGetDatum(ControlFile->checkPoint); > + nulls[0] = false; > + > + values[1] = LSNGetDatum(ControlFile->prevCheckPoint); > + nulls[1] = false; > Instead of setting each flag of nulls[] one by one, just calling once > MemSet would be fine. Any method is fine though. I prefer the current style and I believe it is more consistent with what is done elsewhere. In any case this is not exactly a performance critical path. > + /* get a copy of the control file */ > + ControlFile = get_controlfile(DataDir, progname); > Some whitespaces here. git diff is showing in red here. fixed > + if (ControlFile->pg_control_version % 65536 == 0 && > + ControlFile->pg_control_version / 65536 != 0) > + elog(ERROR, _("byte ordering mismatch")); > You may want to put this check directly in get_controlfile(). it is > repeated 4 times in the backend, and has an equivalent in > pg_controldata. makes sense - done > our @pgcommonallfiles = qw( > - config_info.c exec.c pg_lzcompress.c pgfnames.c psprintf.c > + config_info.c controldata_utils.c exec.c pg_lzcompress.c pgfnames.c > relpath.c rmtree.c string.c username.c wait_error.c); > "psprintf.c" has been removed from this list. This causes the build > with MSVC to fail. good catch -- fixed If there are no other complaints or comments, I will commit the attached sometime this coming week (the the requisite catversion bump). Thanks! Joe -- Crunchy Data - http://crunchydata.com PostgreSQL Support for Secure Enterprises Consulting, Training, & Open Source Development
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index c0b94bc..4b5ee81 100644 *** a/doc/src/sgml/func.sgml --- b/doc/src/sgml/func.sgml *************** SELECT collation for ('foo' COLLATE "de_ *** 16703,16708 **** --- 16703,17064 ---- </tgroup> </table> + <para> + The functions shown in <xref linkend="functions-controldata"> + print information initialized during <command>initdb</>, such + as the catalog version. They also show information about write-ahead + logging and checkpoint processing. This information is cluster-wide, + and not specific to any one database. They provide most of the same + information, from the same source, as + <xref linkend="APP-PGCONTROLDATA">, although in a form better suited + to <acronym>SQL</acronym> functions. + </para> + + <table id="functions-controldata"> + <title>Control Data Functions</title> + <tgroup cols="3"> + <thead> + <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row> + </thead> + + <tbody> + <row> + <entry> + <indexterm><primary>pg_control_checkpoint</primary></indexterm> + <literal><function>pg_control_checkpoint()</function></literal> + </entry> + <entry><type>record</type></entry> + <entry> + Returns information about current checkpoint state. + </entry> + </row> + + <row> + <entry> + <indexterm><primary>pg_control_system</primary></indexterm> + <literal><function>pg_control_system()</function></literal> + </entry> + <entry><type>record</type></entry> + <entry> + Returns information about current controldata file state. + </entry> + </row> + + <row> + <entry> + <indexterm><primary>pg_control_init</primary></indexterm> + <literal><function>pg_control_init()</function></literal> + </entry> + <entry><type>record</type></entry> + <entry> + Returns information about cluster initialization state. + </entry> + </row> + + <row> + <entry> + <indexterm><primary>pg_control_recovery</primary></indexterm> + <literal><function>pg_control_recovery()</function></literal> + </entry> + <entry><type>record</type></entry> + <entry> + Returns information about recovery state. + </entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + <function>pg_control_checkpoint</> returns a record, shown in + <xref linkend="functions-pg-control-checkpoint"> + </para> + + <table id="functions-pg-control-checkpoint"> + <title><function>pg_control_checkpoint</> Columns</title> + <tgroup cols="2"> + <thead> + <row> + <entry>Column Name</entry> + <entry>Data Type</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>checkpoint_location</entry> + <entry><type>pg_lsn</type></entry> + </row> + + <row> + <entry>prior_location</entry> + <entry><type>pg_lsn</type></entry> + </row> + + <row> + <entry>redo_location</entry> + <entry><type>pg_lsn</type></entry> + </row> + + <row> + <entry>redo_wal_file</entry> + <entry><type>text</type></entry> + </row> + + <row> + <entry>timeline_id</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>prev_timeline_id</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>full_page_writes</entry> + <entry><type>boolean</type></entry> + </row> + + <row> + <entry>next_xid</entry> + <entry><type>text</type></entry> + </row> + + <row> + <entry>next_oid</entry> + <entry><type>oid</type></entry> + </row> + + <row> + <entry>next_multixact_id</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>next_multi_offset</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>oldest_xid</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>oldest_xid_dbid</entry> + <entry><type>oid</type></entry> + </row> + + <row> + <entry>oldest_active_xid</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>oldest_multi_xid</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>oldest_multi_dbid</entry> + <entry><type>oid</type></entry> + </row> + + <row> + <entry>oldest_commit_ts_xid</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>newest_commit_ts_xid</entry> + <entry><type>xid</type></entry> + </row> + + <row> + <entry>checkpoint_time</entry> + <entry><type>timestamp with time zone</type></entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + <function>pg_control_system</> returns a record, shown in + <xref linkend="functions-pg-control-system"> + </para> + + <table id="functions-pg-control-system"> + <title><function>pg_control_system</> Columns</title> + <tgroup cols="2"> + <thead> + <row> + <entry>Column Name</entry> + <entry>Data Type</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>pg_control_version</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>catalog_version_no</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>system_identifier</entry> + <entry><type>bigint</type></entry> + </row> + + <row> + <entry>pg_control_last_modified</entry> + <entry><type>timestamp with time zone</type></entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + <function>pg_control_init</> returns a record, shown in + <xref linkend="functions-pg-control-init"> + </para> + + <table id="functions-pg-control-init"> + <title><function>pg_control_init</> Columns</title> + <tgroup cols="2"> + <thead> + <row> + <entry>Column Name</entry> + <entry>Data Type</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>max_data_alignment</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>database_block_size</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>blocks_per_segment</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>wal_block_size</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>bytes_per_wal_segment</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>max_identifier_length</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>max_index_columns</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>max_toast_chunk_size</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>large_object_chunk_size</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>bigint_timestamps</entry> + <entry><type>boolean</type></entry> + </row> + + <row> + <entry>float4_pass_by_value</entry> + <entry><type>boolean</type></entry> + </row> + + <row> + <entry>float8_pass_by_value</entry> + <entry><type>boolean</type></entry> + </row> + + <row> + <entry>data_page_checksum_version</entry> + <entry><type>integer</type></entry> + </row> + + </tbody> + </tgroup> + </table> + + <para> + <function>pg_control_recovery</> returns a record, shown in + <xref linkend="functions-pg-control-recovery"> + </para> + + <table id="functions-pg-control-recovery"> + <title><function>pg_control_recovery</> Columns</title> + <tgroup cols="2"> + <thead> + <row> + <entry>Column Name</entry> + <entry>Data Type</entry> + </row> + </thead> + + <tbody> + + <row> + <entry>min_recovery_end_location</entry> + <entry><type>pg_lsn</type></entry> + </row> + + <row> + <entry>min_recovery_end_timeline</entry> + <entry><type>integer</type></entry> + </row> + + <row> + <entry>backup_start_location</entry> + <entry><type>pg_lsn</type></entry> + </row> + + <row> + <entry>backup_end_location</entry> + <entry><type>pg_lsn</type></entry> + </row> + + <row> + <entry>end_of_backup_record_required</entry> + <entry><type>boolean</type></entry> + </row> + + </tbody> + </tgroup> + </table> + </sect1> <sect1 id="functions-admin"> diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile index a0c82c1..a5b487d 100644 *** a/src/backend/utils/misc/Makefile --- b/src/backend/utils/misc/Makefile *************** include $(top_builddir)/src/Makefile.glo *** 14,20 **** override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS) ! OBJS = guc.o help_config.o pg_config.o pg_rusage.o \ ps_status.o rls.o sampling.o superuser.o timeout.o tzparser.o # This location might depend on the installation directories. Therefore --- 14,20 ---- override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS) ! OBJS = guc.o help_config.o pg_config.o pg_controldata.o pg_rusage.o \ ps_status.o rls.o sampling.o superuser.o timeout.o tzparser.o # This location might depend on the installation directories. Therefore diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c index ...8552c07 . *** a/src/backend/utils/misc/pg_controldata.c --- b/src/backend/utils/misc/pg_controldata.c *************** *** 0 **** --- 1,341 ---- + /*------------------------------------------------------------------------- + * + * pg_controldata.c + * + * Routines to expose the contents of the control data file via + * a set of SQL functions. + * + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/utils/misc/pg_controldata.c + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include "funcapi.h" + #include "miscadmin.h" + #include "access/htup_details.h" + #include "access/xlog_internal.h" + #include "catalog/pg_control.h" + #include "catalog/pg_type.h" + #include "common/controldata_utils.h" + #include "utils/builtins.h" + #include "utils/pg_lsn.h" + #include "utils/timestamp.h" + + Datum + pg_control_system(PG_FUNCTION_ARGS) + { + Datum values[4]; + bool nulls[4]; + TupleDesc tupdesc; + HeapTuple htup; + ControlFileData *ControlFile; + + /* + * Construct a tuple descriptor for the result row. This must match this + * function's pg_proc entry! + */ + tupdesc = CreateTemplateTupleDesc(4, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "system_identifier", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pg_control_last_modified", + TIMESTAMPTZOID, -1, 0); + tupdesc = BlessTupleDesc(tupdesc); + + /* read the control file */ + ControlFile = get_controlfile(DataDir, NULL); + + values[0] = Int32GetDatum(ControlFile->pg_control_version); + nulls[0] = false; + + values[1] = Int32GetDatum(ControlFile->catalog_version_no); + nulls[1] = false; + + values[2] = Int64GetDatum(ControlFile->system_identifier); + nulls[2] = false; + + values[3] = TimestampTzGetDatum(time_t_to_timestamptz(ControlFile->time)); + nulls[3] = false; + + htup = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + } + + Datum + pg_control_checkpoint(PG_FUNCTION_ARGS) + { + Datum values[19]; + bool nulls[19]; + TupleDesc tupdesc; + HeapTuple htup; + ControlFileData *ControlFile; + XLogSegNo segno; + char xlogfilename[MAXFNAMELEN]; + + /* + * Construct a tuple descriptor for the result row. This must match this + * function's pg_proc entry! + */ + tupdesc = CreateTemplateTupleDesc(19, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_location", + LSNOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "prior_location", + LSNOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "redo_location", + LSNOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "redo_wal_file", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "timeline_id", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "prev_timeline_id", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "full_page_writes", + BOOLOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_xid", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_oid", + OIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multixact_id", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "next_multi_offset", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_xid_dbid", + OIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_active_xid", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_xid", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_multi_dbid", + OIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 17, "oldest_commit_ts_xid", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 18, "newest_commit_ts_xid", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 19, "checkpoint_time", + TIMESTAMPTZOID, -1, 0); + tupdesc = BlessTupleDesc(tupdesc); + + /* Read the control file. */ + ControlFile = get_controlfile(DataDir, NULL); + + /* + * Calculate name of the WAL file containing the latest checkpoint's REDO + * start point. + */ + XLByteToSeg(ControlFile->checkPointCopy.redo, segno); + XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno); + + /* Populate the values and null arrays */ + values[0] = LSNGetDatum(ControlFile->checkPoint); + nulls[0] = false; + + values[1] = LSNGetDatum(ControlFile->prevCheckPoint); + nulls[1] = false; + + values[2] = LSNGetDatum(ControlFile->checkPointCopy.redo); + nulls[2] = false; + + values[3] = CStringGetTextDatum(xlogfilename); + nulls[3] = false; + + values[4] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID); + nulls[4] = false; + + values[5] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID); + nulls[5] = false; + + values[6] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites); + nulls[6] = false; + + values[7] = CStringGetTextDatum(psprintf("%u:%u", + ControlFile->checkPointCopy.nextXidEpoch, + ControlFile->checkPointCopy.nextXid)); + nulls[7] = false; + + values[8] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid); + nulls[8] = false; + + values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti); + nulls[9] = false; + + values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset); + nulls[10] = false; + + values[11] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid); + nulls[11] = false; + + values[12] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB); + nulls[12] = false; + + values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid); + nulls[13] = false; + + values[14] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti); + nulls[14] = false; + + values[15] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB); + nulls[15] = false; + + values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid); + nulls[16] = false; + + values[17] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid); + nulls[17] = false; + + values[18] = TimestampTzGetDatum( + time_t_to_timestamptz(ControlFile->checkPointCopy.time)); + nulls[18] = false; + + htup = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + } + + Datum + pg_control_recovery(PG_FUNCTION_ARGS) + { + Datum values[5]; + bool nulls[5]; + TupleDesc tupdesc; + HeapTuple htup; + ControlFileData *ControlFile; + + /* + * Construct a tuple descriptor for the result row. This must match this + * function's pg_proc entry! + */ + tupdesc = CreateTemplateTupleDesc(5, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "min_recovery_end_location", + LSNOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "min_recovery_end_timeline", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "backup_start_location", + LSNOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "backup_end_location", + LSNOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "end_of_backup_record_required", + BOOLOID, -1, 0); + tupdesc = BlessTupleDesc(tupdesc); + + /* read the control file */ + ControlFile = get_controlfile(DataDir, NULL); + + values[0] = LSNGetDatum(ControlFile->minRecoveryPoint); + nulls[0] = false; + + values[1] = Int32GetDatum(ControlFile->minRecoveryPointTLI); + nulls[1] = false; + + values[2] = LSNGetDatum(ControlFile->backupStartPoint); + nulls[2] = false; + + values[3] = LSNGetDatum(ControlFile->backupEndPoint); + nulls[3] = false; + + values[4] = BoolGetDatum(ControlFile->backupEndRequired); + nulls[4] = false; + + htup = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + } + + Datum + pg_control_init(PG_FUNCTION_ARGS) + { + Datum values[13]; + bool nulls[13]; + TupleDesc tupdesc; + HeapTuple htup; + ControlFileData *ControlFile; + + /* + * Construct a tuple descriptor for the result row. This must match this + * function's pg_proc entry! + */ + tupdesc = CreateTemplateTupleDesc(13, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "blocks_per_segment", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_block_size", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "bytes_per_wal_segment", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "max_identifier_length", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "max_index_columns", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "max_toast_chunk_size", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "large_object_chunk_size", + INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "bigint_timestamps", + BOOLOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "float4_pass_by_value", + BOOLOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 12, "float8_pass_by_value", + BOOLOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "data_page_checksum_version", + INT4OID, -1, 0); + tupdesc = BlessTupleDesc(tupdesc); + + /* read the control file */ + ControlFile = get_controlfile(DataDir, NULL); + + values[0] = Int32GetDatum(ControlFile->maxAlign); + nulls[0] = false; + + values[1] = Int32GetDatum(ControlFile->blcksz); + nulls[1] = false; + + values[2] = Int32GetDatum(ControlFile->relseg_size); + nulls[2] = false; + + values[3] = Int32GetDatum(ControlFile->xlog_blcksz); + nulls[3] = false; + + values[4] = Int32GetDatum(ControlFile->xlog_seg_size); + nulls[4] = false; + + values[5] = Int32GetDatum(ControlFile->nameDataLen); + nulls[5] = false; + + values[6] = Int32GetDatum(ControlFile->indexMaxKeys); + nulls[6] = false; + + values[7] = Int32GetDatum(ControlFile->toast_max_chunk_size); + nulls[7] = false; + + values[8] = Int32GetDatum(ControlFile->loblksize); + nulls[8] = false; + + values[9] = BoolGetDatum(ControlFile->enableIntTimes); + nulls[9] = false; + + values[10] = BoolGetDatum(ControlFile->float4ByVal); + nulls[10] = false; + + values[11] = BoolGetDatum(ControlFile->float8ByVal); + nulls[11] = false; + + values[12] = Int32GetDatum(ControlFile->data_checksum_version); + nulls[12] = false; + + htup = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(htup)); + } diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c index 5dd2dbc..fdf7c7d 100644 *** a/src/bin/pg_controldata/pg_controldata.c --- b/src/bin/pg_controldata/pg_controldata.c *************** *** 18,31 **** #include "postgres.h" - #include <unistd.h> #include <time.h> - #include <sys/stat.h> - #include <fcntl.h> #include "access/xlog.h" #include "access/xlog_internal.h" #include "catalog/pg_control.h" #include "pg_getopt.h" --- 18,29 ---- #include "postgres.h" #include <time.h> #include "access/xlog.h" #include "access/xlog_internal.h" #include "catalog/pg_control.h" + #include "common/controldata_utils.h" #include "pg_getopt.h" *************** wal_level_str(WalLevel wal_level) *** 89,99 **** int main(int argc, char *argv[]) { ! ControlFileData ControlFile; ! int fd; ! char ControlFilePath[MAXPGPATH]; char *DataDir = NULL; - pg_crc32c crc; time_t time_tmp; char pgctime_str[128]; char ckpttime_str[128]; --- 87,94 ---- int main(int argc, char *argv[]) { ! ControlFileData *ControlFile; char *DataDir = NULL; time_t time_tmp; char pgctime_str[128]; char ckpttime_str[128]; *************** main(int argc, char *argv[]) *** 161,194 **** exit(1); } ! snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir); ! ! if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1) ! { ! fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"), ! progname, ControlFilePath, strerror(errno)); ! exit(2); ! } ! ! if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData)) ! { ! fprintf(stderr, _("%s: could not read file \"%s\": %s\n"), ! progname, ControlFilePath, strerror(errno)); ! exit(2); ! } ! close(fd); ! ! /* Check the CRC. */ ! INIT_CRC32C(crc); ! COMP_CRC32C(crc, ! (char *) &ControlFile, ! offsetof(ControlFileData, crc)); ! FIN_CRC32C(crc); ! ! if (!EQ_CRC32C(crc, ControlFile.crc)) ! printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n" ! "Either the file is corrupt, or it has a different layout than this program\n" ! "is expecting. The results below are untrustworthy.\n\n")); /* * This slightly-chintzy coding will work as long as the control file --- 156,163 ---- exit(1); } ! /* get a copy of the control file */ ! ControlFile = get_controlfile(DataDir, progname); /* * This slightly-chintzy coding will work as long as the control file *************** main(int argc, char *argv[]) *** 199,208 **** * Use variable for format to suppress overly-anal-retentive gcc warning * about %c */ ! time_tmp = (time_t) ControlFile.time; strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt, localtime(&time_tmp)); ! time_tmp = (time_t) ControlFile.checkPointCopy.time; strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt, localtime(&time_tmp)); --- 168,177 ---- * Use variable for format to suppress overly-anal-retentive gcc warning * about %c */ ! time_tmp = (time_t) ControlFile->time; strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt, localtime(&time_tmp)); ! time_tmp = (time_t) ControlFile->checkPointCopy.time; strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt, localtime(&time_tmp)); *************** main(int argc, char *argv[]) *** 210,338 **** * Calculate name of the WAL file containing the latest checkpoint's REDO * start point. */ ! XLByteToSeg(ControlFile.checkPointCopy.redo, segno); ! XLogFileName(xlogfilename, ControlFile.checkPointCopy.ThisTimeLineID, segno); /* * Format system_identifier separately to keep platform-dependent format * code out of the translatable message string. */ snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT, ! ControlFile.system_identifier); printf(_("pg_control version number: %u\n"), ! ControlFile.pg_control_version); ! if (ControlFile.pg_control_version % 65536 == 0 && ControlFile.pg_control_version / 65536 != 0) ! printf(_("WARNING: possible byte ordering mismatch\n" ! "The byte ordering used to store the pg_control file might not match the one\n" ! "used by this program. In that case the results below would be incorrect, and\n" ! "the PostgreSQL installation would be incompatible with this data directory.\n")); printf(_("Catalog version number: %u\n"), ! ControlFile.catalog_version_no); printf(_("Database system identifier: %s\n"), sysident_str); printf(_("Database cluster state: %s\n"), ! dbState(ControlFile.state)); printf(_("pg_control last modified: %s\n"), pgctime_str); printf(_("Latest checkpoint location: %X/%X\n"), ! (uint32) (ControlFile.checkPoint >> 32), ! (uint32) ControlFile.checkPoint); printf(_("Prior checkpoint location: %X/%X\n"), ! (uint32) (ControlFile.prevCheckPoint >> 32), ! (uint32) ControlFile.prevCheckPoint); printf(_("Latest checkpoint's REDO location: %X/%X\n"), ! (uint32) (ControlFile.checkPointCopy.redo >> 32), ! (uint32) ControlFile.checkPointCopy.redo); printf(_("Latest checkpoint's REDO WAL file: %s\n"), xlogfilename); printf(_("Latest checkpoint's TimeLineID: %u\n"), ! ControlFile.checkPointCopy.ThisTimeLineID); printf(_("Latest checkpoint's PrevTimeLineID: %u\n"), ! ControlFile.checkPointCopy.PrevTimeLineID); printf(_("Latest checkpoint's full_page_writes: %s\n"), ! ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off")); printf(_("Latest checkpoint's NextXID: %u:%u\n"), ! ControlFile.checkPointCopy.nextXidEpoch, ! ControlFile.checkPointCopy.nextXid); printf(_("Latest checkpoint's NextOID: %u\n"), ! ControlFile.checkPointCopy.nextOid); printf(_("Latest checkpoint's NextMultiXactId: %u\n"), ! ControlFile.checkPointCopy.nextMulti); printf(_("Latest checkpoint's NextMultiOffset: %u\n"), ! ControlFile.checkPointCopy.nextMultiOffset); printf(_("Latest checkpoint's oldestXID: %u\n"), ! ControlFile.checkPointCopy.oldestXid); printf(_("Latest checkpoint's oldestXID's DB: %u\n"), ! ControlFile.checkPointCopy.oldestXidDB); printf(_("Latest checkpoint's oldestActiveXID: %u\n"), ! ControlFile.checkPointCopy.oldestActiveXid); printf(_("Latest checkpoint's oldestMultiXid: %u\n"), ! ControlFile.checkPointCopy.oldestMulti); printf(_("Latest checkpoint's oldestMulti's DB: %u\n"), ! ControlFile.checkPointCopy.oldestMultiDB); printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"), ! ControlFile.checkPointCopy.oldestCommitTsXid); printf(_("Latest checkpoint's newestCommitTsXid:%u\n"), ! ControlFile.checkPointCopy.newestCommitTsXid); printf(_("Time of latest checkpoint: %s\n"), ckpttime_str); printf(_("Fake LSN counter for unlogged rels: %X/%X\n"), ! (uint32) (ControlFile.unloggedLSN >> 32), ! (uint32) ControlFile.unloggedLSN); printf(_("Minimum recovery ending location: %X/%X\n"), ! (uint32) (ControlFile.minRecoveryPoint >> 32), ! (uint32) ControlFile.minRecoveryPoint); printf(_("Min recovery ending loc's timeline: %u\n"), ! ControlFile.minRecoveryPointTLI); printf(_("Backup start location: %X/%X\n"), ! (uint32) (ControlFile.backupStartPoint >> 32), ! (uint32) ControlFile.backupStartPoint); printf(_("Backup end location: %X/%X\n"), ! (uint32) (ControlFile.backupEndPoint >> 32), ! (uint32) ControlFile.backupEndPoint); printf(_("End-of-backup record required: %s\n"), ! ControlFile.backupEndRequired ? _("yes") : _("no")); printf(_("wal_level setting: %s\n"), ! wal_level_str(ControlFile.wal_level)); printf(_("wal_log_hints setting: %s\n"), ! ControlFile.wal_log_hints ? _("on") : _("off")); printf(_("max_connections setting: %d\n"), ! ControlFile.MaxConnections); printf(_("max_worker_processes setting: %d\n"), ! ControlFile.max_worker_processes); printf(_("max_prepared_xacts setting: %d\n"), ! ControlFile.max_prepared_xacts); printf(_("max_locks_per_xact setting: %d\n"), ! ControlFile.max_locks_per_xact); printf(_("track_commit_timestamp setting: %s\n"), ! ControlFile.track_commit_timestamp ? _("on") : _("off")); printf(_("Maximum data alignment: %u\n"), ! ControlFile.maxAlign); /* we don't print floatFormat since can't say much useful about it */ printf(_("Database block size: %u\n"), ! ControlFile.blcksz); printf(_("Blocks per segment of large relation: %u\n"), ! ControlFile.relseg_size); printf(_("WAL block size: %u\n"), ! ControlFile.xlog_blcksz); printf(_("Bytes per WAL segment: %u\n"), ! ControlFile.xlog_seg_size); printf(_("Maximum length of identifiers: %u\n"), ! ControlFile.nameDataLen); printf(_("Maximum columns in an index: %u\n"), ! ControlFile.indexMaxKeys); printf(_("Maximum size of a TOAST chunk: %u\n"), ! ControlFile.toast_max_chunk_size); printf(_("Size of a large-object chunk: %u\n"), ! ControlFile.loblksize); printf(_("Date/time type storage: %s\n"), ! (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers"))); printf(_("Float4 argument passing: %s\n"), ! (ControlFile.float4ByVal ? _("by value") : _("by reference"))); printf(_("Float8 argument passing: %s\n"), ! (ControlFile.float8ByVal ? _("by value") : _("by reference"))); printf(_("Data page checksum version: %u\n"), ! ControlFile.data_checksum_version); return 0; } --- 179,302 ---- * Calculate name of the WAL file containing the latest checkpoint's REDO * start point. */ ! XLByteToSeg(ControlFile->checkPointCopy.redo, segno); ! XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno); /* * Format system_identifier separately to keep platform-dependent format * code out of the translatable message string. */ snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT, ! ControlFile->system_identifier); printf(_("pg_control version number: %u\n"), ! ControlFile->pg_control_version); printf(_("Catalog version number: %u\n"), ! ControlFile->catalog_version_no); printf(_("Database system identifier: %s\n"), sysident_str); printf(_("Database cluster state: %s\n"), ! dbState(ControlFile->state)); printf(_("pg_control last modified: %s\n"), pgctime_str); printf(_("Latest checkpoint location: %X/%X\n"), ! (uint32) (ControlFile->checkPoint >> 32), ! (uint32) ControlFile->checkPoint); printf(_("Prior checkpoint location: %X/%X\n"), ! (uint32) (ControlFile->prevCheckPoint >> 32), ! (uint32) ControlFile->prevCheckPoint); printf(_("Latest checkpoint's REDO location: %X/%X\n"), ! (uint32) (ControlFile->checkPointCopy.redo >> 32), ! (uint32) ControlFile->checkPointCopy.redo); printf(_("Latest checkpoint's REDO WAL file: %s\n"), xlogfilename); printf(_("Latest checkpoint's TimeLineID: %u\n"), ! ControlFile->checkPointCopy.ThisTimeLineID); printf(_("Latest checkpoint's PrevTimeLineID: %u\n"), ! ControlFile->checkPointCopy.PrevTimeLineID); printf(_("Latest checkpoint's full_page_writes: %s\n"), ! ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off")); printf(_("Latest checkpoint's NextXID: %u:%u\n"), ! ControlFile->checkPointCopy.nextXidEpoch, ! ControlFile->checkPointCopy.nextXid); printf(_("Latest checkpoint's NextOID: %u\n"), ! ControlFile->checkPointCopy.nextOid); printf(_("Latest checkpoint's NextMultiXactId: %u\n"), ! ControlFile->checkPointCopy.nextMulti); printf(_("Latest checkpoint's NextMultiOffset: %u\n"), ! ControlFile->checkPointCopy.nextMultiOffset); printf(_("Latest checkpoint's oldestXID: %u\n"), ! ControlFile->checkPointCopy.oldestXid); printf(_("Latest checkpoint's oldestXID's DB: %u\n"), ! ControlFile->checkPointCopy.oldestXidDB); printf(_("Latest checkpoint's oldestActiveXID: %u\n"), ! ControlFile->checkPointCopy.oldestActiveXid); printf(_("Latest checkpoint's oldestMultiXid: %u\n"), ! ControlFile->checkPointCopy.oldestMulti); printf(_("Latest checkpoint's oldestMulti's DB: %u\n"), ! ControlFile->checkPointCopy.oldestMultiDB); printf(_("Latest checkpoint's oldestCommitTsXid:%u\n"), ! ControlFile->checkPointCopy.oldestCommitTsXid); printf(_("Latest checkpoint's newestCommitTsXid:%u\n"), ! ControlFile->checkPointCopy.newestCommitTsXid); printf(_("Time of latest checkpoint: %s\n"), ckpttime_str); printf(_("Fake LSN counter for unlogged rels: %X/%X\n"), ! (uint32) (ControlFile->unloggedLSN >> 32), ! (uint32) ControlFile->unloggedLSN); printf(_("Minimum recovery ending location: %X/%X\n"), ! (uint32) (ControlFile->minRecoveryPoint >> 32), ! (uint32) ControlFile->minRecoveryPoint); printf(_("Min recovery ending loc's timeline: %u\n"), ! ControlFile->minRecoveryPointTLI); printf(_("Backup start location: %X/%X\n"), ! (uint32) (ControlFile->backupStartPoint >> 32), ! (uint32) ControlFile->backupStartPoint); printf(_("Backup end location: %X/%X\n"), ! (uint32) (ControlFile->backupEndPoint >> 32), ! (uint32) ControlFile->backupEndPoint); printf(_("End-of-backup record required: %s\n"), ! ControlFile->backupEndRequired ? _("yes") : _("no")); printf(_("wal_level setting: %s\n"), ! wal_level_str(ControlFile->wal_level)); printf(_("wal_log_hints setting: %s\n"), ! ControlFile->wal_log_hints ? _("on") : _("off")); printf(_("max_connections setting: %d\n"), ! ControlFile->MaxConnections); printf(_("max_worker_processes setting: %d\n"), ! ControlFile->max_worker_processes); printf(_("max_prepared_xacts setting: %d\n"), ! ControlFile->max_prepared_xacts); printf(_("max_locks_per_xact setting: %d\n"), ! ControlFile->max_locks_per_xact); printf(_("track_commit_timestamp setting: %s\n"), ! ControlFile->track_commit_timestamp ? _("on") : _("off")); printf(_("Maximum data alignment: %u\n"), ! ControlFile->maxAlign); /* we don't print floatFormat since can't say much useful about it */ printf(_("Database block size: %u\n"), ! ControlFile->blcksz); printf(_("Blocks per segment of large relation: %u\n"), ! ControlFile->relseg_size); printf(_("WAL block size: %u\n"), ! ControlFile->xlog_blcksz); printf(_("Bytes per WAL segment: %u\n"), ! ControlFile->xlog_seg_size); printf(_("Maximum length of identifiers: %u\n"), ! ControlFile->nameDataLen); printf(_("Maximum columns in an index: %u\n"), ! ControlFile->indexMaxKeys); printf(_("Maximum size of a TOAST chunk: %u\n"), ! ControlFile->toast_max_chunk_size); printf(_("Size of a large-object chunk: %u\n"), ! ControlFile->loblksize); printf(_("Date/time type storage: %s\n"), ! (ControlFile->enableIntTimes ? _("64-bit integers") : _("floating-point numbers"))); printf(_("Float4 argument passing: %s\n"), ! (ControlFile->float4ByVal ? _("by value") : _("by reference"))); printf(_("Float8 argument passing: %s\n"), ! (ControlFile->float8ByVal ? _("by value") : _("by reference"))); printf(_("Data page checksum version: %u\n"), ! ControlFile->data_checksum_version); return 0; } diff --git a/src/common/Makefile b/src/common/Makefile index bde4fc2..f7a4a4d 100644 *** a/src/common/Makefile --- b/src/common/Makefile *************** override CPPFLAGS += -DVAL_LDFLAGS_EX="\ *** 36,43 **** override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\"" override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\"" ! OBJS_COMMON = config_info.o exec.o pg_lzcompress.o pgfnames.o psprintf.o \ ! relpath.o rmtree.o string.o username.o wait_error.o OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o --- 36,43 ---- override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\"" override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\"" ! OBJS_COMMON = config_info.o controldata_utils.o exec.o pg_lzcompress.o \ ! pgfnames.o psprintf.o relpath.o rmtree.o string.o username.o wait_error.o OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c index ...b6d0a12 . *** a/src/common/controldata_utils.c --- b/src/common/controldata_utils.c *************** *** 0 **** --- 1,100 ---- + /*------------------------------------------------------------------------- + * + * controldata_utils.c + * Common code for control data file output. + * + * + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/common/controldata_utils.c + * + *------------------------------------------------------------------------- + */ + + #ifndef FRONTEND + #include "postgres.h" + #else + #include "postgres_fe.h" + #endif + + #include <unistd.h> + #include <sys/stat.h> + #include <fcntl.h> + + #include "catalog/pg_control.h" + #include "common/controldata_utils.h" + #include "port/pg_crc32c.h" + + #ifndef FRONTEND + /* NOTE: caller must provide gettext call around the format string */ + #define log_error(...) \ + elog(ERROR, __VA_ARGS__) + #else + #define log_error(...) \ + do { \ + char *buf = psprintf(__VA_ARGS__); \ + fprintf(stderr, "%s: %s\n", progname, buf); \ + exit(2); \ + } while (0) + #endif + + /* + * get_controlfile(char *DataDir, const char *progname) + * + * Get controlfile values. The caller is responsible + * for pfreeing the result. + */ + ControlFileData * + get_controlfile(char *DataDir, const char *progname) + { + ControlFileData *ControlFile; + int fd; + char ControlFilePath[MAXPGPATH]; + pg_crc32c crc; + + ControlFile = palloc(sizeof(ControlFileData)); + snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir); + + if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1) + log_error(_("could not open file \"%s\" for reading: %s"), + ControlFilePath, strerror(errno)); + + if (read(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData)) + log_error(_("could not read file \"%s\": %s"), + ControlFilePath, strerror(errno)); + + close(fd); + + /* Check the CRC. */ + INIT_CRC32C(crc); + COMP_CRC32C(crc, + (char *) ControlFile, + offsetof(ControlFileData, crc)); + FIN_CRC32C(crc); + + if (!EQ_CRC32C(crc, ControlFile->crc)) + #ifndef FRONTEND + elog(ERROR, _("calculated CRC checksum does not match value stored in file")); + #else + printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n" + "Either the file is corrupt, or it has a different layout than this program\n" + "is expecting. The results below are untrustworthy.\n\n")); + #endif + + /* Make sure the control file is valid byte order. */ + if (ControlFile->pg_control_version % 65536 == 0 && + ControlFile->pg_control_version / 65536 != 0) + #ifndef FRONTEND + elog(ERROR, _("byte ordering mismatch")); + #else + printf(_("WARNING: possible byte ordering mismatch\n" + "The byte ordering used to store the pg_control file might not match the one\n" + "used by this program. In that case the results below would be incorrect, and\n" + "the PostgreSQL installation would be incompatible with this data directory.\n")); + #endif + + return ControlFile; + } diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 62b9125..e22bfd3 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DESCR("row security for current context *** 5216,5221 **** --- 5216,5234 ---- DATA(insert OID = 3400 ( pg_config PGNSP PGUID 12 1 23 0 0 f f f f t t i r 0 0 2249 "" "{25,25}" "{o,o}" "{name,setting}" _null_ _null_ pg_config _null_ _null_ _null_ )); DESCR("pg_config binary as a function"); + /* pg_controldata related functions */ + DATA(insert OID = 3441 ( pg_control_system PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{23,23,20,1184}" "{o,o,o,o}" "{pg_control_version,catalog_version_no,system_identifier,pg_control_last_modified}" _null_ _null_ pg_control_system _null_ _null_ _null_ )); + DESCR("pg_controldata general state information as a function"); + + DATA(insert OID = 3442 ( pg_control_checkpoint PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{3220,3220,3220,25,23,23,16,25,26,28,28,28,26,28,28,26,28,28,1184}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{checkpoint_location,prior_location,redo_location,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}" _null_ _null_ pg_control_checkpoint _null_ _null_ _null_ )); + DESCR("pg_controldata checkpoint state information as a function"); + + DATA(insert OID = 3443 ( pg_control_recovery PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{3220,23,3220,3220,16}" "{o,o,o,o,o}" "{min_recovery_end_location,min_recovery_end_timeline,backup_start_location,backup_end_location,end_of_backup_record_required}" _null_ _null_ pg_control_recovery _null_ _null_ _null_ )); + DESCR("pg_controldata recovery state information as a function"); + + DATA(insert OID = 3444 ( pg_control_init PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 2249 "" "{23,23,23,23,23,23,23,23,23,16,16,16,23}" "{o,o,o,o,o,o,o,o,o,o,o,o,o}" "{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,bigint_timestamps,float4_pass_by_value,float8_pass_by_value,data_page_checksum_version}" _null_ _null_ pg_control_init _null_ _null_ _null_ )); + DESCR("pg_controldata init state information as a function"); + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h index ...1a09765 . *** a/src/include/common/controldata_utils.h --- b/src/include/common/controldata_utils.h *************** *** 0 **** --- 1,15 ---- + /* + * controldata_utils.h + * Common code for pg_controldata output + * + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/common/controldata_utils.h + */ + #ifndef COMMON_CONTROLDATA_UTILS_H + #define COMMON_CONTROLDATA_UTILS_H + + extern ControlFileData *get_controlfile(char *DataDir, const char *progname); + + #endif /* COMMON_CONTROLDATA_UTILS_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 7ec93c9..115f8af 100644 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** extern Datum show_all_file_settings(PG_F *** 1151,1156 **** --- 1151,1162 ---- /* pg_config.c */ extern Datum pg_config(PG_FUNCTION_ARGS); + /* pg_controldata.c */ + extern Datum pg_control_checkpoint(PG_FUNCTION_ARGS); + extern Datum pg_control_system(PG_FUNCTION_ARGS); + extern Datum pg_control_init(PG_FUNCTION_ARGS); + extern Datum pg_control_recovery(PG_FUNCTION_ARGS); + /* rls.c */ extern Datum row_security_active(PG_FUNCTION_ARGS); extern Datum row_security_active_name(PG_FUNCTION_ARGS); diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index e4fb44e..949077a 100644 *** a/src/tools/msvc/Mkvcbuild.pm --- b/src/tools/msvc/Mkvcbuild.pm *************** sub mkvcbuild *** 106,113 **** } our @pgcommonallfiles = qw( ! config_info.c exec.c pg_lzcompress.c pgfnames.c psprintf.c ! relpath.c rmtree.c string.c username.c wait_error.c); our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c --- 106,113 ---- } our @pgcommonallfiles = qw( ! config_info.c controldata_utils.c exec.c pg_lzcompress.c pgfnames.c ! psprintf.c relpath.c rmtree.c string.c username.c wait_error.c); our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c
signature.asc
Description: OpenPGP digital signature