Compare commits

...

12 Commits

Author SHA1 Message Date
Tom Lane
58054de2d0 Improve the implementation of information_schema._pg_expandarray().
This function was originally coded with a handmade expansion
of the array subscripts.  We can do it a little faster and far
more legibly today, by using unnest() WITH ORDINALITY.

While at it, let's apply the rowcount estimation support that exists
for the underlying unnest() function: reduce the default ROWS estimate
to 100 and attach array_unnest_support.  I'm not sure that
array_unnest_support can do anything useful today with the call sites
that exist in information_schema, but it can't hurt, and the existing
default rowcount of 1000 is surely much too high for any of these
cases.

The psql.sql regression script is using _pg_expandarray() as a
test case for \sf+.  While we could keep doing so, the new one-line
function body makes a poor test case for \sf+ row-numbering, so
switch it to print another information_schema function.

Discussion: https://postgr.es/m/1424303.1703355485@sss.pgh.pa.us
2023-12-27 15:55:46 -05:00
Tom Lane
6c361d323b Doc: specify aclitem syntax more clearly.
The previous wording here relied solely on an example to explain
aclitem output format.  Add an actual syntax synopsis and
explanation of the elements to make it clearer.

David Johnston and Tom Lane, per gripe from Eugen Konkov.

Discussion: https://postgr.es/m/170326116972.1876499.18357820037829248593@wrigleys.postgresql.org
2023-12-27 13:52:01 -05:00
Tom Lane
3f1fd41631 Fix another incorrect data type choice from commit dc2123400.
add_file_to_manifest declared its mtime argument as pg_time_t,
apparently on the principle that copy-and-paste from the backend
is fine.  However, the callers are passing struct stat's st_mtime
field which is plain time_t, and add_file_to_manifest itself is
passing the value to gmtime(3) which expects plain time_t,
so the whole thing would not work at all on any platform where
those types are different.  Fortunately we can just switch this
variable to time_t.

