<!--
-$PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.24 2004/07/21 20:22:57 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.25 2004/07/21 20:34:43 momjian Exp $
-->
<chapter id="plperl">
<note>
<para>
Users of source packages must specially enable the build of
- PL/Perl during the installation process. (Refer to <xref
- linkend="install-short"> for more information.) Users of
- binary packages might find PL/Perl in a separate subpackage.
-
+ PL/Perl during the installation process. (Refer to the installation
+ instructions for more information.) Users of binary packages
+ might find PL/Perl in a separate subpackage.
</para>
</note>
The body of the function is ordinary Perl code. Since the body of
the function is treated as a string by
<productname>PostgreSQL</productname>, it can be specified using
- dollar quoting (as shown above), or via the legacy single quote
+ dollar quoting (as shown above), or via the usual single quote
syntax (see <xref linkend="sql-syntax-strings"> for more
information).
</para>
</para>
<para>
- If an SQL <literal>NULL</literal> value<indexterm><primary>null
- value</><secondary sortas="PL/Perl">in PL/Perl</></indexterm> is
- passed to a function, the argument value will appear as
- <quote>undefined</> in Perl. The above function definition will not
- behave very nicely with <literal>NULL</literal> inputs (in fact, it
- will act as though they are zeroes). We could add <literal>STRICT</>
- to the function definition to make
- <productname>PostgreSQL</productname> do something more reasonable: if
- a <literal>NULL</literal> value is passed, the function will not be
- called at all, but will just return a <literal>NULL</literal> result
- automatically. Alternatively, we could check for undefined inputs in
- the function body. For example, suppose that we wanted
- <function>perl_max</function> with one <literal>NULL</literal> and one
- non-<literal>NULL</literal> argument to return the
- non-<literal>NULL</literal> argument, rather than a
- <literal>NULL</literal> value:
+ If an SQL null value<indexterm><primary>null value</><secondary
+ sortas="PL/Perl">in PL/Perl</></indexterm> is passed to a function,
+ the argument value will appear as <quote>undefined</> in Perl. The
+ above function definition will not behave very nicely with null
+ inputs (in fact, it will act as though they are zeroes). We could
+ add <literal>STRICT</> to the function definition to make
+ <productname>PostgreSQL</productname> do something more reasonable:
+ if a null value is passed, the function will not be called at all,
+ but will just return a null result automatically. Alternatively,
+ we could check for undefined inputs in the function body. For
+ example, suppose that we wanted <function>perl_max</function> with
+ one null and one non-null argument to return the non-null argument,
+ rather than a null value:
<programlisting>
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
</para>
<para>
- As shown above, to return an SQL <literal>NULL</literal> value from
- a PL/Perl function, return an undefined value. This can be done
- whether the function is strict or not.
+ As shown above, to return an SQL null value from a PL/Perl
+ function, return an undefined value. This can be done whether the
+ function is strict or not.
</para>
<para>
CREATE FUNCTION empcomp(employee) RETURNS integer AS $$
my ($emp) = @_;
- return $emp->{basesalary} + $emp->{bonus};
+ return $emp->{'basesalary'} + $emp->{'bonus'};
$$ LANGUAGE plperl;
SELECT name, empcomp(employee) FROM employee;
</para>
<para>
- There is now support for returning a composite-type result value.
+ There is currently no support for returning a composite-type result
+ value.
</para>
+ <tip>
+ <para>
+ Because the function body is passed as an SQL string literal to
+ <command>CREATE FUNCTION</command>, you have to use dollar quoting
+ or escape single quotes and backslashes within your Perl source,
+ typically by doubling them. Another possible approach is to avoid
+ writing single quotes by using Perl's extended quoting operators
+ (<literal>q[]</literal>, <literal>qq[]</literal>,
+ <literal>qw[]</literal>).
+ </para>
+ </tip>
+ </sect1>
+
+ <sect1 id="plperl-data">
+ <title>Data Values in PL/Perl</title>
+
+ <para>
+ The argument values supplied to a PL/Perl function's code are
+ simply the input arguments converted to text form (just as if they
+ had been displayed by a <command>SELECT</command> statement).
+ Conversely, the <literal>return</> command will accept any string
+ that is acceptable input format for the function's declared return
+ type. So, the PL/Perl programmer can manipulate data values as if
+ they were just text.
+ </para>
</sect1>
<sect1 id="plperl-database">
<para>
Access to the database itself from your Perl function can be done via
- spi_exec_query, or via an experimental module <ulink
+ an experimental module <ulink
url="http://www.cpan.org/modules/by-module/DBD/APILOS/"><literal>DBD::PgSPI</literal></ulink>
(also available at <ulink url="http://www.cpan.org/SITES.html"><acronym>CPAN</>
- mirror sites</ulink>). This module makes available a
+ mirror sites</ulink>). This module makes available a
<acronym>DBI</>-compliant database-handle named
<varname>$pg_dbh</varname> that can be used to perform queries
with normal <acronym>DBI</> syntax.<indexterm><primary>DBI</></indexterm>
-
</para>
<para>
- PL/Perl itself presently provides two additional Perl commands:
+ PL/Perl itself presently provides only one additional Perl command:
<variablelist>
<varlistentry>
- <indexterm>
- <primary>spi_exec_query</primary>
- <secondary>in PL/Perl</secondary>
- </indexterm>
<indexterm>
<primary>elog</primary>
<secondary>in PL/Perl</secondary>
</indexterm>
- <term><function>spi_exec_query(</> [ <replaceable>SELECT query</replaceable> [, <replaceable>max_rows</replaceable>]] | [<replaceable>non-SELECT query</replaceable>] ) </term>
- <listitem>
- <para>
- Here is an example of a SELECT query with the optional maximum
-number of rows.
-<programlisting>
-$rv = spi_exec_query('SELECT * from my_table', 5);
-</programlisting>
-
-This returns up to 5 rows from my_table.
- </para>
- <para>
-If my_table has a column my_column, it would be accessed as
-<programlisting>
-$foo = $rv->{rows}[$i]->{my_column};
-</programlisting>
- </para>
- <para>
-The number of rows actually returned would be:
-<programlisting>
-$nrows = @{$rv->{rows}};
-</programlisting>
- </para>
- <para>
-Here is an example using a non-SELECT statement.
-<programlisting>
-$query = "INSERT INTO my_table VALUES (1, 'test')";
-$rv = spi_exec_query($query);
-</programlisting>
-
-You can then access status (SPI_OK_INSERT, e.g.) like this.
-<programlisting>
-$res = $rv->{status};
-</programlisting>
-
- </para>
- <para>
-To get the rows affected, do:
-<programlisting>
-$nrows = $rv->{rows};
-</programlisting>
- </para>
-
- </listitem>
-
- </varlistentry>
- <varlistentry>
<term><function>elog</> <replaceable>level</replaceable>, <replaceable>msg</replaceable></term>
<listitem>
<para>
</para>
</sect1>
- <sect1 id="plperl-data">
- <title>Data Values in PL/Perl</title>
-
- <para>
- The argument values supplied to a PL/Perl function's code are
- simply the input arguments converted to text form (just as if they
- had been displayed by a <command>SELECT</command> statement).
- Conversely, the <literal>return</> command will accept any string
- that is acceptable input format for the function's declared return
- type. So, the PL/Perl programmer can manipulate data values as if
- they were just text.
- </para>
-
- <para>
- PL/Perl can now return rowsets and composite types, and rowsets of
-composite types.
- </para>
-
- <para>
- Here is an example of a PL/Perl function returning a rowset of a row type:
-<programlisting>
-CREATE TABLE test (
- i int,
- v varchar
-);
-
-INSERT INTO test (i, v) VALUES (1,'first line');
-INSERT INTO test (i, v) VALUES (2,'second line');
-INSERT INTO test (i, v) VALUES (3,'third line');
-INSERT INTO test (i, v) VALUES (4,'immortal');
-
-create function test_munge() returns setof test language plperl as $$
- my $res = [];
- my $rv = spi_exec_query('select i,v from test;');
- my $status = $rv->{status};
- my $rows = @{$rv->{rows}};
- my $processed = $rv->{processed};
- foreach my $rn (0..$rows-1) {
- my $row = $rv->{rows}[$rn];
- $row->{i} += 200 if defined($row->{i});
- $row->{v} =~ tr/A-Za-z/a-zA-Z/ if (defined($row->{v}));
- push @$res,$row;
- }
- return $res;
-$$;
-
-select * from test_munge();
-</programlisting>
- </para>
-
- <para>
- Here is an example of a PL/Perl function returning a composite type:
- <programlisting>
-CREATE TYPE testrowperl AS (f1 integer, f2 text, f3 text);
-
-CREATE OR REPLACE FUNCTION perl_row() RETURNS testrowperl AS $$
-
- return {f2 => 'hello', f1 => 1, f3 => 'world'};
-
-$$ LANGUAGE plperl;
- </programlisting>
- </para>
-
- <para>
- Here is an example of a PL/Perl function returning a rowset of a composite type.
- <programlisting>
-CREATE TYPE testsetperl AS (f1 integer, f2 text, f3 text);
-
-CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testsetperl AS $$
- return[
- {f1 => 1, f2 => 'hello', f3 => 'world'},
- {f1 => 2, f2 => 'hello', f3 => 'postgres'},
- {f1 => 3, f2 => 'hello', f3 => 'plperl'}
- ];
-$$ LANGUAGE plperl;
- </programlisting>
- </para>
- </sect1>
- <sect1 id="plperl-global">
- <title>Global Values in PL/Perl</title>
- <para>
- You can use the %_SHARED to store data between function calls. WHY
-IS THIS A HASH, AND NOT A HASH REF?
- </para>
- <para>
-For example:
-<programlisting>
-CREATE OR REPLACE FUNCTION set_var(TEXT) RETURNS TEXT AS $$
- $_SHARED{first} = 'Hello, PL/Perl!';
- return 'ok';
-$$ LANGUAGE plperl;
-
-CREATE OR REPLACE FUNCTION get_var() RETURNS text AS $$
- return $_SHARED{first};
-$$ LANGUAGE plperl;
-
-SELECT set_var('hello plperl');
-SELECT get_var();
-</programlisting>
-
- </para>
-
-
- </sect1>
-
<sect1 id="plperl-trusted">
<title>Trusted and Untrusted PL/Perl</title>
<literal>plperlu</>, execution would succeed.
</para>
</sect1>
- <sect1 id="plperl-triggers">
- <title>PL/Perl Triggers</title>
-
- <para>
- PL/Perl can now be used to write trigger functions using the
-<varname>$_TD</varname> hash reference.
- </para>
-
- <para>
- Some useful parts of the $_TD hash reference are:
-
-<programlisting>
-$_TD->{new}{foo} # NEW value of column foo
-$_TD->{old}{bar} # OLD value of column bar
-$_TD{name} # Name of the trigger being called
-$_TD{event} # INSERT, UPDATE, DELETE or UNKNOWN
-$_TD{when} # BEFORE, AFTER or UNKNOWN
-$_TD{level} # ROW, STATEMENT or UNKNOWN
-$_TD{relid} # Relation ID of the table on which the trigger occurred.
-$_TD{relname} # Name of the table on which the trigger occurred.
-@{$_TD{argv}} # Array of arguments to the trigger function. May be empty.
-$_TD{argc} # Number of arguments to the trigger. Why is this here?
-</programlisting>
-
- </para>
-
- <para>
- Triggers can return one of the following:
-<programlisting>
-return; -- Executes the statement
-SKIP; -- Doesn't execute the statement
-MODIFY; -- Says it modified a NEW row
-</programlisting>
- </para>
-
- <para>
-Here is an example of a trigger function, illustrating some of the
-above.
-<programlisting>
-CREATE TABLE test (
- i int,
- v varchar
-);
-
-CREATE OR REPLACE FUNCTION valid_id() RETURNS trigger AS $$
- if (($_TD->{new}{i}>=100) || ($_TD->{new}{i}<=0)) {
- return "SKIP"; # Skip INSERT/UPDATE command
- } elsif ($_TD->{new}{v} ne "immortal") {
- $_TD->{new}{v} .= "(modified by trigger)";
- return "MODIFY"; # Modify tuple and proceed INSERT/UPDATE command
- } else {
- return; # Proceed INSERT/UPDATE command
- }
-$$ LANGUAGE plperl;
-
-CREATE TRIGGER "test_valid_id_trig" BEFORE INSERT OR UPDATE ON test
-FOR EACH ROW EXECUTE PROCEDURE "valid_id"();
-</programlisting>
- </para>
- </sect1>
<sect1 id="plperl-missing">
- <title>Limitations and Missing Features</title>
+ <title>Missing Features</title>
<para>
The following features are currently missing from PL/Perl, but they
<listitem>
<para>
PL/Perl functions cannot call each other directly (because they
- are anonymous subroutines inside Perl).
+ are anonymous subroutines inside Perl). There's presently no
+ way for them to share global variables, either.
</para>
</listitem>
<listitem>
<para>
- <application>Full SPI</application> is not yet implemented.
+ PL/Perl cannot be used to write trigger
+ functions.<indexterm><primary>trigger</><secondary>in
+ PL/Perl</></indexterm>
</para>
</listitem>
+
<listitem>
- <para>
- In the current implementation, if you are fetching or
- returning very large datasets, you should be aware that these
- will all go into memory. Future features will help with this.
- In the meantime, we suggest that you not use pl/perl if you
- will fetch or return very large result sets.
- </para>
+ <para>
+ <application>DBD::PgSPI</applicatioN> or similar capability
+ should be integrated into the standard
+ <productname>PostgreSQL</productname> distribution.
+ </para>
</listitem>
-
</itemizedlist>
</para>
</sect1>
#
# Copyright (c) 1994, Regents of the University of California
#
-# $PostgreSQL: pgsql/src/backend/Makefile,v 1.102 2004/07/21 20:22:58 momjian Exp $
+# $PostgreSQL: pgsql/src/backend/Makefile,v 1.103 2004/07/21 20:34:44 momjian Exp $
#
#-------------------------------------------------------------------------
##########################################################################
-all: submake-libpgport submake-libpq postgres $(POSTGRES_IMP)
+all: submake-libpgport postgres $(POSTGRES_IMP)
ifneq ($(PORTNAME), cygwin)
ifneq ($(PORTNAME), win32)
postgres: $(OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -I $(libpq_srcdir) $(export_dynamic) $^ $(LIBS) $(libpq) -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $^ $(LIBS) -o $@
endif
endif
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.188 2004/07/21 20:22:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.189 2004/07/21 20:34:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "postmaster/bgwriter.h"
-#include "postmaster/pg_autovacuum.h"
#include "storage/freespace.h"
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
case BS_XLOG_BGWRITER:
statmsg = "writer process";
break;
- case BS_XLOG_AUTOVAC:
- statmsg = "auto vacuum process";
- break;
default:
statmsg = "??? process";
break;
case BS_XLOG_BGWRITER:
InitDummyProcess(DUMMY_PROC_BGWRITER);
break;
- case BS_XLOG_AUTOVAC:
- InitDummyProcess(DUMMY_PROC_AUTOVAC);
- break;
default:
InitDummyProcess(DUMMY_PROC_DEFAULT);
BackgroundWriterMain();
proc_exit(1); /* should never return */
- case BS_XLOG_AUTOVAC:
- /* don't set signals, autovac has its own agenda */
- InitXLOGAccess();
- AutoVacMain();
- proc_exit(1); /* should never return */
-
default:
elog(PANIC, "unrecognized XLOG op: %d", xlogop);
proc_exit(1);
#
# Makefile for backend/catalog
#
-# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.52 2004/07/21 20:22:59 momjian Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.53 2004/07/21 20:34:45 momjian Exp $
#
#-------------------------------------------------------------------------
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
pg_namespace.h pg_conversion.h pg_database.h pg_shadow.h pg_group.h \
- pg_tablespace.h pg_depend.h pg_autovacuum.h indexing.h \
+ pg_tablespace.h pg_depend.h indexing.h \
)
pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
*
* Copyright 1996-2003, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.7 2004/07/21 20:22:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.8 2004/07/21 20:34:45 momjian Exp $
*/
CREATE VIEW pg_user AS
SELECT
N.nspname AS schemaname,
C.relname AS tablename,
- T.spcname AS tablespace,
pg_get_userbyid(C.relowner) AS tableowner,
C.relhasindex AS hasindexes,
C.relhasrules AS hasrules,
(C.reltriggers > 0) AS hastriggers
FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
- LEFT JOIN pg_tablespace T ON (T.oid = C.reltablespace)
WHERE C.relkind = 'r';
CREATE VIEW pg_indexes AS
SELECT
N.nspname AS schemaname,
C.relname AS tablename,
- T.spcname AS tablespace,
I.relname AS indexname,
pg_get_indexdef(I.oid) AS indexdef
FROM pg_index X JOIN pg_class C ON (C.oid = X.indrelid)
JOIN pg_class I ON (I.oid = X.indexrelid)
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
- LEFT JOIN pg_tablespace T ON (T.oid = C.reltablespace)
WHERE C.relkind = 'r' AND I.relkind = 'i';
CREATE VIEW pg_stats AS
# Makefile for src/backend/postmaster
#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/backend/postmaster/Makefile,v 1.17 2004/07/21 20:22:59 momjian Exp $
+# $PostgreSQL: pgsql/src/backend/postmaster/Makefile,v 1.18 2004/07/21 20:34:46 momjian Exp $
#
#-------------------------------------------------------------------------
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-OBJS = postmaster.o bgwriter.o pgstat.o pgarch.o pg_autovacuum.o
+OBJS = postmaster.o bgwriter.o pgstat.o pgarch.o
all: SUBSYS.o
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.413 2004/07/21 20:22:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.414 2004/07/21 20:34:46 momjian Exp $
*
* NOTES
*
* The Postmaster cleans up after backends if they have an emergency
* exit and/or core dump.
*
+ * Error Reporting:
+ * Use write_stderr() only for reporting "interactive" errors
+ * (essentially, bogus arguments on the command line). Once the
+ * postmaster is launched, use ereport(). In particular, don't use
+ * write_stderr() for anything that occurs after pmdaemonize.
+ *
*-------------------------------------------------------------------------
*/
static pid_t StartupPID = 0,
BgWriterPID = 0,
PgArchPID = 0,
- AutoVacPID = 0,
PgStatPID = 0;
/* Startup/shutdown state */
static int CountChildren(void);
static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
static pid_t StartChildProcess(int xlop);
-static void postmaster_error(const char *fmt,...);
#ifdef EXEC_BACKEND
#define StartupDataBase() StartChildProcess(BS_XLOG_STARTUP)
#define StartBackgroundWriter() StartChildProcess(BS_XLOG_BGWRITER)
-#define StartAutoVac() StartChildProcess(BS_XLOG_AUTOVAC)
/*
#ifdef USE_ASSERT_CHECKING
SetConfigOption("debug_assertions", optarg, PGC_POSTMASTER, PGC_S_ARGV);
#else
- postmaster_error("assert checking is not compiled in");
+ write_stderr("%s: assert checking is not compiled in\n", progname);
#endif
break;
case 'a':
}
default:
- fprintf(stderr,
- gettext("Try \"%s --help\" for more information.\n"),
- progname);
+ write_stderr("Try \"%s --help\" for more information.\n",
+ progname);
ExitPostmaster(1);
}
}
*/
if (optind < argc)
{
- postmaster_error("invalid argument: \"%s\"", argv[optind]);
- fprintf(stderr,
- gettext("Try \"%s --help\" for more information.\n"),
- progname);
+ write_stderr("%s: invalid argument: \"%s\"\n",
+ progname, argv[optind]);
+ write_stderr("Try \"%s --help\" for more information.\n",
+ progname);
ExitPostmaster(1);
}
* for lack of buffers. The specific choices here are somewhat
* arbitrary.
*/
- postmaster_error("the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16");
+ write_stderr("%s: the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16\n", progname);
ExitPostmaster(1);
}
if (ReservedBackends >= MaxBackends)
{
- postmaster_error("superuser_reserved_connections must be less than max_connections");
+ write_stderr("%s: superuser_reserved_connections must be less than max_connections\n", progname);
ExitPostmaster(1);
}
*/
if (!CheckDateTokenTables())
{
- postmaster_error("invalid datetoken tables, please fix");
+ write_stderr("%s: invalid datetoken tables, please fix\n", progname);
ExitPostmaster(1);
}
* CAUTION: when changing this list, check for side-effects on the signal
* handling setup of child processes. See tcop/postgres.c,
* bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/pgarch.c,
- * postmaster/pgstat.c, and postmaster/pg_autovacuum.c.
+ * and postmaster/pgstat.c.
*/
pqinitmask();
PG_SETMASK(&BlockSig);
fp = AllocateFile(path, PG_BINARY_R);
if (fp == NULL)
{
- fprintf(stderr,
- gettext("%s: could not find the database system\n"
- "Expected to find it in the directory \"%s\",\n"
- "but could not open file \"%s\": %s\n"),
- progname, checkdir, path, strerror(errno));
+ write_stderr("%s: could not find the database system\n"
+ "Expected to find it in the directory \"%s\",\n"
+ "but could not open file \"%s\": %s\n",
+ progname, checkdir, path, strerror(errno));
ExitPostmaster(2);
}
FreeFile(fp);
pid = fork();
if (pid == (pid_t) -1)
{
- postmaster_error("could not fork background process: %s",
- strerror(errno));
+ write_stderr("%s: could not fork background process: %s\n",
+ progname, strerror(errno));
ExitPostmaster(1);
}
else if (pid)
#ifdef HAVE_SETSID
if (setsid() < 0)
{
- postmaster_error("could not dissociate from controlling TTY: %s",
- strerror(errno));
+ write_stderr("%s: could not dissociate from controlling TTY: %s\n",
+ progname, strerror(errno));
ExitPostmaster(1);
}
#endif
int nSockets;
time_t now,
last_touch_time;
- struct timeval earlier,
+ struct timeval earlier,
later;
- struct timezone tz;
+ struct timezone tz;
gettimeofday(&earlier, &tz);
last_touch_time = time(NULL);
kill(BgWriterPID, SIGUSR2);
}
- /*
- * If no AutoVacuum process is running, and we are not in
- * a state that prevents it, start one. It doesn't matter if this
- * fails, we'll just try again later.
- */
- if (autovacuum_start_daemon)
- {
- if (pgstat_collect_tuplelevel)
- {
- if (AutoVacPID == 0 && StartupPID == 0 && !FatalError)
- {
- AutoVacPID = StartAutoVac();
- if(pgstat_collect_resetonpmstart)
- elog(WARNING,"pg_autovacuum: stats_reset_on_server_start should be disabled for optimal performance");
-
- /* If shutdown is pending, set it going */
- if (Shutdown > NoShutdown && AutoVacPID != 0)
- kill(AutoVacPID, SIGUSR2);
- }
- }
- else
- elog(WARNING, "pg_autovacuum: autovac is enabled, but requires stats_row_level which is not enabled");
- }
- else if(AutoVacPID > 0)
- kill(AutoVacPID, SIGUSR2);
-
- if (!autovacuum_start_daemon)
- elog(DEBUG1, "pg_autovacuum: not enabled");
-
/* If we have lost the archiver, try to start a new one */
if (XLogArchivingActive() && PgArchPID == 0 &&
StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
backendPID = (int) ntohl(canc->backendPID);
cancelAuthCode = (long) ntohl(canc->cancelAuthCode);
- if (backendPID == BgWriterPID)
- {
- ereport(DEBUG2,
- (errmsg_internal("ignoring cancel request for bgwriter process %d",
- backendPID)));
- return;
- }
- if (backendPID == AutoVacPID)
- {
- ereport(DEBUG2,
- (errmsg_internal("ignoring cancel request for autovacuum process %d",
- backendPID)));
- return;
- }
-
/*
* See if we have a matching backend. In the EXEC_BACKEND case, we
* can no longer access the postmaster's own backend list, and must
kill(BgWriterPID, SIGHUP);
if (PgArchPID != 0)
kill(PgArchPID, SIGHUP);
- if (AutoVacPID != 0)
- kill(AutoVacPID, SIGHUP);
/* PgStatPID does not currently need SIGHUP */
load_hba();
load_ident();
/* Tell pgarch to shut down too; nothing left for it to do */
if (PgArchPID != 0)
kill(PgArchPID, SIGQUIT);
- /* I don't think we need to Start the autovac process if not running */
- /* And tell it to shut down */
- if (AutoVacPID != 0)
- kill(AutoVacPID, SIGUSR2);
/* Tell pgstat to shut down too; nothing left for it to do */
if (PgStatPID != 0)
kill(PgStatPID, SIGQUIT);
/* Tell pgarch to shut down too; nothing left for it to do */
if (PgArchPID != 0)
kill(PgArchPID, SIGQUIT);
- /* And tell it to shut down */
- if (AutoVacPID != 0)
- kill(AutoVacPID, SIGUSR2);
/* Tell pgstat to shut down too; nothing left for it to do */
if (PgStatPID != 0)
kill(PgStatPID, SIGQUIT);
kill(BgWriterPID, SIGQUIT);
if (PgArchPID != 0)
kill(PgArchPID, SIGQUIT);
- if (AutoVacPID != 0)
- kill(AutoVacPID, SIGQUIT);
if (PgStatPID != 0)
kill(PgStatPID, SIGQUIT);
if (DLGetHead(BackendList))
if (XLogArchivingActive() &&
StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
PgArchPID = pgarch_start();
- /*
- * Shutdown autovac if a shutdown request was pending.
- */
- if (Shutdown > NoShutdown && AutoVacPID != 0)
- kill(AutoVacPID, SIGUSR2);
-
continue;
}
- /*
- * Was it the autovac?
- */
- if (AutoVacPID != 0 && pid == AutoVacPID)
- {
- AutoVacPID = 0;
- if (exitstatus != 0)
- {
- /*
- * Any unexpected exit of the autovacuum is treated as a crash.
- * FIXME: This is useful for debugging autovac, but I think it should be
- * ripped out before final patch, autovac shouldn't crash the postmaster
- */
- LogChildExit(LOG, gettext("pg_autovacuum process"),
- pid, exitstatus);
- HandleChildCrash(pid, exitstatus);
- continue;
- }
- }
-
/*
* Was it the statistics collector? If so, just try to start a new
* one; no need to force reset of the rest of the system. (If fail,
* StartupDataBase. (We can ignore the archiver and stats processes
* here since they are not connected to shmem.)
*/
- if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0 || AutoVacPID != 0)
+ if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0)
goto reaper_done;
ereport(LOG,
(errmsg("all server processes terminated; reinitializing")));
/* And tell it to shut down */
if (BgWriterPID != 0)
kill(BgWriterPID, SIGUSR2);
- /* Tell AutoVac to shut down */
- if (AutoVacPID != 0)
- kill(AutoVacPID, SIGUSR2);
}
reaper_done:
}
FatalError = true;
-
- /* Take care of the autovacuum too */
- if (pid == AutoVacPID)
- AutoVacPID = 0;
- else if (AutoVacPID != 0 && !FatalError)
- {
- ereport(DEBUG2,
- (errmsg_internal("sending %s to process %d",
- (SendStop ? "SIGSTOP" : "SIGQUIT"),
- (int) AutoVacPID)));
- kill(AutoVacPID, (SendStop ? SIGSTOP : SIGQUIT));
- }
-
- FatalError = true;
}
/*
ereport(LOG,
(errmsg("could not fork background writer process: %m")));
break;
- case BS_XLOG_AUTOVAC:
- ereport(LOG,
- (errmsg("could not fork auto vacuum process: %m")));
- break;
default:
ereport(LOG,
(errmsg("could not fork process: %m")));
return true;
}
-/*
- * This should be used only for reporting "interactive" errors (essentially,
- * bogus arguments on the command line). Once the postmaster is launched,
- * use ereport. In particular, don't use this for anything that occurs
- * after pmdaemonize.
- */
-static void
-postmaster_error(const char *fmt,...)
-{
- va_list ap;
-
- fprintf(stderr, "%s: ", progname);
- va_start(ap, fmt);
- vfprintf(stderr, gettext(fmt), ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
#ifdef EXEC_BACKEND
if (r == WAIT_OBJECT_0)
pg_queue_signal(SIGCHLD);
else
- fprintf(stderr, "ERROR: failed to wait on child process handle: %d\n",
+ write_stderr("ERROR: failed to wait on child process handle: %d\n",
(int) GetLastError());
CloseHandle(procHandle);
return 0;
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.222 2004/07/21 20:23:01 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.223 2004/07/21 20:34:46 momjian Exp $
*
*--------------------------------------------------------------------
*/
#include "optimizer/prep.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
-#include "pgstat.h"
#include "postmaster/bgwriter.h"
-#include "postmaster/pg_autovacuum.h"
#include "postmaster/postmaster.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
+#include "pgstat.h"
char *guc_pgdata;
char *guc_hbafile;
&pgstat_collect_blocklevel,
false, NULL, NULL
},
- {
- {"autovacuum", PGC_SIGHUP, AUTOVACUUM,
- gettext_noop("Starts the auto vacuum subprocess."),
- NULL
- },
- &autovacuum_start_daemon,
- false, NULL, NULL
- },
{
{"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
&block_size,
BLCKSZ, BLCKSZ, BLCKSZ, NULL, NULL
},
- {
- {"autovacuum_vacuum_threshold_base", PGC_SIGHUP, AUTOVACUUM,
- gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
- NULL
- },
- &autovacuum_vacuum_base,
- 1000, 0, INT_MAX, NULL, NULL
- },
- {
- {"autovacuum_analyze_threshold_base", PGC_SIGHUP, AUTOVACUUM,
- gettext_noop("Minimum number of tuple updates or deletes prior to analyze."),
- NULL
- },
- &autovacuum_analyze_base,
- 500, 0, INT_MAX, NULL, NULL
- },
- {
- {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
- gettext_noop("Minimum number of tuple updates or deletes prior to analyze."),
- NULL
- },
- &autovacuum_analyze_base,
- 500, 0, INT_MAX, NULL, NULL
- },
/* End-of-list marker */
{
&phony_random_seed,
0.5, 0.0, 1.0, assign_random_seed, show_random_seed
},
- {
- {"autovacuum_vacuum_threshold_sf", PGC_SIGHUP, AUTOVACUUM,
- gettext_noop("Numer of tuple updates or deletes prior to vacuum as a factor of reltuples."),
- NULL
- },
- &autovacuum_vacuum_scaling_factor,
- 2, 0, 100, NULL, NULL
- },
- {
- {"autovacuum_analyze_threshold_sf", PGC_SIGHUP, AUTOVACUUM,
- gettext_noop("Numer of tuple updates or deletes prior to analyze as a factor of reltuples."),
- NULL
- },
- &autovacuum_analyze_scaling_factor,
- 1, 0, 100, NULL, NULL
- },
/* End-of-list marker */
{
#stats_reset_on_server_start = true
-#---------------------------------------------------------------------------
-# VACUUM DAEMON
-#---------------------------------------------------------------------------
-
-#autovacuum = false # requires stats_row_level = true
-#autovacuum_vacuum_threshold_base = 1000
-#autovacuum_vacuum_threshold_sf = 2
-#autovacuum_analyze_threshold_base = 500
-#autovacuum_analyze_threshold_sf = 1
-
#---------------------------------------------------------------------------
# CLIENT CONNECTION DEFAULTS
#---------------------------------------------------------------------------
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.36 2004/07/21 20:23:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.37 2004/07/21 20:34:47 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#define BS_XLOG_BOOTSTRAP 1
#define BS_XLOG_STARTUP 2
#define BS_XLOG_BGWRITER 3
-#define BS_XLOG_AUTOVAC 4
#endif /* BOOTSTRAP_H */
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.245 2004/07/21 20:23:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.246 2004/07/21 20:34:48 momjian Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200407211
+#define CATALOG_VERSION_NO 200407121
#endif
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/postmaster/postmaster.h,v 1.3 2004/07/21 20:23:04 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/postmaster/postmaster.h,v 1.4 2004/07/21 20:34:48 momjian Exp $
*
*-------------------------------------------------------------------------
*/
extern bool Log_connections;
extern bool log_hostname;
extern char *rendezvous_name;
-extern bool autovacuum_start_daemon;
#ifdef WIN32
extern HANDLE PostmasterHandle;
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.70 2004/07/21 20:23:04 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.71 2004/07/21 20:34:49 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#define DUMMY_PROC_DEFAULT 0
#define DUMMY_PROC_BGWRITER 1
-#define DUMMY_PROC_AUTOVAC 2
-#define NUM_DUMMY_PROCS 3
+#define NUM_DUMMY_PROCS 2
/* configurable options */
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.13 2004/07/21 20:23:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.14 2004/07/21 20:34:49 momjian Exp $
*
*-------------------------------------------------------------------------
*/
COMPAT_OPTIONS_CLIENT,
DEVELOPER_OPTIONS,
COMPILE_OPTIONS,
- AUTOVACUUM,
CUSTOM_OPTIONS
};
viewname | definition
--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
- pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, t.spcname AS "tablespace", i.relname AS indexname, pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
+ pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(i.oid) AS indexdef FROM (((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
pg_locks | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_statio_user_sequences | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.schemaname, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE (((pg_statio_all_sequences.schemaname <> 'pg_catalog'::name) AND (pg_statio_all_sequences.schemaname <> 'pg_toast'::name)) AND (pg_statio_all_sequences.schemaname <> 'information_schema'::name));
pg_statio_user_tables | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE (((pg_statio_all_tables.schemaname <> 'pg_catalog'::name) AND (pg_statio_all_tables.schemaname <> 'pg_toast'::name)) AND (pg_statio_all_tables.schemaname <> 'information_schema'::name));
pg_stats | SELECT nspname AS schemaname, relname AS tablename, attname, stanullfrac AS null_frac, stawidth AS avg_width, stadistinct AS n_distinct, CASE 1 WHEN stakind1 THEN stavalues1 WHEN stakind2 THEN stavalues2 WHEN stakind3 THEN stavalues3 WHEN stakind4 THEN stavalues4 ELSE NULL::"unknown" END AS most_common_vals, CASE 1 WHEN stakind1 THEN stanumbers1 WHEN stakind2 THEN stanumbers2 WHEN stakind3 THEN stanumbers3 WHEN stakind4 THEN stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE 2 WHEN stakind1 THEN stavalues1 WHEN stakind2 THEN stavalues2 WHEN stakind3 THEN stavalues3 WHEN stakind4 THEN stavalues4 ELSE NULL::"unknown" END AS histogram_bounds, CASE 3 WHEN stakind1 THEN stanumbers1[1] WHEN stakind2 THEN stanumbers2[1] WHEN stakind3 THEN stanumbers3[1] WHEN stakind4 THEN stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE has_table_privilege(c.oid, 'select'::text);
- pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, t.spcname AS "tablespace", pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM ((pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'r'::"char");
+ pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'r'::"char");
pg_user | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow;
pg_views | SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'v'::"char");
rtest_v1 | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1;