mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 00:01:55 -04:00
Compare commits
12 Commits
e0477837ce
...
58054de2d0
Author | SHA1 | Date | |
---|---|---|---|
|
58054de2d0 | ||
|
6c361d323b | ||
|
3f1fd41631 | ||
|
390408ec08 | ||
|
a7ebd82b9e | ||
|
98c6231d19 | ||
|
da083b20f6 | ||
|
7e6fb5da41 | ||
|
06b10f80ba | ||
|
3e527aeeed | ||
|
3727b8d0e3 | ||
|
7d7ef075d2 |
@ -52,6 +52,12 @@ SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
|||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_statements_reset();
|
||||||
|
pg_stat_statements_reset
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
\d pg_stat_statements
|
\d pg_stat_statements
|
||||||
View "public.pg_stat_statements"
|
View "public.pg_stat_statements"
|
||||||
Column | Type | Collation | Nullable | Default
|
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
|
-- New functions and views for pg_stat_statements in 1.8
|
||||||
AlTER EXTENSION pg_stat_statements UPDATE TO '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
|
\d pg_stat_statements
|
||||||
View "public.pg_stat_statements"
|
View "public.pg_stat_statements"
|
||||||
Column | Type | Collation | Nullable | Default
|
Column | Type | Collation | Nullable | Default
|
||||||
@ -125,15 +142,10 @@ AlTER EXTENSION pg_stat_statements UPDATE TO '1.8';
|
|||||||
wal_fpi | bigint | | |
|
wal_fpi | bigint | | |
|
||||||
wal_bytes | numeric | | |
|
wal_bytes | numeric | | |
|
||||||
|
|
||||||
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
|
||||||
pg_get_functiondef
|
has_data
|
||||||
--------------------------------------------------------------------------------------------------------------------------------
|
----------
|
||||||
CREATE OR REPLACE FUNCTION public.pg_stat_statements_reset(userid oid DEFAULT 0, dbid oid DEFAULT 0, queryid bigint DEFAULT 0)+
|
t
|
||||||
RETURNS void +
|
|
||||||
LANGUAGE c +
|
|
||||||
PARALLEL SAFE STRICT +
|
|
||||||
AS '$libdir/pg_stat_statements', $function$pg_stat_statements_reset_1_7$function$ +
|
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- New function pg_stat_statement_info, and new function
|
-- New function pg_stat_statement_info, and new function
|
||||||
@ -324,4 +336,10 @@ SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
|||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
|
||||||
|
t
|
||||||
|
---
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
DROP EXTENSION pg_stat_statements;
|
DROP EXTENSION pg_stat_statements;
|
||||||
|
@ -28,13 +28,15 @@ SET SESSION AUTHORIZATION pg_read_all_stats;
|
|||||||
SELECT pg_stat_statements_reset();
|
SELECT pg_stat_statements_reset();
|
||||||
RESET SESSION AUTHORIZATION;
|
RESET SESSION AUTHORIZATION;
|
||||||
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
||||||
|
SELECT pg_stat_statements_reset();
|
||||||
\d pg_stat_statements
|
\d pg_stat_statements
|
||||||
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
|
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
|
||||||
|
|
||||||
-- New functions and views for pg_stat_statements in 1.8
|
-- New functions and views for pg_stat_statements in 1.8
|
||||||
AlTER EXTENSION pg_stat_statements UPDATE TO '1.8';
|
AlTER EXTENSION pg_stat_statements UPDATE TO '1.8';
|
||||||
\d pg_stat_statements
|
|
||||||
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
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
|
-- New function pg_stat_statement_info, and new function
|
||||||
-- and view for pg_stat_statements introduced in 1.9
|
-- 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;
|
SELECT count(*) > 0 AS has_data FROM pg_stat_statements;
|
||||||
-- New parameter minmax_only of pg_stat_statements_reset function
|
-- New parameter minmax_only of pg_stat_statements_reset function
|
||||||
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc);
|
||||||
|
SELECT pg_stat_statements_reset() IS NOT NULL AS t;
|
||||||
|
|
||||||
DROP EXTENSION pg_stat_statements;
|
DROP EXTENSION pg_stat_statements;
|
||||||
|
@ -2318,9 +2318,16 @@ REVOKE ALL ON accounts FROM PUBLIC;
|
|||||||
<primary><type>aclitem</type></primary>
|
<primary><type>aclitem</type></primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
The privileges that have been granted for a particular object are
|
The privileges that have been granted for a particular object are
|
||||||
displayed as a list of <type>aclitem</type> entries, where each
|
displayed as a list of <type>aclitem</type> entries, each having the
|
||||||
<type>aclitem</type> describes the permissions of one grantee that
|
format:
|
||||||
have been granted by a particular grantor. For example,
|
<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=r*w/hobbes</literal> specifies that the role
|
||||||
<literal>calvin</literal> has the privilege
|
<literal>calvin</literal> has the privilege
|
||||||
<literal>SELECT</literal> (<literal>r</literal>) with grant option
|
<literal>SELECT</literal> (<literal>r</literal>) with grant option
|
||||||
|
@ -409,7 +409,6 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
|
|||||||
|
|
||||||
so->markItemIndex = -1;
|
so->markItemIndex = -1;
|
||||||
so->arrayKeyCount = 0;
|
so->arrayKeyCount = 0;
|
||||||
so->firstPage = false;
|
|
||||||
BTScanPosUnpinIfPinned(so->markPos);
|
BTScanPosUnpinIfPinned(so->markPos);
|
||||||
BTScanPosInvalidate(so->markPos);
|
BTScanPosInvalidate(so->markPos);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ static OffsetNumber _bt_binsrch(Relation rel, BTScanInsert key, Buffer buf);
|
|||||||
static int _bt_binsrch_posting(BTScanInsert key, Page page,
|
static int _bt_binsrch_posting(BTScanInsert key, Page page,
|
||||||
OffsetNumber offnum);
|
OffsetNumber offnum);
|
||||||
static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir,
|
static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir,
|
||||||
OffsetNumber offnum);
|
OffsetNumber offnum, bool firstPage);
|
||||||
static void _bt_saveitem(BTScanOpaque so, int itemIndex,
|
static void _bt_saveitem(BTScanOpaque so, int itemIndex,
|
||||||
OffsetNumber offnum, IndexTuple itup);
|
OffsetNumber offnum, IndexTuple itup);
|
||||||
static int _bt_setuppostingitems(BTScanOpaque so, int itemIndex,
|
static int _bt_setuppostingitems(BTScanOpaque so, int itemIndex,
|
||||||
@ -1395,7 +1395,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
offnum = _bt_binsrch(rel, &inskey, buf);
|
offnum = _bt_binsrch(rel, &inskey, buf);
|
||||||
Assert(!BTScanPosIsValid(so->currPos));
|
Assert(!BTScanPosIsValid(so->currPos));
|
||||||
so->currPos.buf = buf;
|
so->currPos.buf = buf;
|
||||||
so->firstPage = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now load data from the first page of the scan.
|
* 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
|
* 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".
|
* 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
|
* 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.
|
* Returns true if any matching items found on the page, false if none.
|
||||||
*/
|
*/
|
||||||
static bool
|
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;
|
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||||
Page page;
|
Page page;
|
||||||
@ -1530,7 +1530,8 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
|
|||||||
int itemIndex;
|
int itemIndex;
|
||||||
bool continuescan;
|
bool continuescan;
|
||||||
int indnatts;
|
int indnatts;
|
||||||
bool requiredMatchedByPrecheck;
|
bool continuescanPrechecked;
|
||||||
|
bool haveFirstMatch = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We must have the buffer pinned and locked, but the usual macro can't be
|
* 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));
|
Assert(BTScanPosIsPinned(so->currPos));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prechecking the page with scan keys required for direction scan. We
|
* Prechecking the value of the continuescan flag for the last item on the
|
||||||
* check these keys with the last item on the page (according to our scan
|
* page (for backwards scan it will be the first item on a page). If we
|
||||||
* direction). If these keys are matched, we can skip checking them with
|
* observe it to be true, then it should be true for all other items. This
|
||||||
* every item on the page. Scan keys for our scan direction would
|
* allows us to do significant optimizations in the _bt_checkkeys()
|
||||||
* necessarily match the previous items. Scan keys required for opposite
|
* function for all the items on the page.
|
||||||
* direction scan are already matched by the _bt_first() call.
|
|
||||||
*
|
*
|
||||||
* With the forward scan, we do this check for the last item 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
|
* 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
|
* We skip this for the first page in the scan to evade the possible
|
||||||
* slowdown of the point queries.
|
* slowdown of the point queries.
|
||||||
*/
|
*/
|
||||||
if (!so->firstPage && minoff < maxoff)
|
if (!firstPage && minoff < maxoff)
|
||||||
{
|
{
|
||||||
ItemId iid;
|
ItemId iid;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
@ -1610,18 +1610,17 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
|
|||||||
itup = (IndexTuple) PageGetItem(page, iid);
|
itup = (IndexTuple) PageGetItem(page, iid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the precheck. Note that we pass the pointer to
|
* Do the precheck. Note that we pass the pointer to the
|
||||||
* 'requiredMatchedByPrecheck' to 'continuescan' argument. That will
|
* 'continuescanPrechecked' to the 'continuescan' argument. That will
|
||||||
* set flag to true if all required keys are satisfied and false
|
* set flag to true if all required keys are satisfied and false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
(void) _bt_checkkeys(scan, itup, indnatts, dir,
|
(void) _bt_checkkeys(scan, itup, indnatts, dir,
|
||||||
&requiredMatchedByPrecheck, false);
|
&continuescanPrechecked, false, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
so->firstPage = false;
|
continuescanPrechecked = false;
|
||||||
requiredMatchedByPrecheck = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScanDirectionIsForward(dir))
|
if (ScanDirectionIsForward(dir))
|
||||||
@ -1651,19 +1650,22 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
|
|||||||
Assert(!BTreeTupleIsPivot(itup));
|
Assert(!BTreeTupleIsPivot(itup));
|
||||||
|
|
||||||
passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
|
passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
|
||||||
&continuescan, requiredMatchedByPrecheck);
|
&continuescan,
|
||||||
|
continuescanPrechecked,
|
||||||
|
haveFirstMatch);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the result of prechecking required keys was true, then in
|
* If the result of prechecking required keys was true, then in
|
||||||
* assert-enabled builds we also recheck that the _bt_checkkeys()
|
* assert-enabled builds we also recheck that the _bt_checkkeys()
|
||||||
* result is the same.
|
* result is the same.
|
||||||
*/
|
*/
|
||||||
Assert(!requiredMatchedByPrecheck ||
|
Assert((!continuescanPrechecked && haveFirstMatch) ||
|
||||||
passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
|
passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
|
||||||
&continuescan, false));
|
&continuescan, false, false));
|
||||||
if (passes_quals)
|
if (passes_quals)
|
||||||
{
|
{
|
||||||
/* tuple passes all scan key conditions */
|
/* tuple passes all scan key conditions */
|
||||||
|
haveFirstMatch = true;
|
||||||
if (!BTreeTupleIsPosting(itup))
|
if (!BTreeTupleIsPosting(itup))
|
||||||
{
|
{
|
||||||
/* Remember it */
|
/* Remember it */
|
||||||
@ -1718,7 +1720,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
|
|||||||
int truncatt;
|
int truncatt;
|
||||||
|
|
||||||
truncatt = BTreeTupleGetNAtts(itup, scan->indexRelation);
|
truncatt = BTreeTupleGetNAtts(itup, scan->indexRelation);
|
||||||
_bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false);
|
_bt_checkkeys(scan, itup, truncatt, dir, &continuescan, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!continuescan)
|
if (!continuescan)
|
||||||
@ -1771,19 +1773,22 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum)
|
|||||||
Assert(!BTreeTupleIsPivot(itup));
|
Assert(!BTreeTupleIsPivot(itup));
|
||||||
|
|
||||||
passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
|
passes_quals = _bt_checkkeys(scan, itup, indnatts, dir,
|
||||||
&continuescan, requiredMatchedByPrecheck);
|
&continuescan,
|
||||||
|
continuescanPrechecked,
|
||||||
|
haveFirstMatch);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the result of prechecking required keys was true, then in
|
* If the result of prechecking required keys was true, then in
|
||||||
* assert-enabled builds we also recheck that the _bt_checkkeys()
|
* assert-enabled builds we also recheck that the _bt_checkkeys()
|
||||||
* result is the same.
|
* result is the same.
|
||||||
*/
|
*/
|
||||||
Assert(!requiredMatchedByPrecheck ||
|
Assert((!continuescanPrechecked && !haveFirstMatch) ||
|
||||||
passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
|
passes_quals == _bt_checkkeys(scan, itup, indnatts, dir,
|
||||||
&continuescan, false));
|
&continuescan, false, false));
|
||||||
if (passes_quals && tuple_alive)
|
if (passes_quals && tuple_alive)
|
||||||
{
|
{
|
||||||
/* tuple passes all scan key conditions */
|
/* tuple passes all scan key conditions */
|
||||||
|
haveFirstMatch = true;
|
||||||
if (!BTreeTupleIsPosting(itup))
|
if (!BTreeTupleIsPosting(itup))
|
||||||
{
|
{
|
||||||
/* Remember it */
|
/* Remember it */
|
||||||
@ -2079,7 +2084,7 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir)
|
|||||||
PredicateLockPage(rel, blkno, scan->xs_snapshot);
|
PredicateLockPage(rel, blkno, scan->xs_snapshot);
|
||||||
/* see if there are any matches on this page */
|
/* see if there are any matches on this page */
|
||||||
/* note that this will clear moreRight if we can stop */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
else if (scan->parallel_scan != NULL)
|
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);
|
PredicateLockPage(rel, BufferGetBlockNumber(so->currPos.buf), scan->xs_snapshot);
|
||||||
/* see if there are any matches on this page */
|
/* see if there are any matches on this page */
|
||||||
/* note that this will clear moreLeft if we can stop */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
else if (scan->parallel_scan != NULL)
|
else if (scan->parallel_scan != NULL)
|
||||||
@ -2487,14 +2492,13 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
/* remember which buffer we have pinned */
|
/* remember which buffer we have pinned */
|
||||||
so->currPos.buf = buf;
|
so->currPos.buf = buf;
|
||||||
so->firstPage = true;
|
|
||||||
|
|
||||||
_bt_initialize_more_data(so, dir);
|
_bt_initialize_more_data(so, dir);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now load data from the first page of the scan.
|
* 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
|
* There's no actually-matching data on this page. Try to advance to
|
||||||
|
@ -1364,13 +1364,15 @@ _bt_mark_scankey_required(ScanKey skey)
|
|||||||
* tupnatts: number of attributes in tupnatts (high key may be truncated)
|
* tupnatts: number of attributes in tupnatts (high key may be truncated)
|
||||||
* dir: direction we are scanning in
|
* dir: direction we are scanning in
|
||||||
* continuescan: output parameter (will be set correctly in all cases)
|
* continuescan: output parameter (will be set correctly in all cases)
|
||||||
* requiredMatchedByPrecheck: indicates that scan keys required for
|
* continuescanPrechecked: indicates that *continuescan flag is known to
|
||||||
* direction scan are already matched
|
* be true for the last item on the page
|
||||||
|
* haveFirstMatch: indicates that we already have at least one match
|
||||||
|
* in the current page
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
|
_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
|
||||||
ScanDirection dir, bool *continuescan,
|
ScanDirection dir, bool *continuescan,
|
||||||
bool requiredMatchedByPrecheck)
|
bool continuescanPrechecked, bool haveFirstMatch)
|
||||||
{
|
{
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
BTScanOpaque so;
|
BTScanOpaque so;
|
||||||
@ -1406,13 +1408,23 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, int tupnatts,
|
|||||||
requiredOppositeDir = true;
|
requiredOppositeDir = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is the key required for scanning for either forward or backward
|
* If the caller told us the *continuescan flag is known to be true
|
||||||
* direction? If so and caller told us that these types of keys are
|
* for the last item on the page, then we know the keys required for
|
||||||
* known to be matched, skip the check. Except for the row keys,
|
* the current direction scan should be matched. Otherwise, the
|
||||||
* where NULLs could be found in the middle of matching values.
|
* *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) &&
|
if ((requiredSameDir || (requiredOppositeDir && haveFirstMatch)) &&
|
||||||
!(key->sk_flags & SK_ROW_HEADER) && requiredMatchedByPrecheck)
|
!(key->sk_flags & SK_ROW_HEADER) && continuescanPrechecked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (key->sk_attno > tupnatts)
|
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
|
* Apply the key-checking function. When the key is required for the
|
||||||
* opposite direction scan, it must be already satisfied by
|
* opposite direction scan, it must be already satisfied as soon as
|
||||||
* _bt_first() except for the NULLs checking, which have already done
|
* there is already match on the page. Except for the NULLs checking,
|
||||||
* above.
|
* which have already done above.
|
||||||
*/
|
*/
|
||||||
if (!requiredOppositeDir)
|
if (!(requiredOppositeDir && haveFirstMatch))
|
||||||
{
|
{
|
||||||
test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
|
test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
|
||||||
datum, key->sk_argument);
|
datum, key->sk_argument);
|
||||||
|
@ -2280,7 +2280,7 @@ XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
|
|||||||
char *from;
|
char *from;
|
||||||
Size nbytes;
|
Size nbytes;
|
||||||
Size nleft;
|
Size nleft;
|
||||||
int written;
|
ssize_t written;
|
||||||
instr_time start;
|
instr_time start;
|
||||||
|
|
||||||
/* OK to write the page(s) */
|
/* OK to write the page(s) */
|
||||||
|
@ -117,8 +117,8 @@ static void perform_base_backup(basebackup_options *opt, bbsink *sink,
|
|||||||
IncrementalBackupInfo *ib);
|
IncrementalBackupInfo *ib);
|
||||||
static void parse_basebackup_options(List *options, basebackup_options *opt);
|
static void parse_basebackup_options(List *options, basebackup_options *opt);
|
||||||
static int compareWalFileNames(const ListCell *a, const ListCell *b);
|
static int compareWalFileNames(const ListCell *a, const ListCell *b);
|
||||||
static int basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
|
static ssize_t basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
|
||||||
const char *filename, bool partial_read_ok);
|
const char *filename, bool partial_read_ok);
|
||||||
|
|
||||||
/* Was the backup currently in-progress initiated in recovery mode? */
|
/* Was the backup currently in-progress initiated in recovery mode? */
|
||||||
static bool backup_started_in_recovery = false;
|
static bool backup_started_in_recovery = false;
|
||||||
@ -525,7 +525,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink,
|
|||||||
{
|
{
|
||||||
char *walFileName = (char *) lfirst(lc);
|
char *walFileName = (char *) lfirst(lc);
|
||||||
int fd;
|
int fd;
|
||||||
size_t cnt;
|
ssize_t cnt;
|
||||||
pgoff_t len = 0;
|
pgoff_t len = 0;
|
||||||
|
|
||||||
snprintf(pathbuf, MAXPGPATH, XLOGDIR "/%s", walFileName);
|
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.
|
* Returns the number of bytes read.
|
||||||
*/
|
*/
|
||||||
static int
|
static ssize_t
|
||||||
basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
|
basebackup_read_file(int fd, char *buf, size_t nbytes, off_t offset,
|
||||||
const char *filename, bool partial_read_ok)
|
const char *filename, bool partial_read_ok)
|
||||||
{
|
{
|
||||||
int rc;
|
ssize_t rc;
|
||||||
|
|
||||||
pgstat_report_wait_start(WAIT_EVENT_BASEBACKUP_READ);
|
pgstat_report_wait_start(WAIT_EVENT_BASEBACKUP_READ);
|
||||||
rc = pg_pread(fd, buf, nbytes, offset);
|
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)
|
if (!partial_read_ok && rc > 0 && rc != nbytes)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(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)));
|
filename, rc, nbytes)));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -575,7 +575,7 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
|
|||||||
tle->tli,
|
tle->tli,
|
||||||
LSN_FORMAT_ARGS(tli_start_lsn),
|
LSN_FORMAT_ARGS(tli_start_lsn),
|
||||||
LSN_FORMAT_ARGS(tli_end_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))));
|
LSN_FORMAT_ARGS(tli_missing_lsn))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,11 +43,8 @@ SET search_path TO information_schema;
|
|||||||
CREATE FUNCTION _pg_expandarray(IN anyarray, OUT x anyelement, OUT n int)
|
CREATE FUNCTION _pg_expandarray(IN anyarray, OUT x anyelement, OUT n int)
|
||||||
RETURNS SETOF RECORD
|
RETURNS SETOF RECORD
|
||||||
LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE
|
LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE
|
||||||
AS 'select $1[s],
|
ROWS 100 SUPPORT pg_catalog.array_unnest_support
|
||||||
s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
|
AS 'SELECT * FROM pg_catalog.unnest($1) WITH ORDINALITY';
|
||||||
from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
|
|
||||||
pg_catalog.array_upper($1,1),
|
|
||||||
1) as g(s)';
|
|
||||||
|
|
||||||
/* Given an index's OID and an underlying-table column number, return the
|
/* Given an index's OID and an underlying-table column number, return the
|
||||||
* column's position in the index (NULL if not there) */
|
* column's position in the index (NULL if not there) */
|
||||||
|
@ -438,7 +438,7 @@ GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact,
|
|||||||
LWLockMode mode = reset_pending_lsn ? LW_EXCLUSIVE : LW_SHARED;
|
LWLockMode mode = reset_pending_lsn ? LW_EXCLUSIVE : LW_SHARED;
|
||||||
int n;
|
int n;
|
||||||
List *tles;
|
List *tles;
|
||||||
XLogRecPtr unsummarized_lsn;
|
XLogRecPtr unsummarized_lsn = InvalidXLogRecPtr;
|
||||||
TimeLineID unsummarized_tli = 0;
|
TimeLineID unsummarized_tli = 0;
|
||||||
bool should_make_exact = false;
|
bool should_make_exact = false;
|
||||||
List *existing_summaries;
|
List *existing_summaries;
|
||||||
|
@ -416,7 +416,7 @@ SyncRepInitConfig(void)
|
|||||||
SpinLockRelease(&MyWalSnd->mutex);
|
SpinLockRelease(&MyWalSnd->mutex);
|
||||||
|
|
||||||
ereport(DEBUG1,
|
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)));
|
application_name, priority)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +483,7 @@ SyncRepReleaseWaiters(void)
|
|||||||
|
|
||||||
if (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY)
|
if (SyncRepConfig->syncrep_method == SYNC_REP_PRIORITY)
|
||||||
ereport(LOG,
|
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)));
|
application_name, MyWalSnd->sync_standby_priority)));
|
||||||
else
|
else
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
|
@ -6317,6 +6317,9 @@ array_unnest(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Planner support function for array_unnest(anyarray)
|
* 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
|
Datum
|
||||||
array_unnest_support(PG_FUNCTION_ARGS)
|
array_unnest_support(PG_FUNCTION_ARGS)
|
||||||
|
@ -538,7 +538,7 @@ check_control_files(int n_backups, char **backup_dirs)
|
|||||||
|
|
||||||
/* Control file contents not meaningful if CRC is bad. */
|
/* Control file contents not meaningful if CRC is bad. */
|
||||||
if (!crc_ok)
|
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. */
|
/* Can't interpret control file if not current version. */
|
||||||
if (control_file->pg_control_version != PG_CONTROL_VERSION)
|
if (control_file->pg_control_version != PG_CONTROL_VERSION)
|
||||||
|
@ -504,7 +504,7 @@ make_rfile(char *filename, bool missing_ok)
|
|||||||
static void
|
static void
|
||||||
read_bytes(rfile *rf, void *buffer, unsigned length)
|
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)
|
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);
|
pg_fatal("could not read file \"%s\": %m", rf->filename);
|
||||||
else
|
else
|
||||||
pg_fatal("could not read file \"%s\": read only %d of %d bytes",
|
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];
|
uint8 buffer[BLCKSZ];
|
||||||
rfile *s = sourcemap[i];
|
rfile *s = sourcemap[i];
|
||||||
unsigned wb;
|
int wb;
|
||||||
|
|
||||||
/* Update accounting information. */
|
/* Update accounting information. */
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
@ -641,7 +641,7 @@ write_reconstructed_file(char *input_filename,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned rb;
|
int rb;
|
||||||
|
|
||||||
/* Read the block from the correct source, except if dry-run. */
|
/* Read the block from the correct source, except if dry-run. */
|
||||||
rb = pg_pread(s->fd, buffer, BLCKSZ, offsetmap[i]);
|
rb = pg_pread(s->fd, buffer, BLCKSZ, offsetmap[i]);
|
||||||
@ -650,9 +650,9 @@ write_reconstructed_file(char *input_filename,
|
|||||||
if (rb < 0)
|
if (rb < 0)
|
||||||
pg_fatal("could not read file \"%s\": %m", s->filename);
|
pg_fatal("could not read file \"%s\": %m", s->filename);
|
||||||
else
|
else
|
||||||
pg_fatal("could not read file \"%s\": read only %d of %d bytes at offset %u",
|
pg_fatal("could not read file \"%s\": read only %d of %d bytes at offset %llu",
|
||||||
s->filename, (int) rb, BLCKSZ,
|
s->filename, rb, BLCKSZ,
|
||||||
(unsigned) offsetmap[i]);
|
(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);
|
pg_fatal("could not write file \"%s\": %m", output_filename);
|
||||||
else
|
else
|
||||||
pg_fatal("could not write file \"%s\": wrote only %d of %d bytes",
|
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. */
|
/* Update the checksum computation. */
|
||||||
|
@ -72,7 +72,7 @@ create_manifest_writer(char *directory)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
add_file_to_manifest(manifest_writer *mwriter, const char *manifest_path,
|
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,
|
pg_checksum_type checksum_type,
|
||||||
int checksum_length,
|
int checksum_length,
|
||||||
uint8 *checksum_payload)
|
uint8 *checksum_payload)
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#define WRITE_MANIFEST_H
|
#define WRITE_MANIFEST_H
|
||||||
|
|
||||||
#include "common/checksum_helper.h"
|
#include "common/checksum_helper.h"
|
||||||
#include "pgtime.h"
|
|
||||||
|
|
||||||
struct manifest_wal_range;
|
struct manifest_wal_range;
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ typedef struct manifest_writer manifest_writer;
|
|||||||
extern manifest_writer *create_manifest_writer(char *directory);
|
extern manifest_writer *create_manifest_writer(char *directory);
|
||||||
extern void add_file_to_manifest(manifest_writer *mwriter,
|
extern void add_file_to_manifest(manifest_writer *mwriter,
|
||||||
const char *manifest_path,
|
const char *manifest_path,
|
||||||
size_t size, pg_time_t mtime,
|
size_t size, time_t mtime,
|
||||||
pg_checksum_type checksum_type,
|
pg_checksum_type checksum_type,
|
||||||
int checksum_length,
|
int checksum_length,
|
||||||
uint8 *checksum_payload);
|
uint8 *checksum_payload);
|
||||||
|
@ -1051,9 +1051,6 @@ typedef struct BTScanOpaqueData
|
|||||||
int *killedItems; /* currPos.items indexes of killed items */
|
int *killedItems; /* currPos.items indexes of killed items */
|
||||||
int numKilled; /* number of currently stored 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
|
* If we are doing an index-only scan, these are the tuple storage
|
||||||
* workspaces for the currPos and markPos respectively. Each is of size
|
* 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 void _bt_preprocess_keys(IndexScanDesc scan);
|
||||||
extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
||||||
int tupnatts, ScanDirection dir, bool *continuescan,
|
int tupnatts, ScanDirection dir, bool *continuescan,
|
||||||
bool requiredMatchedByPrecheck);
|
bool requiredMatchedByPrecheck, bool haveFirstMatch);
|
||||||
extern void _bt_killitems(IndexScanDesc scan);
|
extern void _bt_killitems(IndexScanDesc scan);
|
||||||
extern BTCycleId _bt_vacuum_cycleid(Relation rel);
|
extern BTCycleId _bt_vacuum_cycleid(Relation rel);
|
||||||
extern BTCycleId _bt_start_vacuum(Relation rel);
|
extern BTCycleId _bt_start_vacuum(Relation rel);
|
||||||
|
@ -57,6 +57,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 202312251
|
#define CATALOG_VERSION_NO 202312271
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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
|
# 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
|
# and replay the same changes again. But a clean shutdown should never repeat
|
||||||
# the same changes when we use the SQL decoding interface.
|
# 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.
|
# There are no new writes, so the result should be empty.
|
||||||
$result = $node_primary->safe_psql('postgres',
|
$result = $node_primary->safe_psql('postgres',
|
||||||
|
@ -5293,26 +5293,30 @@ comment on function psql_df_plpgsql () is 'some comment';
|
|||||||
rollback;
|
rollback;
|
||||||
drop role regress_psql_user;
|
drop role regress_psql_user;
|
||||||
-- check \sf
|
-- check \sf
|
||||||
\sf information_schema._pg_expandarray
|
\sf information_schema._pg_index_position
|
||||||
CREATE OR REPLACE FUNCTION information_schema._pg_expandarray(anyarray, OUT x anyelement, OUT n integer)
|
CREATE OR REPLACE FUNCTION information_schema._pg_index_position(oid, smallint)
|
||||||
RETURNS SETOF record
|
RETURNS integer
|
||||||
LANGUAGE sql
|
LANGUAGE sql
|
||||||
IMMUTABLE PARALLEL SAFE STRICT
|
STABLE STRICT
|
||||||
AS $function$select $1[s],
|
BEGIN ATOMIC
|
||||||
s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
|
SELECT (ss.a).n AS n
|
||||||
from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
|
FROM ( SELECT information_schema._pg_expandarray(pg_index.indkey) AS a
|
||||||
pg_catalog.array_upper($1,1),
|
FROM pg_index
|
||||||
1) as g(s)$function$
|
WHERE (pg_index.indexrelid = $1)) ss
|
||||||
\sf+ information_schema._pg_expandarray
|
WHERE ((ss.a).x = $2);
|
||||||
CREATE OR REPLACE FUNCTION information_schema._pg_expandarray(anyarray, OUT x anyelement, OUT n integer)
|
END
|
||||||
RETURNS SETOF record
|
\sf+ information_schema._pg_index_position
|
||||||
|
CREATE OR REPLACE FUNCTION information_schema._pg_index_position(oid, smallint)
|
||||||
|
RETURNS integer
|
||||||
LANGUAGE sql
|
LANGUAGE sql
|
||||||
IMMUTABLE PARALLEL SAFE STRICT
|
STABLE STRICT
|
||||||
1 AS $function$select $1[s],
|
1 BEGIN ATOMIC
|
||||||
2 s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
|
2 SELECT (ss.a).n AS n
|
||||||
3 from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
|
3 FROM ( SELECT information_schema._pg_expandarray(pg_index.indkey) AS a
|
||||||
4 pg_catalog.array_upper($1,1),
|
4 FROM pg_index
|
||||||
5 1) as g(s)$function$
|
5 WHERE (pg_index.indexrelid = $1)) ss
|
||||||
|
6 WHERE ((ss.a).x = $2);
|
||||||
|
7 END
|
||||||
\sf+ interval_pl_time
|
\sf+ interval_pl_time
|
||||||
CREATE OR REPLACE FUNCTION pg_catalog.interval_pl_time(interval, time without time zone)
|
CREATE OR REPLACE FUNCTION pg_catalog.interval_pl_time(interval, time without time zone)
|
||||||
RETURNS time without time zone
|
RETURNS time without time zone
|
||||||
|
@ -1312,8 +1312,8 @@ rollback;
|
|||||||
drop role regress_psql_user;
|
drop role regress_psql_user;
|
||||||
|
|
||||||
-- check \sf
|
-- check \sf
|
||||||
\sf information_schema._pg_expandarray
|
\sf information_schema._pg_index_position
|
||||||
\sf+ information_schema._pg_expandarray
|
\sf+ information_schema._pg_index_position
|
||||||
\sf+ interval_pl_time
|
\sf+ interval_pl_time
|
||||||
\sf ts_debug(text)
|
\sf ts_debug(text)
|
||||||
\sf+ ts_debug(text)
|
\sf+ ts_debug(text)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user