Per warnings from assorted buildfarm members.
2023-12-27 13:05:19 -05:00
Peter Eisentraut
390408ec08 Fix incorrect format placeholders 2023-12-27 17:39:10 +01:00
Peter Eisentraut
a7ebd82b9e Fix a warning in Perl test code
The code was passing a scalar argument to node->restart(), but it was
expecting a hash, which causes a warning from Perl ("Odd number of
elements in hash assignment").

But the node->restart() function doesn't take a mode argument anyway.
This was probably copied from an incorrect comment (see commit
750c59d7ec).  The default restart mode is already "fast", so the test
should still be semantically correct without explicitly specifying the
mode.

Discussion: https://www.postgresql.org/message-id/e3f4bf1b-63d3-408a-b07e-d35a0fdf1b98@eisentraut.org
2023-12-27 17:15:26 +01:00
Tom Lane
98c6231d19 Fix incorrect data type choices in some read and write calls.
Recently-introduced code in reconstruct.c was using "unsigned"
to store the result of read(), pg_pread(), or write().  This is
completely bogus: it breaks subsequent tests for the result being
negative, as we're being reminded of by a chorus of buildfarm
warnings.  Switch to "int" as was doubtless intended.  (There are
several other uses of "unsigned" in this file that also look poorly
chosen to me, but for now I'm just trying to clean up the buildfarm.)

A larger problem is that "int" is not necessarily wide enough to hold
the result: per POSIX, all these functions return ssize_t.  In places
where the requested read or write length clearly fits in int, that's
academic.  It may be academic anyway as long as we constrain
individual data files to 1GB, since even a readv or writev-like
operation would then not be responsible for transferring more than
1GB.  Nonetheless it seems like trouble waiting to happen, so I made
a pass over readv and writev calls and fixed the result variables
where that seemed appropriate.  We might want to think about changing
some of the fd.c functions to return ssize_t too, for future-proofing;
but I didn't tackle that here.

Discussion: https://postgr.es/m/1672202.1703441340@sss.pgh.pa.us
2023-12-27 11:02:53 -05:00
Robert Haas
da083b20f6 Initialize variable to placate compiler.
I don't think there's a real problem here, because if we reach
the loop over 'tles' then we will either find at least one
TimeLineHistoryEntry such that oldest_segno != 0, in which case
unsummarized_lsn will be initialized, or else unsummarized_tli
will remain 0 and an error will occur before unsummarized_lsn
is used for anything. But some compilers are complainining, as
reported on list by Nathan Bossart and off-list by Andrew Dunstan.

Discussion: http://postgr.es/m/20231223215147.GA69623@nathanxps13
2023-12-27 08:45:23 -05:00
Alexander Korotkov
7e6fb5da41 Improvements and fixes for e0b1ee17dc
e0b1ee17dc introduced optimization for matching B-tree scan keys required for
the directional scan.  However, it incorrectly assumed that all keys required
for opposite direction scan are satisfied by _bt_first().  It has been
illustrated that with multiple scan keys over the same column, a lesser one
(according to the scan direction) could win leaving the other one unsatisfied.

Instead of relying on _bt_first() this commit introduces code that memorizes
whether there was at least one match on the page.  If that's true we know that
keys required for opposite-direction scan are satisfied as soon as
corresponding values are not NULLs.

Also, this commit simplifies the description for the optimization of keys
required for the current direction scan.  Now the flag used for this is named
continuescanPrechecked and means exactly that *continuescan flag is known
to be true for the last item on the page.

Reported-by: Peter Geoghegan
Discussion: https://postgr.es/m/CAH2-Wzn0LeLcb1PdBnK0xisz8NpHkxRrMr3NWJ%2BKOK-WZ%2BQtTQ%40mail.gmail.com
Reviewed-by: Pavel Borisov
2023-12-27 14:35:08 +02:00
Alexander Korotkov
06b10f80ba Remove BTScanOpaqueData.firstPage
It's not necessary to keep the firstPage flag as a field of BTScanOpaqueData.
This commit makes it an argument of the _bt_readpage() function.  We can easily
distinguish first-time and repeated calls (within the scan) of this function.

Reported-by: Peter Geoghegan
Discussion: https://postgr.es/m/CAH2-Wzk4SOsw%2BtHuTFiz8U9Jqj-R77rYPkhWKODCBb1mdHACXA%40mail.gmail.com
Reviewed-by: Pavel Borisov
2023-12-27 14:21:49 +02:00
Peter Eisentraut
3e527aeeed pg_stat_statements: Add test coverage for pg_stat_statements_reset_1_7
Run pg_stat_statements_reset() once while the appropriate extension
version is installed.

Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://www.postgresql.org/message-id/flat/40d1e4f2-835f-448f-a541-8ff5db75bf3d@eisentraut.org
2023-12-27 10:48:01 +01:00
Peter Eisentraut
3727b8d0e3 pg_stat_statements: Add test coverage for pg_stat_statements_1_8()
This requires reading pg_stat_statements at least once while the 1.8
version of the extension is installed.

Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://www.postgresql.org/message-id/flat/40d1e4f2-835f-448f-a541-8ff5db75bf3d@eisentraut.org
2023-12-27 10:48:01 +01:00
John Naylor
7d7ef075d2 Fix typo and case in messages
Follow up to dc2123400

Kyotaro Horiguchi

Discussion: https://postgr.es/m/20231222.154939.1509525390095583358.horikyota.ntt@gmail.com
Discussion: https://postgr.es/m/20231225.145124.1745560266993421173.horikyota.ntt@gmail.com
2023-12-27 13:31:54 +07:00
22 changed files with 153 additions and 110 deletions

View File

@ -52,6 +52,12 @@ SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
(1 row)
SELECT pg_stat_statements_reset();
pg_stat_statements_reset
--------------------------
(1 row)
\d pg_stat_statements
View "public.pg_stat_statements"
Column | Type | Collation | Nullable | Default
@ -88,6 +94,17 @@ SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
-- New functions and views for pg_stat_statements in 1.8
AlTER EXTENSION pg_stat_statements UPDATE TO '1.8';
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
pg_get_functiondef
--------------------------------------------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.pg_stat_statements_reset(userid oid DEFAULT 0, dbid oid DEFAULT 0, queryid bigint DEFAULT 0)+
RETURNS void +
LANGUAGE c +
PARALLEL SAFE STRICT +
AS '$libdir/pg_stat_statements', $function$pg_stat_statements_reset_1_7$function$ +
(1 row)
\d pg_stat_statements
View "public.pg_stat_statements"
Column | Type | Collation | Nullable | Default
@ -125,15 +142,10 @@ AlTER EXTENSION pg_stat_statements UPDATE TO '1.8';
wal_fpi | bigint | | |
wal_bytes | numeric | | |
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
pg_get_functiondef
--------------------------------------------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.pg_stat_statements_reset(userid oid DEFAULT 0, dbid oid DEFAULT 0, queryid bigint DEFAULT 0)+
RETURNS void +
LANGUAGE c +
PARALLEL SAFE STRICT +
AS '$libdir/pg_stat_statements', $function$pg_stat_statements_reset_1_7$function$ +
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
has_data
----------
t
(1 row)
-- New function pg_stat_statement_info, and new function
@ -324,4 +336,10 @@ SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
(1 row)
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
t
---
t
(1 row)
DROP EXTENSION pg_stat_statements;

View File

@ -28,13 +28,15 @@ SET SESSION AUTHORIZATION pg_read_all_stats;
SELECT pg_stat_statements_reset();
RESET SESSION AUTHORIZATION;
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
SELECT pg_stat_statements_reset();
\d pg_stat_statements
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
-- New functions and views for pg_stat_statements in 1.8
AlTER EXTENSION pg_stat_statements UPDATE TO '1.8';
\d pg_stat_statements
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
\d pg_stat_statements
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
-- New function pg_stat_statement_info, and new function
-- and view for pg_stat_statements introduced in 1.9
@ -54,5 +56,6 @@ AlTER EXTENSION pg_stat_statements UPDATE TO '1.11';
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
-- New parameter minmax_only of pg_stat_statements_reset function
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
DROP EXTENSION pg_stat_statements;

View File

@ -2318,9 +2318,16 @@ REVOKE ALL ON accounts FROM PUBLIC;
<primary><type>aclitem</type></primary>
</indexterm>
The privileges that have been granted for a particular object are
displayed as a list of <type>aclitem</type> entries, where each
<type>aclitem</type> describes the permissions of one grantee that
have been granted by a particular grantor. For example,
displayed as a list of <type>aclitem</type> entries, each having the
format:
<synopsis>
<replaceable>grantee</replaceable><literal>=</literal><replaceable>privilege-abbreviation</replaceable><optional><literal>*</literal></optional>...<literal>/</literal><replaceable>grantor</replaceable>
</synopsis>
Each <type>aclitem</type> lists all the permissions of one grantee that
have been granted by a particular grantor. Specific privileges are
represented by one-letter abbreviations from
<xref linkend="privilege-abbrevs-table"/>, with <literal>*</literal>
appended if the privilege was granted with grant option. For example,
<literal>calvin=r*w/hobbes</literal> specifies that the role
<literal>calvin</literal> has the privilege
<literal>SELECT</literal> (<literal>r</literal>) with grant option

View File

@ -409,7 +409,6 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
so->markItemIndex = -1;
so->arrayKeyCount = 0;
so->firstPage = false;
BTScanPosUnpinIfPinned(so->markPos);
BTScanPosInvalidate(so->markPos);

View File

@ -30,7 +30,7 @@ static OffsetNumber _bt_binsrch(Relation rel, BTScanInsert key, Buffer buf);
static int _bt_binsrch_posting(BTScanInsert key, Page page,
OffsetNumber offnum);
static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir,
OffsetNumber offnum);
OffsetNumber offnum, bool firstPage);
static void _bt_saveitem(BTScanOpaque so, int itemIndex,
OffsetNumber offnum, IndexTuple itup);
static int _bt_setuppostingitems(BTScanOpaque so, int itemIndex,
@ -1395,7 +1395,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
offnum = _bt_binsrch(rel, &inskey, buf);
Assert(!BTScanPosIsValid(so->currPos));
so->currPos.buf = buf;
so->firstPage = true;
/*
* Now load data from the first page of the scan.
@ -1416,7 +1415,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* for the page. For example, when inskey is both < the leaf page's high
* key and > all of its non-pivot tuples, offnum will be "maxoff + 1".
*/
if (!_bt_readpage(scan, dir, offnum))
if (!_bt_readpage(scan, dir, offnum, true))
{
/*
* There's no actually-matching data on this page. Try to advance to
@ -1520,7 +1519,8 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
* Returns true if any matching items found on the page, false if none.
*/
static bool
_bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
_bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
bool firstPage)
{
BTScanOpaque so = (BTScanOpaque) scan->opaque;
Page page;
@ -1530,7 +1530,8 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
int itemIndex;
bool continuescan;
int indnatts;
bool requiredMatchedByPrecheck;
bool continuescanPrechecked;
bool haveFirstMatch = false;
/*
* We must have the buffer pinned and locked, but the usual macro can't be
@ -1585,12 +1586,11 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
Assert(BTScanPosIsPinned(so->currPos));
/*
* Prechecking the page with scan keys required for direction scan. We
* check these keys with the last item on the page (according to our scan
* direction). If these keys are matched, we can skip checking them with
* every item on the page. Scan keys for our scan direction would
* necessarily match the previous items. Scan keys required for opposite
* direction scan are already matched by the _bt_first() call.
* Prechecking the value of the continuescan flag for the last item on the
* page (for backwards scan it will be the first item on a page). If we
* observe it to be true, then it should be true for all other items. This
* allows us to do significant optimizations in the _bt_checkkeys()
* function for all the items on the page.
*
* With the forward scan, we do this check for the last item on the page
* instead of the high key. It's relatively likely that the most
@ -1601,7 +1601,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
* We skip this for the first page in the scan to evade the possible
* slowdown of the point queries.
*/
if (!so->firstPage && minoff < maxoff)
if (!firstPage && minoff < maxoff)
{
ItemId iid;
IndexTuple itup;
@ -1610,18 +1610,17 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
itup = (IndexTuple) PageGetItem(page, iid);
/*
* Do the precheck. Note that we pass the pointer to
* 'requiredMatchedByPrecheck' to 'continuescan' argument. That will
* Do the precheck. Note that we pass the pointer to the
* 'continuescanPrechecked' to the 'continuescan' argument. That will
* set flag to true if all required keys are satisfied and false
* otherwise.
*/
(void) _bt_checkkeys(scan, itup, indnatts, dir,
&requiredMatchedByPrecheck, false);
&continuescanPrechecked, false, false);
}
else
{
so->firstPage = false;
requiredMatchedByPrecheck = false;
continuescanPrechecked = false;
}
if (ScanDirectionIsForward(dir))
@ -1651,19 +1650,22 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
Assert(!BTreeTupleIsPivot(itup));
passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
&continuescan, requiredMatchedByPrecheck);
&continuescan,
continuescanPrechecked,
haveFirstMatch);
/*
* If the result of prechecking required keys was true, then in
* assert-enabled builds we also recheck that the _bt_checkkeys()
* result is the same.
*/
Assert(!requiredMatchedByPrecheck ||
Assert((!continuescanPrechecked && haveFirstMatch) ||
passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
&continuescan, false));
&continuescan, false, false));
if (passes_quals)
{
/* tuple passes all scan key conditions */
haveFirstMatch = true;
if (!BTreeTupleIsPosting(itup))
{
/* Remember it */
@ -1718,7 +1720,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
int truncatt;
truncatt = BTreeTupleGetNAtts(itup, scan->indexRelation);
_bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false);
_bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false, false);
}
if (!continuescan)
@ -1771,19 +1773,22 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
Assert(!BTreeTupleIsPivot(itup));
passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
&continuescan, requiredMatchedByPrecheck);
&continuescan,
continuescanPrechecked,
haveFirstMatch);
/*
* If the result of prechecking required keys was true, then in
* assert-enabled builds we also recheck that the _bt_checkkeys()
* result is the same.
*/
Assert(!requiredMatchedByPrecheck ||
Assert((!continuescanPrechecked && !haveFirstMatch) ||
passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
&continuescan, false));
&continuescan, false, false));
if (passes_quals && tuple_alive)
{
/* tuple passes all scan key conditions */
haveFirstMatch = true;
if (!BTreeTupleIsPosting(itup))
{
/* Remember it */
@ -2079,7 +2084,7 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir)
PredicateLockPage(rel, blkno, scan->xs_snapshot);
/* see if there are any matches on this page */
/* note that this will clear moreRight if we can stop */
if (_bt_readpage(scan, dir, P_FIRSTDATAKEY(opaque)))
if (_bt_readpage(scan, dir, P_FIRSTDATAKEY(opaque), false))
break;
}
else if (scan->parallel_scan != NULL)
@ -2170,7 +2175,7 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir)
PredicateLockPage(rel, BufferGetBlockNumber(so->currPos.buf), scan->xs_snapshot);
/* see if there are any matches on this page */
/* note that this will clear moreLeft if we can stop */
if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page)))
if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page), false))
break;
}
else if (scan->parallel_scan != NULL)
@ -2487,14 +2492,13 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
/* remember which buffer we have pinned */
so->currPos.buf = buf;
so->firstPage = true;
_bt_initialize_more_data(so, dir);
/*
* Now load data from the first page of the scan.
*/
if (!_bt_readpage(scan, dir, start))
if (!_bt_readpage(scan, dir, start, false))
{
/*
* There's no actually-matching data on this page. Try to advance to

View File

@ -1364,13 +1364,15 @@ _bt_mark_scankey_required(ScanKey skey)
* tupnatts: number of attributes in tupnatts (high key may be truncated)
* dir: direction we are scanning in
* continuescan: output parameter (will be set correctly in all cases)
* requiredMatchedByPrecheck: indicates that scan keys required for
* direction scan are already matched
* continuescanPrechecked: indicates that *continuescan flag is known to
* be true for the last item on the page
* haveFirstMatch: indicates that we already have at least one match
* in the current page
*/
bool
_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
ScanDirection dir, bool *continuescan,
bool requiredMatchedByPrecheck)
bool continuescanPrechecked, bool haveFirstMatch)
{
TupleDesc tupdesc;
BTScanOpaque so;
@ -1406,13 +1408,23 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
requiredOppositeDir = true;
/*
* Is the key required for scanning for either forward or backward
* direction? If so and caller told us that these types of keys are
* known to be matched, skip the check. Except for the row keys,
* where NULLs could be found in the middle of matching values.
* If the caller told us the *continuescan flag is known to be true
* for the last item on the page, then we know the keys required for
* the current direction scan should be matched. Otherwise, the
* *continuescan flag would be set for the current item and
* subsequently the last item on the page accordingly.
*
* If the key is required for the opposite direction scan, we can skip
* the check if the caller tells us there was already at least one
* matching item on the page. Also, we require the *continuescan flag
* to be true for the last item on the page to know there are no
* NULLs.
*
* Both cases above work except for the row keys, where NULLs could be
* found in the middle of matching values.
*/
if ((requiredSameDir || requiredOppositeDir) &&
!(key->sk_flags & SK_ROW_HEADER) && requiredMatchedByPrecheck)
if ((requiredSameDir || (requiredOppositeDir && haveFirstMatch)) &&
!(key->sk_flags & SK_ROW_HEADER) && continuescanPrechecked)
continue;
if (key->sk_attno > tupnatts)
@ -1513,12 +1525,12 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
}
/*
* Apply the key checking function. When the key is required for
* opposite direction scan, it must be already satisfied by
* _bt_first() except for the NULLs checking, which have already done
* above.
* Apply the key-checking function. When the key is required for the
* opposite direction scan, it must be already satisfied as soon as
* there is already match on the page. Except for the NULLs checking,
* which have already done above.
*/
if (!requiredOppositeDir)
if (!(requiredOppositeDir && haveFirstMatch))
{
test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
datum, key->sk_argument);

