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
