mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 00:02:13 -04:00
Compare commits
No commits in common. "e83aa9f92fdd88c2912cc43a61fd9f59f4c8f4d3" and "3650e7a3933166b40f7f9043bd91f45d3467c74d" have entirely different histories.
e83aa9f92f
...
3650e7a393
@ -15,8 +15,6 @@
|
|||||||
# Make "html" the default target, since that is what most people tend
|
# Make "html" the default target, since that is what most people tend
|
||||||
# to want to use.
|
# to want to use.
|
||||||
html:
|
html:
|
||||||
# Note that all is *not* the default target in this directory
|
|
||||||
all: html man
|
|
||||||
|
|
||||||
# We don't need the tree-wide headers or install support here.
|
# We don't need the tree-wide headers or install support here.
|
||||||
NO_GENERATED_HEADERS=yes
|
NO_GENERATED_HEADERS=yes
|
||||||
@ -27,6 +25,8 @@ top_builddir = ../../..
|
|||||||
include $(top_builddir)/src/Makefile.global
|
include $(top_builddir)/src/Makefile.global
|
||||||
|
|
||||||
|
|
||||||
|
all: html man
|
||||||
|
|
||||||
|
|
||||||
ifndef DBTOEPUB
|
ifndef DBTOEPUB
|
||||||
DBTOEPUB = $(missing) dbtoepub
|
DBTOEPUB = $(missing) dbtoepub
|
||||||
@ -55,7 +55,7 @@ override XSLTPROCFLAGS += --stringparam pg.version '$(VERSION)'
|
|||||||
|
|
||||||
GENERATED_SGML = version.sgml \
|
GENERATED_SGML = version.sgml \
|
||||||
features-supported.sgml features-unsupported.sgml errcodes-table.sgml \
|
features-supported.sgml features-unsupported.sgml errcodes-table.sgml \
|
||||||
keywords-table.sgml targets-meson.sgml wait_event_types.sgml
|
keywords-table.sgml wait_event_types.sgml
|
||||||
|
|
||||||
ALLSGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML)
|
ALLSGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML)
|
||||||
|
|
||||||
@ -110,9 +110,6 @@ keywords-table.sgml: $(top_srcdir)/src/include/parser/kwlist.h $(wildcard $(srcd
|
|||||||
wait_event_types.sgml: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl
|
wait_event_types.sgml: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl
|
||||||
$(PERL) $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl --docs $<
|
$(PERL) $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl --docs $<
|
||||||
|
|
||||||
targets-meson.sgml: targets-meson.txt $(srcdir)/generate-targets-meson.pl
|
|
||||||
$(PERL) $(srcdir)/generate-targets-meson.pl $^ > $@
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## Generation of some text files.
|
## Generation of some text files.
|
||||||
##
|
##
|
||||||
|
@ -7510,12 +7510,11 @@ log_line_prefix = '%m [%p] %q%u@%d/%a '
|
|||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Causes each replication command and <literal>walsender</literal>
|
Causes each replication command to be logged in the server log.
|
||||||
process's replication slot acquisition/release to be logged in the
|
See <xref linkend="protocol-replication"/> for more information about
|
||||||
server log. See <xref linkend="protocol-replication"/> for more
|
replication command. The default value is <literal>off</literal>.
|
||||||
information about replication command. The default value is
|
Only superusers and users with the appropriate <literal>SET</literal>
|
||||||
<literal>off</literal>. Only superusers and users with the appropriate
|
privilege can change this setting.
|
||||||
<literal>SET</literal> privilege can change this setting.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -434,19 +434,20 @@ LOGLEVEL=-Dorg.apache.commons.logging.simplelog.defaultlog=WARN
|
|||||||
<title>Building the Documentation with Meson</title>
|
<title>Building the Documentation with Meson</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To build the documentation using Meson, change to the
|
Two options are provided for building the documentation using Meson.
|
||||||
<filename>build</filename> directory before running one of these commands,
|
Change to the <filename>build</filename> directory before running
|
||||||
or add <option>-C build</option> to the command.
|
one of these commands, or add <option>-C build</option> to the command.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To build just the <acronym>HTML</acronym> version of the documentation:
|
To build just the <acronym>HTML</acronym> version of the documentation:
|
||||||
<screen>
|
<screen>
|
||||||
<prompt>build$ </prompt><userinput>ninja html</userinput>
|
<prompt>build$ </prompt><userinput>ninja docs</userinput>
|
||||||
|
</screen>
|
||||||
|
To build all forms of the documentation:
|
||||||
|
<screen>
|
||||||
|
<prompt>build$ </prompt><userinput>ninja alldocs</userinput>
|
||||||
</screen>
|
</screen>
|
||||||
For a list of other documentation targets see
|
|
||||||
<xref linkend="targets-meson-documentation"/>.
|
|
||||||
|
|
||||||
The output appears in the
|
The output appears in the
|
||||||
subdirectory <filename>build/doc/src/sgml</filename>.
|
subdirectory <filename>build/doc/src/sgml</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
<!ENTITY high-availability SYSTEM "high-availability.sgml">
|
<!ENTITY high-availability SYSTEM "high-availability.sgml">
|
||||||
<!ENTITY installbin SYSTEM "install-binaries.sgml">
|
<!ENTITY installbin SYSTEM "install-binaries.sgml">
|
||||||
<!ENTITY installation SYSTEM "installation.sgml">
|
<!ENTITY installation SYSTEM "installation.sgml">
|
||||||
<!ENTITY targets-meson SYSTEM "targets-meson.sgml">
|
|
||||||
<!ENTITY installw SYSTEM "install-windows.sgml">
|
<!ENTITY installw SYSTEM "install-windows.sgml">
|
||||||
<!ENTITY maintenance SYSTEM "maintenance.sgml">
|
<!ENTITY maintenance SYSTEM "maintenance.sgml">
|
||||||
<!ENTITY manage-ag SYSTEM "manage-ag.sgml">
|
<!ENTITY manage-ag SYSTEM "manage-ag.sgml">
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
#!/usr/bin/perl
|
|
||||||
#
|
|
||||||
# Generate the targets-meson.sgml file from targets-meson.txt
|
|
||||||
# Copyright (c) 2000-2023, PostgreSQL Global Development Group
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
my $targets_meson_file = $ARGV[0];
|
|
||||||
open my $targets_meson, '<', $targets_meson_file or die;
|
|
||||||
|
|
||||||
print
|
|
||||||
"<!-- autogenerated from doc/src/sgml/targets-meson.txt, do not edit -->\n";
|
|
||||||
|
|
||||||
# Find the start of each group of targets
|
|
||||||
while (<$targets_meson>)
|
|
||||||
{
|
|
||||||
next if /^#/;
|
|
||||||
|
|
||||||
if (/^(.*) Targets:$/)
|
|
||||||
{
|
|
||||||
my $targets = $1;
|
|
||||||
my $targets_id = lc $targets;
|
|
||||||
|
|
||||||
print qq(
|
|
||||||
<sect3 id="targets-meson-$targets_id">
|
|
||||||
<title>$targets Targets</title>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
);
|
|
||||||
|
|
||||||
# Each target in the group
|
|
||||||
while (<$targets_meson>)
|
|
||||||
{
|
|
||||||
next if /^#/;
|
|
||||||
last if !/^\s+([^ ]+)\s+(.+)/;
|
|
||||||
|
|
||||||
my $target = $1;
|
|
||||||
my $desc = $2;
|
|
||||||
my $target_id = $1;
|
|
||||||
|
|
||||||
$target_id =~ s/\//-/g;
|
|
||||||
|
|
||||||
print qq(
|
|
||||||
<varlistentry id="meson-target-${target_id}">
|
|
||||||
<term><option>${target}</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
${desc}
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
print qq(
|
|
||||||
</variablelist>
|
|
||||||
</sect3>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close $targets_meson;
|
|
@ -3200,21 +3200,6 @@ ninja install
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</sect3>
|
</sect3>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="targets-meson">
|
|
||||||
<title><literal>meson</literal> Build Targets</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Individual build targets can be built using <command>ninja</command> <replaceable>target</replaceable>.
|
|
||||||
|
|
||||||
When no target is specified, everything except documentation is
|
|
||||||
built. Individual build products can be built using the path/filename as
|
|
||||||
<replaceable>target</replaceable>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
&targets-meson;
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="install-post">
|
<sect1 id="install-post">
|
||||||
|
@ -71,15 +71,6 @@ doc_generated += custom_target('keywords-table.sgml',
|
|||||||
capture: true,
|
capture: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
doc_generated += custom_target('targets-meson.sgml',
|
|
||||||
input: files('targets-meson.txt'),
|
|
||||||
output: 'targets-meson.sgml',
|
|
||||||
command: [perl, files('generate-targets-meson.pl'), '@INPUT@'],
|
|
||||||
build_by_default: false,
|
|
||||||
install: false,
|
|
||||||
capture: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
# For everything else we need at least xmllint
|
# For everything else we need at least xmllint
|
||||||
if not xmllint_bin.found()
|
if not xmllint_bin.found()
|
||||||
subdir_done()
|
subdir_done()
|
||||||
@ -151,8 +142,7 @@ if docs_dep.found()
|
|||||||
'--install-dir-contents', dir_doc_html, html],
|
'--install-dir-contents', dir_doc_html, html],
|
||||||
build_always_stale: true, build_by_default: false,
|
build_always_stale: true, build_by_default: false,
|
||||||
)
|
)
|
||||||
alias_target('html', html)
|
alias_target('install-doc-html', install_doc_html)
|
||||||
alias_target('install-html', install_doc_html)
|
|
||||||
|
|
||||||
# build and install multi-page html docs as part of docs target
|
# build and install multi-page html docs as part of docs target
|
||||||
docs += html
|
docs += html
|
||||||
@ -241,12 +231,11 @@ if docs_dep.found()
|
|||||||
'--install-dirs', dir_man, '@INPUT@'],
|
'--install-dirs', dir_man, '@INPUT@'],
|
||||||
build_always_stale: true, build_by_default: false,
|
build_always_stale: true, build_by_default: false,
|
||||||
)
|
)
|
||||||
alias_target('man', man)
|
alias_target('install-doc-man', install_doc_man)
|
||||||
alias_target('install-man', install_doc_man)
|
|
||||||
|
|
||||||
# built and installed as part of the the docs target
|
# even though we don't want to build man pages as part of 'docs', we do want
|
||||||
|
# to install them as part of install-docs
|
||||||
installdocs += install_doc_man
|
installdocs += install_doc_man
|
||||||
docs += man
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
# Copyright (c) 2023, PostgreSQL Global Development Group
|
|
||||||
#
|
|
||||||
# Description of important meson targets, used for the 'help' target and
|
|
||||||
# installation.sgml (via generate-targets-meson.pl). Right now the parsers are
|
|
||||||
# extremely simple. Both parsers ignore comments. The help target prints
|
|
||||||
# everything else. For xml everything without a leading newline is a group,
|
|
||||||
# remaining lines are target separated by whitespace from their description
|
|
||||||
#
|
|
||||||
Code Targets:
|
|
||||||
all Build everything other than documentation
|
|
||||||
backend Build backend and related modules
|
|
||||||
bin Build frontend binaries
|
|
||||||
contrib Build contrib modules
|
|
||||||
pl Build procedual languages
|
|
||||||
|
|
||||||
Developer Targets:
|
|
||||||
reformat-dat-files Rewrite catalog data files into standard format
|
|
||||||
expand-dat-files Expand all data files to include defaults
|
|
||||||
update-unicode Update unicode data to new version
|
|
||||||
|
|
||||||
Documentation Targets:
|
|
||||||
html Build documentation in multi-page HTML format
|
|
||||||
man Build documentation in man page format
|
|
||||||
docs Build documentation in multi-page HTML and man page format
|
|
||||||
doc/src/sgml/postgres-A4.pdf Build documentation in PDF format, with A4 pages
|
|
||||||
doc/src/sgml/postgres-US.pdf Build documentation in PDF format, with US letter pages
|
|
||||||
doc/src/sgml/postgres.html Build documentation in single-page HTML format
|
|
||||||
alldocs Build documentation in all supported formats
|
|
||||||
|
|
||||||
Installation Targets:
|
|
||||||
install Install postgres, excluding documentation
|
|
||||||
install-docs Install documentation in multi-page HTML and man page formats
|
|
||||||
install-html Install documentation in multi-page HTML format
|
|
||||||
install-man Install documentation in man page format
|
|
||||||
install-quiet Like "install", but installed files are not displayed
|
|
||||||
install-world Install postgres, including multi-page HTML and man page documentation
|
|
||||||
uninstall Remove installed files
|
|
||||||
|
|
||||||
Other Targets:
|
|
||||||
clean Remove all build products
|
|
||||||
test Run all enabled tests (including contrib)
|
|
||||||
world Build everything, including documentation
|
|
||||||
help List important targets
|
|
@ -3331,17 +3331,8 @@ alias_target('bin', bin_targets + [libpq_st])
|
|||||||
alias_target('pl', pl_targets)
|
alias_target('pl', pl_targets)
|
||||||
alias_target('contrib', contrib_targets)
|
alias_target('contrib', contrib_targets)
|
||||||
alias_target('testprep', testprep_targets)
|
alias_target('testprep', testprep_targets)
|
||||||
|
|
||||||
alias_target('world', all_built, docs)
|
|
||||||
alias_target('install-world', install_quiet, installdocs)
|
alias_target('install-world', install_quiet, installdocs)
|
||||||
|
|
||||||
run_target('help',
|
|
||||||
command: [
|
|
||||||
perl, '-ne', 'next if /^#/; print',
|
|
||||||
files('doc/src/sgml/targets-meson.txt'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
|
@ -235,10 +235,6 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
|
|||||||
* when a function has search_path set in proconfig. Add a search path cache
|
* when a function has search_path set in proconfig. Add a search path cache
|
||||||
* that can be used by recomputeNamespacePath().
|
* that can be used by recomputeNamespacePath().
|
||||||
*
|
*
|
||||||
* The cache is also used to remember already-validated strings in
|
|
||||||
* check_search_path() to avoid the need to call SplitIdentifierString()
|
|
||||||
* repeatedly.
|
|
||||||
*
|
|
||||||
* The search path cache is based on a wrapper around a simplehash hash table
|
* The search path cache is based on a wrapper around a simplehash hash table
|
||||||
* (nsphash, defined below). The spcache wrapper deals with OOM while trying
|
* (nsphash, defined below). The spcache wrapper deals with OOM while trying
|
||||||
* to initialize a key, and also offers a more convenient API.
|
* to initialize a key, and also offers a more convenient API.
|
||||||
@ -283,36 +279,40 @@ spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
|
|||||||
static nsphash_hash * SearchPathCache = NULL;
|
static nsphash_hash * SearchPathCache = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create or reset search_path cache as necessary.
|
* Create search path cache.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
spcache_init(void)
|
spcache_init(void)
|
||||||
{
|
{
|
||||||
Assert(SearchPathCacheContext);
|
Assert(SearchPathCacheContext);
|
||||||
|
|
||||||
if (SearchPathCache && searchPathCacheValid &&
|
if (SearchPathCache)
|
||||||
SearchPathCache->members < SPCACHE_RESET_THRESHOLD)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MemoryContextReset(SearchPathCacheContext);
|
|
||||||
/* arbitrary initial starting size of 16 elements */
|
/* arbitrary initial starting size of 16 elements */
|
||||||
SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL);
|
SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL);
|
||||||
searchPathCacheValid = true;
|
searchPathCacheValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up entry in search path cache without inserting. Returns NULL if not
|
* Reset and reinitialize search path cache.
|
||||||
* present.
|
|
||||||
*/
|
*/
|
||||||
static SearchPathCacheEntry *
|
static void
|
||||||
spcache_lookup(const char *searchPath, Oid roleid)
|
spcache_reset(void)
|
||||||
{
|
{
|
||||||
SearchPathCacheKey cachekey = {
|
Assert(SearchPathCacheContext);
|
||||||
.searchPath = searchPath,
|
Assert(SearchPathCache);
|
||||||
.roleid = roleid
|
|
||||||
};
|
|
||||||
|
|
||||||
return nsphash_lookup(SearchPathCache, cachekey);
|
MemoryContextReset(SearchPathCacheContext);
|
||||||
|
SearchPathCache = NULL;
|
||||||
|
|
||||||
|
spcache_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32
|
||||||
|
spcache_members(void)
|
||||||
|
{
|
||||||
|
return SearchPathCache->members;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -325,25 +325,27 @@ static SearchPathCacheEntry *
|
|||||||
spcache_insert(const char *searchPath, Oid roleid)
|
spcache_insert(const char *searchPath, Oid roleid)
|
||||||
{
|
{
|
||||||
SearchPathCacheEntry *entry;
|
SearchPathCacheEntry *entry;
|
||||||
|
bool found;
|
||||||
SearchPathCacheKey cachekey = {
|
SearchPathCacheKey cachekey = {
|
||||||
.searchPath = searchPath,
|
.searchPath = searchPath,
|
||||||
.roleid = roleid
|
.roleid = roleid
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* searchPath is not saved in SearchPathCacheContext. First perform a
|
* If a new entry is created, we must ensure that it's properly
|
||||||
* lookup, and copy searchPath only if we need to create a new entry.
|
* initialized. Set the cache invalid temporarily, so that if the
|
||||||
|
* MemoryContextStrdup() below raises an OOM, the cache will be reset on
|
||||||
|
* the next use, clearing the uninitialized entry.
|
||||||
*/
|
*/
|
||||||
entry = nsphash_lookup(SearchPathCache, cachekey);
|
searchPathCacheValid = false;
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
{
|
|
||||||
bool found;
|
|
||||||
|
|
||||||
cachekey.searchPath = MemoryContextStrdup(SearchPathCacheContext, searchPath);
|
|
||||||
entry = nsphash_insert(SearchPathCache, cachekey, &found);
|
entry = nsphash_insert(SearchPathCache, cachekey, &found);
|
||||||
Assert(!found);
|
|
||||||
|
|
||||||
|
/* ensure that key is initialized and the rest is zeroed */
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
entry->key.searchPath = MemoryContextStrdup(SearchPathCacheContext, searchPath);
|
||||||
|
entry->key.roleid = roleid;
|
||||||
entry->oidlist = NIL;
|
entry->oidlist = NIL;
|
||||||
entry->finalPath = NIL;
|
entry->finalPath = NIL;
|
||||||
entry->firstNS = InvalidOid;
|
entry->firstNS = InvalidOid;
|
||||||
@ -352,6 +354,7 @@ spcache_insert(const char *searchPath, Oid roleid)
|
|||||||
/* do not touch entry->status, used by simplehash */
|
/* do not touch entry->status, used by simplehash */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchPathCacheValid = true;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4180,15 +4183,31 @@ finalNamespacePath(List *oidlist, Oid *firstNS)
|
|||||||
/*
|
/*
|
||||||
* Retrieve search path information from the cache; or if not there, fill
|
* Retrieve search path information from the cache; or if not there, fill
|
||||||
* it. The returned entry is valid only until the next call to this function.
|
* it. The returned entry is valid only until the next call to this function.
|
||||||
|
*
|
||||||
|
* We also determine if the newly-computed finalPath is the same as the
|
||||||
|
* prevPath passed by the caller (i.e. a no-op or a real change?). It's more
|
||||||
|
* efficient to check for a change in this function than the caller, because
|
||||||
|
* we can avoid unnecessary temporary copies of the previous path.
|
||||||
*/
|
*/
|
||||||
static const SearchPathCacheEntry *
|
static const SearchPathCacheEntry *
|
||||||
cachedNamespacePath(const char *searchPath, Oid roleid)
|
cachedNamespacePath(const char *searchPath, Oid roleid, List *prevPath,
|
||||||
|
bool *same)
|
||||||
{
|
{
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
SearchPathCacheEntry *entry;
|
SearchPathCacheEntry *entry;
|
||||||
|
List *prevPathCopy = NIL;
|
||||||
|
|
||||||
spcache_init();
|
spcache_init();
|
||||||
|
|
||||||
|
/* invalidate cache if necessary */
|
||||||
|
if (!searchPathCacheValid || spcache_members() >= SPCACHE_RESET_THRESHOLD)
|
||||||
|
{
|
||||||
|
/* prevPath will be destroyed; make temp copy for later comparison */
|
||||||
|
prevPathCopy = list_copy(prevPath);
|
||||||
|
prevPath = prevPathCopy;
|
||||||
|
spcache_reset();
|
||||||
|
}
|
||||||
|
|
||||||
entry = spcache_insert(searchPath, roleid);
|
entry = spcache_insert(searchPath, roleid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4213,22 +4232,38 @@ cachedNamespacePath(const char *searchPath, Oid roleid)
|
|||||||
if (entry->finalPath == NIL || object_access_hook ||
|
if (entry->finalPath == NIL || object_access_hook ||
|
||||||
entry->forceRecompute)
|
entry->forceRecompute)
|
||||||
{
|
{
|
||||||
list_free(entry->finalPath);
|
/*
|
||||||
entry->finalPath = NIL;
|
* Do not free the stale value of entry->finalPath until we've
|
||||||
|
* performed the comparison, in case it's aliased by prevPath (which
|
||||||
|
* can only happen when recomputing due to an object_access_hook).
|
||||||
|
*/
|
||||||
|
List *finalPath;
|
||||||
|
|
||||||
oldcxt = MemoryContextSwitchTo(SearchPathCacheContext);
|
oldcxt = MemoryContextSwitchTo(SearchPathCacheContext);
|
||||||
entry->finalPath = finalNamespacePath(entry->oidlist,
|
finalPath = finalNamespacePath(entry->oidlist,
|
||||||
&entry->firstNS);
|
&entry->firstNS);
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
|
*same = equal(prevPath, finalPath);
|
||||||
|
|
||||||
|
list_free(entry->finalPath);
|
||||||
|
entry->finalPath = finalPath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If an object_access_hook is set when finalPath is calculated, the
|
* If an object_access_hook set when finalPath is calculated, the
|
||||||
* result may be affected by the hook. Force recomputation of
|
* result may be affected by the hook. Force recomputation of
|
||||||
* finalPath the next time this cache entry is used, even if the
|
* finalPath the next time this cache entry is used, even if the
|
||||||
* object_access_hook is not set at that time.
|
* object_access_hook is not set at that time.
|
||||||
*/
|
*/
|
||||||
entry->forceRecompute = object_access_hook ? true : false;
|
entry->forceRecompute = object_access_hook ? true : false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* use cached version of finalPath */
|
||||||
|
*same = equal(prevPath, entry->finalPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_free(prevPathCopy);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -4240,6 +4275,7 @@ static void
|
|||||||
recomputeNamespacePath(void)
|
recomputeNamespacePath(void)
|
||||||
{
|
{
|
||||||
Oid roleid = GetUserId();
|
Oid roleid = GetUserId();
|
||||||
|
bool newPathEqual;
|
||||||
bool pathChanged;
|
bool pathChanged;
|
||||||
const SearchPathCacheEntry *entry;
|
const SearchPathCacheEntry *entry;
|
||||||
|
|
||||||
@ -4247,32 +4283,24 @@ recomputeNamespacePath(void)
|
|||||||
if (baseSearchPathValid && namespaceUser == roleid)
|
if (baseSearchPathValid && namespaceUser == roleid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entry = cachedNamespacePath(namespace_search_path, roleid);
|
entry = cachedNamespacePath(namespace_search_path, roleid, baseSearchPath,
|
||||||
|
&newPathEqual);
|
||||||
|
|
||||||
if (baseCreationNamespace == entry->firstNS &&
|
if (baseCreationNamespace == entry->firstNS &&
|
||||||
baseTempCreationPending == entry->temp_missing &&
|
baseTempCreationPending == entry->temp_missing &&
|
||||||
equal(entry->finalPath, baseSearchPath))
|
newPathEqual)
|
||||||
{
|
{
|
||||||
pathChanged = false;
|
pathChanged = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryContext oldcxt;
|
|
||||||
List *newpath;
|
|
||||||
|
|
||||||
pathChanged = true;
|
pathChanged = true;
|
||||||
|
}
|
||||||
/* Must save OID list in permanent storage. */
|
|
||||||
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
|
||||||
newpath = list_copy(entry->finalPath);
|
|
||||||
MemoryContextSwitchTo(oldcxt);
|
|
||||||
|
|
||||||
/* Now safe to assign to state variables. */
|
/* Now safe to assign to state variables. */
|
||||||
list_free(baseSearchPath);
|
baseSearchPath = entry->finalPath;
|
||||||
baseSearchPath = newpath;
|
|
||||||
baseCreationNamespace = entry->firstNS;
|
baseCreationNamespace = entry->firstNS;
|
||||||
baseTempCreationPending = entry->temp_missing;
|
baseTempCreationPending = entry->temp_missing;
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark the path valid. */
|
/* Mark the path valid. */
|
||||||
baseSearchPathValid = true;
|
baseSearchPathValid = true;
|
||||||
@ -4597,40 +4625,11 @@ ResetTempTableNamespace(void)
|
|||||||
bool
|
bool
|
||||||
check_search_path(char **newval, void **extra, GucSource source)
|
check_search_path(char **newval, void **extra, GucSource source)
|
||||||
{
|
{
|
||||||
Oid roleid = InvalidOid;
|
|
||||||
const char *searchPath = *newval;
|
|
||||||
char *rawname;
|
char *rawname;
|
||||||
List *namelist;
|
List *namelist;
|
||||||
bool use_cache = (SearchPathCacheContext != NULL);
|
|
||||||
|
|
||||||
/*
|
/* Need a modifiable copy of string */
|
||||||
* We used to try to check that the named schemas exist, but there are
|
rawname = pstrdup(*newval);
|
||||||
* many valid use-cases for having search_path settings that include
|
|
||||||
* schemas that don't exist; and often, we are not inside a transaction
|
|
||||||
* here and so can't consult the system catalogs anyway. So now, the only
|
|
||||||
* requirement is syntactic validity of the identifier list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Checking only the syntactic validity also allows us to use the search
|
|
||||||
* path cache (if available) to avoid calling SplitIdentifierString() on
|
|
||||||
* the same string repeatedly.
|
|
||||||
*/
|
|
||||||
if (use_cache)
|
|
||||||
{
|
|
||||||
spcache_init();
|
|
||||||
|
|
||||||
roleid = GetUserId();
|
|
||||||
|
|
||||||
if (spcache_lookup(searchPath, roleid) != NULL)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure validity check succeeds before creating cache entry.
|
|
||||||
*/
|
|
||||||
|
|
||||||
rawname = pstrdup(searchPath); /* need a modifiable copy */
|
|
||||||
|
|
||||||
/* Parse string into list of identifiers */
|
/* Parse string into list of identifiers */
|
||||||
if (!SplitIdentifierString(rawname, ',', &namelist))
|
if (!SplitIdentifierString(rawname, ',', &namelist))
|
||||||
@ -4653,10 +4652,6 @@ check_search_path(char **newval, void **extra, GucSource source)
|
|||||||
pfree(rawname);
|
pfree(rawname);
|
||||||
list_free(namelist);
|
list_free(namelist);
|
||||||
|
|
||||||
/* create empty cache entry */
|
|
||||||
if (use_cache)
|
|
||||||
(void) spcache_insert(searchPath, roleid);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,16 +537,6 @@ retry:
|
|||||||
*/
|
*/
|
||||||
if (SlotIsLogical(s))
|
if (SlotIsLogical(s))
|
||||||
pgstat_acquire_replslot(s);
|
pgstat_acquire_replslot(s);
|
||||||
|
|
||||||
if (am_walsender)
|
|
||||||
{
|
|
||||||
ereport(log_replication_commands ? LOG : DEBUG1,
|
|
||||||
SlotIsLogical(s)
|
|
||||||
? errmsg("acquired logical replication slot \"%s\"",
|
|
||||||
NameStr(s->data.name))
|
|
||||||
: errmsg("acquired physical replication slot \"%s\"",
|
|
||||||
NameStr(s->data.name)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -559,17 +549,9 @@ void
|
|||||||
ReplicationSlotRelease(void)
|
ReplicationSlotRelease(void)
|
||||||
{
|
{
|
||||||
ReplicationSlot *slot = MyReplicationSlot;
|
ReplicationSlot *slot = MyReplicationSlot;
|
||||||
char *slotname = NULL; /* keep compiler quiet */
|
|
||||||
bool is_logical = false; /* keep compiler quiet */
|
|
||||||
|
|
||||||
Assert(slot != NULL && slot->active_pid != 0);
|
Assert(slot != NULL && slot->active_pid != 0);
|
||||||
|
|
||||||
if (am_walsender)
|
|
||||||
{
|
|
||||||
slotname = pstrdup(NameStr(slot->data.name));
|
|
||||||
is_logical = SlotIsLogical(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slot->data.persistency == RS_EPHEMERAL)
|
if (slot->data.persistency == RS_EPHEMERAL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -614,18 +596,6 @@ ReplicationSlotRelease(void)
|
|||||||
MyProc->statusFlags &= ~PROC_IN_LOGICAL_DECODING;
|
MyProc->statusFlags &= ~PROC_IN_LOGICAL_DECODING;
|
||||||
ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags;
|
ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags;
|
||||||
LWLockRelease(ProcArrayLock);
|
LWLockRelease(ProcArrayLock);
|
||||||
|
|
||||||
if (am_walsender)
|
|
||||||
{
|
|
||||||
ereport(log_replication_commands ? LOG : DEBUG1,
|
|
||||||
is_logical
|
|
||||||
? errmsg("released logical replication slot \"%s\"",
|
|
||||||
slotname)
|
|
||||||
: errmsg("released physical replication slot \"%s\"",
|
|
||||||
slotname));
|
|
||||||
|
|
||||||
pfree(slotname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1061,25 +1061,9 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
|
|||||||
ReplicationSlotCreate(cmd->slotname, false,
|
ReplicationSlotCreate(cmd->slotname, false,
|
||||||
cmd->temporary ? RS_TEMPORARY : RS_PERSISTENT,
|
cmd->temporary ? RS_TEMPORARY : RS_PERSISTENT,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
if (reserve_wal)
|
|
||||||
{
|
|
||||||
ReplicationSlotReserveWal();
|
|
||||||
|
|
||||||
ReplicationSlotMarkDirty();
|
|
||||||
|
|
||||||
/* Write this slot to disk if it's a permanent one. */
|
|
||||||
if (!cmd->temporary)
|
|
||||||
ReplicationSlotSave();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogicalDecodingContext *ctx;
|
|
||||||
bool need_full_snapshot = false;
|
|
||||||
|
|
||||||
Assert(cmd->kind == REPLICATION_KIND_LOGICAL);
|
|
||||||
|
|
||||||
CheckLogicalDecodingRequirements();
|
CheckLogicalDecodingRequirements();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1092,6 +1076,12 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
|
|||||||
ReplicationSlotCreate(cmd->slotname, true,
|
ReplicationSlotCreate(cmd->slotname, true,
|
||||||
cmd->temporary ? RS_TEMPORARY : RS_EPHEMERAL,
|
cmd->temporary ? RS_TEMPORARY : RS_EPHEMERAL,
|
||||||
two_phase);
|
two_phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->kind == REPLICATION_KIND_LOGICAL)
|
||||||
|
{
|
||||||
|
LogicalDecodingContext *ctx;
|
||||||
|
bool need_full_snapshot = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do options check early so that we can bail before calling the
|
* Do options check early so that we can bail before calling the
|
||||||
@ -1185,6 +1175,16 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
|
|||||||
if (!cmd->temporary)
|
if (!cmd->temporary)
|
||||||
ReplicationSlotPersist();
|
ReplicationSlotPersist();
|
||||||
}
|
}
|
||||||
|
else if (cmd->kind == REPLICATION_KIND_PHYSICAL && reserve_wal)
|
||||||
|
{
|
||||||
|
ReplicationSlotReserveWal();
|
||||||
|
|
||||||
|
ReplicationSlotMarkDirty();
|
||||||
|
|
||||||
|
/* Write this slot to disk if it's a permanent one. */
|
||||||
|
if (!cmd->temporary)
|
||||||
|
ReplicationSlotSave();
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(xloc, sizeof(xloc), "%X/%X",
|
snprintf(xloc, sizeof(xloc), "%X/%X",
|
||||||
LSN_FORMAT_ARGS(MyReplicationSlot->data.confirmed_flush));
|
LSN_FORMAT_ARGS(MyReplicationSlot->data.confirmed_flush));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user