View File

@ -2280,7 +2280,7 @@ XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
char *from;
Size nbytes;
Size nleft;
int written;
ssize_t written;
instr_time start;
/* OK to write the page(s) */

View File

@ -117,8 +117,8 @@ static void perform_base_backup(basebackup_options *opt, bbsink *sink,
IncrementalBackupInfo *ib);
static void parse_basebackup_options(List *options, basebackup_options *opt);
static int compareWalFileNames(const ListCell *a, const ListCell *b);
static int basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
const char *filename, bool partial_read_ok);
static ssize_t basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
const char *filename, bool partial_read_ok);
/* Was the backup currently in-progress initiated in recovery mode? */
static bool backup_started_in_recovery = false;
@ -525,7 +525,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
{
char *walFileName = (char *) lfirst(lc);
int fd;
size_t cnt;
ssize_t cnt;
pgoff_t len = 0;
snprintf(pathbuf, MAXPGPATH, XLOGDIR "/%s", walFileName);
@ -2079,11 +2079,11 @@ convert_link_to_directory(const char *pathbuf, struct stat *statbuf)
*
* Returns the number of bytes read.
*/
static int
static ssize_t
basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
const char *filename, bool partial_read_ok)
{
int rc;
ssize_t rc;
pgstat_report_wait_start(WAIT_EVENT_BASEBACKUP_READ);
rc = pg_pread(fd, buf, nbytes, offset);
@ -2096,7 +2096,7 @@ basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
if (!partial_read_ok && rc > 0 && rc != nbytes)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not read file \"%s\": read %d of %zu",
errmsg("could not read file \"%s\": read %zd of %zu",
filename, rc, nbytes)));
return rc;

View File

@ -575,7 +575,7 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
tle->tli,
LSN_FORMAT_ARGS(tli_start_lsn),
LSN_FORMAT_ARGS(tli_end_lsn)),
errdetail("The first unsummarized LSN is this range is %X/%X.",
errdetail("The first unsummarized LSN in this range is %X/%X.",
LSN_FORMAT_ARGS(tli_missing_lsn))));
}

View File

@ -43,11 +43,8 @@ SET search_path TO information_schema;
CREATE FUNCTION _pg_expandarray(IN anyarray, OUT x anyelement, OUT n int)
RETURNS SETOF RECORD
LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE
AS 'select $1[s],
s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
pg_catalog.array_upper($1,1),
1) as g(s)';
ROWS 100 SUPPORT pg_catalog.array_unnest_support
AS 'SELECT * FROM pg_catalog.unnest($1) WITH ORDINALITY';
/* Given an index's OID and an underlying-table column number, return the
* column's position in the index (NULL if not there) */

View File

@ -438,7 +438,7 @@ GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact,
LWLockMode mode = reset_pending_lsn ? LW_EXCLUSIVE : LW_SHARED;
int n;
List *tles;
XLogRecPtr unsummarized_lsn;
XLogRecPtr unsummarized_lsn = InvalidXLogRecPtr;
TimeLineID unsummarized_tli = 0;
bool should_make_exact = false;
List *existing_summaries;

View File

@ -416,7 +416,7 @@ SyncRepInitConfig(void)
SpinLockRelease(&MyWalSnd->mutex);
ereport(DEBUG1,
(errmsg_internal("standby \"%s\" now has synchronous standby priority %u",
(errmsg_internal("standby \"%s\" now has synchronous standby priority %d",
application_name, priority)));
}
}
@ -483,7 +483,7 @@ SyncRepReleaseWaiters(void)
if (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY)
ereport(LOG,
(errmsg("standby \"%s\" is now a synchronous standby with priority %u",
(errmsg("standby \"%s\" is now a synchronous standby with priority %d",
application_name, MyWalSnd->sync_standby_priority)));
else
ereport(LOG,

View File

@ -6317,6 +6317,9 @@ array_unnest(PG_FUNCTION_ARGS)
/*
* Planner support function for array_unnest(anyarray)
*
* Note: this is now also used for information_schema._pg_expandarray(),
* which is simply a wrapper around array_unnest().
*/
Datum
array_unnest_support(PG_FUNCTION_ARGS)

View File

@ -538,7 +538,7 @@ check_control_files(int n_backups, char **backup_dirs)
/* Control file contents not meaningful if CRC is bad. */
if (!crc_ok)
pg_fatal("%s: crc is incorrect", controlpath);
pg_fatal("%s: CRC is incorrect", controlpath);
/* Can't interpret control file if not current version. */
if (control_file->pg_control_version != PG_CONTROL_VERSION)

View File

@ -504,7 +504,7 @@ make_rfile(char *filename, bool missing_ok)
static void
read_bytes(rfile *rf, void *buffer, unsigned length)
{
unsigned rb = read(rf->fd, buffer, length);
int rb = read(rf->fd, buffer, length);
if (rb != length)
{
@ -512,7 +512,7 @@ read_bytes(rfile *rf, void *buffer, unsigned length)
pg_fatal("could not read file \"%s\": %m", rf->filename);
else
pg_fatal("could not read file \"%s\": read only %d of %d bytes",
rf->filename, (int) rb, length);
rf->filename, rb, length);
}
}
@ -614,7 +614,7 @@ write_reconstructed_file(char *input_filename,
{
uint8 buffer[BLCKSZ];
rfile *s = sourcemap[i];
unsigned wb;
int wb;
/* Update accounting information. */
if (s == NULL)
@ -641,7 +641,7 @@ write_reconstructed_file(char *input_filename,
}
else
{
unsigned rb;
int rb;
/* Read the block from the correct source, except if dry-run. */
rb = pg_pread(s->fd, buffer, BLCKSZ, offsetmap[i]);
@ -650,9 +650,9 @@ write_reconstructed_file(char *input_filename,
if (rb < 0)
pg_fatal("could not read file \"%s\": %m", s->filename);
else
pg_fatal("could not read file \"%s\": read only %d of %d bytes at offset %u",
s->filename, (int) rb, BLCKSZ,
(unsigned) offsetmap[i]);
pg_fatal("could not read file \"%s\": read only %d of %d bytes at offset %llu",
s->filename, rb, BLCKSZ,
(unsigned long long) offsetmap[i]);
}
}
@ -663,7 +663,7 @@ write_reconstructed_file(char *input_filename,
pg_fatal("could not write file \"%s\": %m", output_filename);
else
pg_fatal("could not write file \"%s\": wrote only %d of %d bytes",
output_filename, (int) wb, BLCKSZ);
output_filename, wb, BLCKSZ);
}
/* Update the checksum computation. */

View File

@ -72,7 +72,7 @@ create_manifest_writer(char *directory)
*/
void
add_file_to_manifest(manifest_writer *mwriter, const char *manifest_path,
size_t size, pg_time_t mtime,
size_t size, time_t mtime,
pg_checksum_type checksum_type,
int checksum_length,
uint8 *checksum_payload)

View File

@ -13,7 +13,6 @@
#define WRITE_MANIFEST_H
#include "common/checksum_helper.h"
#include "pgtime.h"
struct manifest_wal_range;
@ -23,7 +22,7 @@ typedef struct manifest_writer manifest_writer;
extern manifest_writer *create_manifest_writer(char *directory);
extern void add_file_to_manifest(manifest_writer *mwriter,
const char *manifest_path,
size_t size, pg_time_t mtime,
size_t size, time_t mtime,
pg_checksum_type checksum_type,
int checksum_length,
uint8 *checksum_payload);

View File

@ -1051,9 +1051,6 @@ typedef struct BTScanOpaqueData
int *killedItems; /* currPos.items indexes of killed items */
int numKilled; /* number of currently stored items */
/* flag indicating the first page in the scan */
bool firstPage;
/*
* If we are doing an index-only scan, these are the tuple storage
* workspaces for the currPos and markPos respectively. Each is of size
@ -1254,7 +1251,7 @@ extern void _bt_restore_array_keys(IndexScanDesc scan);
extern void _bt_preprocess_keys(IndexScanDesc scan);
extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
int tupnatts, ScanDirection dir, bool *continuescan,
bool requiredMatchedByPrecheck);
bool requiredMatchedByPrecheck, bool haveFirstMatch);
extern void _bt_killitems(IndexScanDesc scan);
extern BTCycleId _bt_vacuum_cycleid(Relation rel);
extern BTCycleId _bt_start_vacuum(Relation rel);

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202312251
#define CATALOG_VERSION_NO 202312271
#endif

View File

@ -70,7 +70,7 @@ is(scalar(my @foobar = split /^/m, $result),
# If we immediately crash the server we might lose the progress we just made
# and replay the same changes again. But a clean shutdown should never repeat
# the same changes when we use the SQL decoding interface.
$node_primary->restart('fast');
$node_primary->restart;
# There are no new writes, so the result should be empty.
$result = $node_primary->safe_psql('postgres',

View File

@ -5293,26 +5293,30 @@ comment on function psql_df_plpgsql () is 'some comment';
rollback;
drop role regress_psql_user;
-- check \sf
\sf information_schema._pg_expandarray
CREATE OR REPLACE FUNCTION information_schema._pg_expandarray(anyarray, OUT x anyelement, OUT n integer)
RETURNS SETOF record
\sf information_schema._pg_index_position
CREATE OR REPLACE FUNCTION information_schema._pg_index_position(oid, smallint)
RETURNS integer
LANGUAGE sql
IMMUTABLE PARALLEL SAFE STRICT
AS $function$select $1[s],
s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
pg_catalog.array_upper($1,1),
1) as g(s)$function$
\sf+ information_schema._pg_expandarray
CREATE OR REPLACE FUNCTION information_schema._pg_expandarray(anyarray, OUT x anyelement, OUT n integer)
RETURNS SETOF record
STABLE STRICT
BEGIN ATOMIC
SELECT (ss.a).n AS n
FROM ( SELECT information_schema._pg_expandarray(pg_index.indkey) AS a
FROM pg_index
WHERE (pg_index.indexrelid = $1)) ss
WHERE ((ss.a).x = $2);
END
\sf+ information_schema._pg_index_position
CREATE OR REPLACE FUNCTION information_schema._pg_index_position(oid, smallint)
RETURNS integer
LANGUAGE sql
IMMUTABLE PARALLEL SAFE STRICT
1 AS $function$select $1[s],
2 s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
3 from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
4 pg_catalog.array_upper($1,1),
5 1) as g(s)$function$
STABLE STRICT
1 BEGIN ATOMIC
2 SELECT (ss.a).n AS n
3 FROM ( SELECT information_schema._pg_expandarray(pg_index.indkey) AS a
4 FROM pg_index
5 WHERE (pg_index.indexrelid = $1)) ss
6 WHERE ((ss.a).x = $2);
7 END
\sf+ interval_pl_time
CREATE OR REPLACE FUNCTION pg_catalog.interval_pl_time(interval, time without time zone)
RETURNS time without time zone

View File

@ -1312,8 +1312,8 @@ rollback;
drop role regress_psql_user;
-- check \sf
\sf information_schema._pg_expandarray
\sf+ information_schema._pg_expandarray
\sf information_schema._pg_index_position
\sf+ information_schema._pg_index_position
\sf+ interval_pl_time
\sf ts_debug(text)
\sf+ ts_debug(text)