summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShigeru Hanada2011-03-11 03:01:29 +0000
committerShigeru Hanada2011-03-11 03:01:29 +0000
commit6ef467bfe4b55f28ab6c4c9414cab49795c1e6b0 (patch)
tree4e45e3dd0961562a621fc1bde5f3d7a221a6cff3
parent6e1ebd8c8358fad0642c65d97205fe398b154ed2 (diff)
parent303b7fcd10a34d8c8b4c3e6e258faeaf107dcf92 (diff)
Merge branch 'master' into postgresql_fdw
-rw-r--r--contrib/auth_delay/auth_delay.c2
-rw-r--r--contrib/pg_test_fsync/pg_test_fsync.c108
-rw-r--r--doc/src/sgml/config.sgml2
-rw-r--r--doc/src/sgml/func.sgml28
-rw-r--r--doc/src/sgml/pgupgrade.sgml18
-rw-r--r--doc/src/sgml/ref/alter_table.sgml10
-rw-r--r--doc/src/sgml/ref/alter_type.sgml4
-rw-r--r--doc/src/sgml/ref/clusterdb.sgml10
-rw-r--r--doc/src/sgml/ref/comment.sgml52
-rw-r--r--doc/src/sgml/ref/create_domain.sgml5
-rw-r--r--doc/src/sgml/ref/create_table.sgml6
-rw-r--r--doc/src/sgml/ref/createdb.sgml20
-rw-r--r--doc/src/sgml/ref/createlang.sgml8
-rw-r--r--doc/src/sgml/ref/createuser.sgml8
-rw-r--r--doc/src/sgml/ref/dropdb.sgml6
-rw-r--r--doc/src/sgml/ref/droplang.sgml8
-rw-r--r--doc/src/sgml/ref/dropuser.sgml6
-rw-r--r--doc/src/sgml/ref/initdb.sgml20
-rw-r--r--doc/src/sgml/ref/pg_controldata.sgml1
-rw-r--r--doc/src/sgml/ref/pg_ctl-ref.sgml15
-rw-r--r--doc/src/sgml/ref/pg_dump.sgml8
-rw-r--r--doc/src/sgml/ref/postgres-ref.sgml19
-rw-r--r--doc/src/sgml/ref/psql-ref.sgml28
-rw-r--r--doc/src/sgml/ref/reindexdb.sgml12
-rw-r--r--doc/src/sgml/ref/vacuumdb.sgml10
-rw-r--r--doc/src/sgml/release-9.1.sgml72
-rw-r--r--doc/src/sgml/syntax.sgml41
-rw-r--r--doc/src/sgml/xfunc.sgml6
-rw-r--r--src/Makefile5
-rw-r--r--src/backend/Makefile7
-rw-r--r--src/backend/access/common/tupdesc.c3
-rw-r--r--src/backend/access/transam/xlog.c5
-rw-r--r--src/backend/catalog/aclchk.c30
-rw-r--r--src/backend/catalog/objectaddress.c27
-rw-r--r--src/backend/catalog/system_views.sql4
-rw-r--r--src/backend/commands/collationcmds.c2
-rw-r--r--src/backend/commands/functioncmds.c4
-rw-r--r--src/backend/commands/sequence.c23
-rw-r--r--src/backend/commands/tablecmds.c65
-rw-r--r--src/backend/commands/typecmds.c27
-rw-r--r--src/backend/commands/user.c15
-rw-r--r--src/backend/commands/view.c13
-rw-r--r--src/backend/nodes/copyfuncs.c7
-rw-r--r--src/backend/nodes/equalfuncs.c7
-rw-r--r--src/backend/nodes/makefuncs.c5
-rw-r--r--src/backend/nodes/outfuncs.c5
-rw-r--r--src/backend/parser/gram.y182
-rw-r--r--src/backend/parser/parse_expr.c17
-rw-r--r--src/backend/parser/parse_func.c4
-rw-r--r--src/backend/parser/parse_relation.c3
-rw-r--r--src/backend/parser/parse_type.c166
-rw-r--r--src/backend/parser/parse_utilcmd.c46
-rw-r--r--src/backend/replication/README31
-rw-r--r--src/backend/replication/basebackup.c2
-rw-r--r--src/backend/replication/syncrep.c18
-rw-r--r--src/backend/storage/ipc/shmqueue.c2
-rw-r--r--src/backend/utils/adt/format_type.c25
-rw-r--r--src/backend/utils/adt/ruleutils.c5
-rw-r--r--src/backend/utils/misc/guc.c2
-rw-r--r--src/bin/initdb/initdb.c2
-rw-r--r--src/bin/pg_dump/common.c15
-rw-r--r--src/bin/pg_dump/pg_backup_directory.c2
-rw-r--r--src/bin/pg_dump/pg_dump.c75
-rw-r--r--src/bin/pg_dump/pg_dump.h2
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_collation.h5
-rw-r--r--src/include/catalog/pg_foreign_table.h2
-rw-r--r--src/include/catalog/pg_proc.h4
-rw-r--r--src/include/nodes/makefuncs.h2
-rw-r--r--src/include/nodes/parsenodes.h17
-rw-r--r--src/include/parser/parse_type.h14
-rw-r--r--src/include/replication/basebackup.h2
-rw-r--r--src/include/replication/syncrep.h13
-rw-r--r--src/include/replication/walsender.h3
-rw-r--r--src/include/storage/proc.h2
-rw-r--r--src/include/utils/acl.h1
-rw-r--r--src/pl/plpgsql/src/pl_comp.c2
-rw-r--r--src/test/isolation/Makefile6
-rw-r--r--src/test/isolation/isolationtester.h10
-rw-r--r--src/test/isolation/specscanner.l26
-rw-r--r--src/test/regress/expected/collate.linux.utf8.out12
-rw-r--r--src/test/regress/expected/foreign_data.out2
-rw-r--r--src/tools/git-external-diff22
83 files changed, 919 insertions, 614 deletions
diff --git a/contrib/auth_delay/auth_delay.c b/contrib/auth_delay/auth_delay.c
index 09191bd250..199de9bb39 100644
--- a/contrib/auth_delay/auth_delay.c
+++ b/contrib/auth_delay/auth_delay.c
@@ -2,7 +2,7 @@
*
* auth_delay.c
*
- * Copyright (C) 2010, PostgreSQL Global Development Group
+ * Copyright (C) 2010-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
* contrib/auth_delay/auth_delay.c
diff --git a/contrib/pg_test_fsync/pg_test_fsync.c b/contrib/pg_test_fsync/pg_test_fsync.c
index d07548322c..49a7b3c2c0 100644
--- a/contrib/pg_test_fsync/pg_test_fsync.c
+++ b/contrib/pg_test_fsync/pg_test_fsync.c
@@ -23,7 +23,7 @@
#define XLOG_BLCKSZ_K (XLOG_BLCKSZ / 1024)
#define LABEL_FORMAT " %-32s"
-#define NA_FORMAT LABEL_FORMAT "%18s"
+#define NA_FORMAT "%18s"
#define OPS_FORMAT "%9.3f ops/sec"
static const char *progname;
@@ -134,6 +134,11 @@ handle_args(int argc, char *argv[])
}
printf("%d operations per test\n", ops_per_test);
+#if PG_O_DIRECT != 0
+ printf("O_DIRECT supported on this platform for open_datasync and open_sync.\n");
+#else
+ printf("Direct I/O is not supported on this platform.\n");
+#endif
}
static void
@@ -184,43 +189,19 @@ test_sync(int writes_per_op)
/*
* Test open_datasync if available
*/
-#ifdef OPEN_DATASYNC_FLAG
- printf(LABEL_FORMAT, "open_datasync"
-#if PG_O_DIRECT != 0
- " (non-direct I/O)*"
-#endif
- );
+ printf(LABEL_FORMAT, "open_datasync");
fflush(stdout);
- if ((tmpfile = open(filename, O_RDWR | O_DSYNC, 0)) == -1)
- die("could not open output file");
- gettimeofday(&start_t, NULL);
- for (ops = 0; ops < ops_per_test; ops++)
- {
- for (writes = 0; writes < writes_per_op; writes++)
- if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
- die("write failed");
- if (lseek(tmpfile, 0, SEEK_SET) == -1)
- die("seek failed");
- }
- gettimeofday(&stop_t, NULL);
- close(tmpfile);
- print_elapse(start_t, stop_t);
-
- /*
- * If O_DIRECT is enabled, test that with open_datasync
- */
-#if PG_O_DIRECT != 0
+#ifdef OPEN_DATASYNC_FLAG
if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
{
- printf(NA_FORMAT, "o_direct", "n/a**\n");
+ printf(NA_FORMAT, "n/a*\n");
fs_warning = true;
}
else
{
- printf(LABEL_FORMAT, "open_datasync (direct I/O)");
- fflush(stdout);
-
+ if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
+ die("could not open output file");
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
{
@@ -234,19 +215,17 @@ test_sync(int writes_per_op)
close(tmpfile);
print_elapse(start_t, stop_t);
}
-#endif
-
#else
- printf(NA_FORMAT, "open_datasync", "n/a\n");
+ printf(NA_FORMAT, "n/a\n");
#endif
/*
* Test fdatasync if available
*/
-#ifdef HAVE_FDATASYNC
printf(LABEL_FORMAT, "fdatasync");
fflush(stdout);
+#ifdef HAVE_FDATASYNC
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
gettimeofday(&start_t, NULL);
@@ -263,7 +242,7 @@ test_sync(int writes_per_op)
close(tmpfile);
print_elapse(start_t, stop_t);
#else
- printf(NA_FORMAT, "fdatasync", "n/a\n");
+ printf(NA_FORMAT, "n/a\n");
#endif
/*
@@ -292,10 +271,10 @@ test_sync(int writes_per_op)
/*
* If fsync_writethrough is available, test as well
*/
-#ifdef HAVE_FSYNC_WRITETHROUGH
printf(LABEL_FORMAT, "fsync_writethrough");
fflush(stdout);
+#ifdef HAVE_FSYNC_WRITETHROUGH
if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
die("could not open output file");
gettimeofday(&start_t, NULL);
@@ -313,49 +292,23 @@ test_sync(int writes_per_op)
close(tmpfile);
print_elapse(start_t, stop_t);
#else
- printf(NA_FORMAT, "fsync_writethrough", "n/a\n");
+ printf(NA_FORMAT, "n/a\n");
#endif
/*
* Test open_sync if available
*/
-#ifdef OPEN_SYNC_FLAG
- printf(LABEL_FORMAT, "open_sync"
-#if PG_O_DIRECT != 0
- " (non-direct I/O)*"
-#endif
- );
+ printf(LABEL_FORMAT, "open_sync");
fflush(stdout);
- if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG, 0)) == -1)
- die("could not open output file");
- gettimeofday(&start_t, NULL);
- for (ops = 0; ops < ops_per_test; ops++)
- {
- for (writes = 0; writes < writes_per_op; writes++)
- if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
- die("write failed");
- if (lseek(tmpfile, 0, SEEK_SET) == -1)
- die("seek failed");
- }
- gettimeofday(&stop_t, NULL);
- close(tmpfile);
- print_elapse(start_t, stop_t);
-
- /*
- * If O_DIRECT is enabled, test that with open_sync
- */
-#if PG_O_DIRECT != 0
+#ifdef OPEN_SYNC_FLAG
if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1)
{
- printf(NA_FORMAT, "o_direct", "n/a**\n");
+ printf(NA_FORMAT, "n/a*\n");
fs_warning = true;
}
else
{
- printf(LABEL_FORMAT, "open_sync (direct I/O)");
- fflush(stdout);
-
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
{
@@ -369,20 +322,13 @@ test_sync(int writes_per_op)
close(tmpfile);
print_elapse(start_t, stop_t);
}
-#endif
-
#else
- printf(NA_FORMAT, "open_sync", "n/a\n");
-#endif
-
-#if defined(OPEN_DATASYNC_FLAG) || defined(OPEN_SYNC_FLAG)
- if (PG_O_DIRECT != 0)
- printf("* This non-direct I/O mode is not used by Postgres.\n");
+ printf(NA_FORMAT, "n/a\n");
#endif
if (fs_warning)
{
- printf("** This file system and its mount options do not support direct\n");
+ printf("* This file system and its mount options do not support direct\n");
printf("I/O, e.g. ext4 in journaled mode.\n");
}
}
@@ -407,16 +353,16 @@ test_open_syncs(void)
static void
test_open_sync(const char *msg, int writes_size)
{
-#ifdef OPEN_SYNC_FLAG
int tmpfile, ops, writes;
+ printf(LABEL_FORMAT, msg);
+ fflush(stdout);
+
+#ifdef OPEN_SYNC_FLAG
if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1)
- printf(NA_FORMAT, "o_direct", "n/a**\n");
+ printf(NA_FORMAT, "n/a*\n");
else
{
- printf(LABEL_FORMAT, msg);
- fflush(stdout);
-
gettimeofday(&start_t, NULL);
for (ops = 0; ops < ops_per_test; ops++)
{
@@ -433,7 +379,7 @@ test_open_sync(const char *msg, int writes_size)
}
#else
- printf(NA_FORMAT, "open_sync", "n/a\n");
+ printf(NA_FORMAT, "n/a\n");
#endif
}
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index ec7e44315f..8e27f730a4 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2061,7 +2061,7 @@ SET ENABLE_SEQSCAN TO OFF;
</varlistentry>
<varlistentry id="guc-sync-standby-names" xreflabel="synchronous_standby_names">
- <term><varname>synchronous_standby_names</varname> (<type>integer</type>)</term>
+ <term><varname>synchronous_standby_names</varname> (<type>string</type>)</term>
<indexterm>
<primary><varname>synchronous_standby_names</> configuration parameter</primary>
</indexterm>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index c5d75c4c65..4635cf2bb5 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -13269,7 +13269,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<tbody>
<row>
- <entry><literal><function>format_type(<parameter>type_oid</parameter> [, <parameter>typemod</> [, <parameter>collation_oid</> ]])</function></literal></entry>
+ <entry><literal><function>format_type(<parameter>type_oid</parameter>, <parameter>typemod</>)</function></literal></entry>
<entry><type>text</type></entry>
<entry>get SQL name of a data type</entry>
</row>
@@ -13410,9 +13410,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<para>
<function>format_type</function> returns the SQL name of a data type that
is identified by its type OID and possibly a type modifier. Pass NULL
- for the type modifier or omit the argument if no specific modifier is known.
- If a collation is given as third argument, a <literal>COLLATE</> clause
- followed by a formatted collation name is appended.
+ for the type modifier if no specific modifier is known.
</para>
<para>
@@ -13588,10 +13586,10 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33);
</table>
<para>
- <function>col_description</function> returns the comment for a table column,
- which is specified by the OID of its table and its column number.
- <function>obj_description</function> cannot be used for table columns since
- columns do not have OIDs of their own.
+ <function>col_description</function> returns the comment for a table
+ column, which is specified by the OID of its table and its column number.
+ (<function>obj_description</function> cannot be used for table columns
+ since columns do not have OIDs of their own.)
</para>
<para>
@@ -13610,8 +13608,8 @@ SELECT typlen FROM pg_type WHERE oid = pg_typeof(33);
<function>shobj_description</function> is used just like
<function>obj_description</function> except it is used for retrieving
comments on shared objects. Some system catalogs are global to all
- databases within each cluster and their descriptions are stored globally
- as well.
+ databases within each cluster, and the descriptions for objects in them
+ are stored globally as well.
</para>
<indexterm>
@@ -14219,6 +14217,16 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
</tgroup>
</table>
+ <indexterm>
+ <primary>pg_is_xlog_replay_paused</primary>
+ </indexterm>
+ <indexterm>
+ <primary>pg_xlog_replay_pause</primary>
+ </indexterm>
+ <indexterm>
+ <primary>pg_xlog_replay_resume</primary>
+ </indexterm>
+
<para>
The functions shown in <xref
linkend="functions-recovery-control-table"> control the progress of recovery.
diff --git a/doc/src/sgml/pgupgrade.sgml b/doc/src/sgml/pgupgrade.sgml
index 5b42fa85aa..c41068f074 100644
--- a/doc/src/sgml/pgupgrade.sgml
+++ b/doc/src/sgml/pgupgrade.sgml
@@ -58,13 +58,13 @@
<varlistentry>
<term><option>-b</option> <replaceable>old_bindir</></term>
- <term><option>--old-bindir</option> <replaceable>OLDBINDIR</></term>
+ <term><option>--old-bindir=</option><replaceable>OLDBINDIR</></term>
<listitem><para>specify the old cluster executable directory</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-B</option> <replaceable>new_bindir</></term>
- <term><option>--new-bindir</option> <replaceable>NEWBINDIR</></term>
+ <term><option>--new-bindir=</option><replaceable>NEWBINDIR</></term>
<listitem><para>specify the new cluster executable directory</para></listitem>
</varlistentry>
@@ -76,13 +76,13 @@
<varlistentry>
<term><option>-d</option> <replaceable>old_datadir</></term>
- <term><option>--old-datadir</option> <replaceable>OLDDATADIR</></term>
+ <term><option>--old-datadir=</option><replaceable>OLDDATADIR</></term>
<listitem><para>specify the old cluster data directory</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-D</option> <replaceable>new_datadir</></term>
- <term><option>--new-datadir</option> <replaceable>NEWDATADIR</></term>
+ <term><option>--new-datadir=</option><replaceable>NEWDATADIR</></term>
<listitem><para>specify the new cluster data directory</para></listitem>
</varlistentry>
@@ -94,7 +94,7 @@
<varlistentry>
<term><option>-G</option> <replaceable>debug_filename</></term>
- <term><option>--debugfile</option> <replaceable>DEBUGFILENAME</></term>
+ <term><option>--debugfile=</option><replaceable>DEBUGFILENAME</></term>
<listitem><para>output debugging activity to file</para></listitem>
</varlistentry>
@@ -106,25 +106,25 @@
<varlistentry>
<term><option>-l</option> <replaceable>log_filename</></term>
- <term><option>--logfile</option> <replaceable>LOGFILENAME</></term>
+ <term><option>--logfile=</option><replaceable>LOGFILENAME</></term>
<listitem><para>log session activity to file</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-p</option> <replaceable>old_portnum</></term>
- <term><option>--old-port</option> <replaceable>portnum</></term>
+ <term><option>--old-port=</option><replaceable>portnum</></term>
<listitem><para>specify the old cluster port number</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-P</option> <replaceable>new_portnum</></term>
- <term><option>--new-port</option> <replaceable>portnum</></term>
+ <term><option>--new-port=</option><replaceable>portnum</></term>
<listitem><para>specify the new cluster port number</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-u</option> <replaceable>username</></term>
- <term><option>--user</option> <replaceable>username</></term>
+ <term><option>--user=</option><replaceable>username</></term>
<listitem><para>clusters superuser</para></listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index b8c4c507a2..c1948624d7 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -32,9 +32,9 @@ ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
- ADD [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
+ ADD [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ COLLATE <replaceable class="PARAMETER">collation</replaceable> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
DROP [ COLUMN ] [ IF EXISTS ] <replaceable class="PARAMETER">column</replaceable> [ RESTRICT | CASCADE ]
- ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">type</replaceable> [ USING <replaceable class="PARAMETER">expression</replaceable> ]
+ ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable> [ COLLATE <replaceable class="PARAMETER">collation</replaceable> ] [ USING <replaceable class="PARAMETER">expression</replaceable> ]
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> SET DEFAULT <replaceable class="PARAMETER">expression</replaceable>
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> DROP DEFAULT
ALTER [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> { SET | DROP } NOT NULL
@@ -115,7 +115,11 @@ ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
This form changes the type of a column of a table. Indexes and
simple table constraints involving the column will be automatically
converted to use the new column type by reparsing the originally
- supplied expression. The optional <literal>USING</literal>
+ supplied expression.
+ The optional <literal>COLLATE</literal> clause specifies a collation
+ for the new column; if omitted, the collation is the default for the
+ new column type.
+ The optional <literal>USING</literal>
clause specifies how to compute the new column value from the old;
if omitted, the default conversion is the same as an assignment
cast from old data type to new. A <literal>USING</literal>
diff --git a/doc/src/sgml/ref/alter_type.sgml b/doc/src/sgml/ref/alter_type.sgml
index 09db0cc8b2..e889ffbc35 100644
--- a/doc/src/sgml/ref/alter_type.sgml
+++ b/doc/src/sgml/ref/alter_type.sgml
@@ -32,9 +32,9 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replacea
<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
- ADD ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ CASCADE | RESTRICT ]
+ ADD ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ COLLATE <replaceable class="PARAMETER">collation</replaceable> ] [ CASCADE | RESTRICT ]
DROP ATTRIBUTE [ IF EXISTS ] <replaceable class="PARAMETER">attribute_name</replaceable> [ CASCADE | RESTRICT ]
- ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable> [ CASCADE | RESTRICT ]
+ ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable> [ COLLATE <replaceable class="PARAMETER">collation</replaceable> ] [ CASCADE | RESTRICT ]
</synopsis>
</refsynopsisdiv>
diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.sgml
index 5ce3a41fc7..081f398706 100644
--- a/doc/src/sgml/ref/clusterdb.sgml
+++ b/doc/src/sgml/ref/clusterdb.sgml
@@ -77,7 +77,7 @@ PostgreSQL documentation
<varlistentry>
<term><option><optional>-d</> <replaceable class="parameter">dbname</replaceable></></term>
- <term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></></term>
+ <term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
Specifies the name of the database to be clustered.
@@ -113,7 +113,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable></></term>
- <term><option>--table <replaceable class="parameter">table</replaceable></></term>
+ <term><option>--table=<replaceable class="parameter">table</replaceable></></term>
<listitem>
<para>
Cluster <replaceable class="parameter">table</replaceable> only.
@@ -162,7 +162,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the server is
@@ -174,7 +174,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -186,7 +186,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml
index 2610fd5b8d..bc848b3069 100644
--- a/doc/src/sgml/ref/comment.sgml
+++ b/doc/src/sgml/ref/comment.sgml
@@ -65,11 +65,18 @@ COMMENT ON
</para>
<para>
- To modify a comment, issue a new <command>COMMENT</> command for the
- same object. Only one comment string is stored for each object.
- To remove a comment, write <literal>NULL</literal> in place of the text
- string.
- Comments are automatically dropped when the object is dropped.
+ Only one comment string is stored for each object, so to modify a comment,
+ issue a new <command>COMMENT</> command for the same object. To remove a
+ comment, write <literal>NULL</literal> in place of the text string.
+ Comments are automatically dropped when their object is dropped.
+ </para>
+
+ <para>
+ For most kinds of object, only the object's owner can set the comment.
+ Roles don't have owners, so the rule for <literal>COMMENT ON ROLE</> is
+ that you must be superuser to comment on a superuser role, or have the
+ <literal>CREATEROLE</> privilege to comment on non-superuser roles.
+ Of course, a superuser can comment on anything.
</para>
<para>
@@ -93,15 +100,15 @@ COMMENT ON
<term><replaceable class="parameter">agg_name</replaceable></term>
<term><replaceable class="parameter">constraint_name</replaceable></term>
<term><replaceable class="parameter">function_name</replaceable></term>
- <term><replaceable class="parameter">op</replaceable></term>
+ <term><replaceable class="parameter">operator_name</replaceable></term>
<term><replaceable class="parameter">rule_name</replaceable></term>
<term><replaceable class="parameter">trigger_name</replaceable></term>
<listitem>
<para>
The name of the object to be commented. Names of tables,
- aggregates, domains, foreign tables, functions, indexes, operators,
- operator classes, operator families, sequences, text search objects,
- types, and views can be schema-qualified.
+ aggregates, collations, conversions, domains, foreign tables, functions,
+ indexes, operators, operator classes, operator families, sequences,
+ text search objects, types, and views can be schema-qualified.
</para>
</listitem>
</varlistentry>
@@ -137,7 +144,6 @@ COMMENT ON
<varlistentry>
<term><replaceable class="parameter">argmode</replaceable></term>
-
<listitem>
<para>
The mode of a function argument: <literal>IN</>, <literal>OUT</>,
@@ -154,7 +160,6 @@ COMMENT ON
<varlistentry>
<term><replaceable class="parameter">argname</replaceable></term>
-
<listitem>
<para>
The name of a function argument.
@@ -167,7 +172,6 @@ COMMENT ON
<varlistentry>
<term><replaceable class="parameter">argtype</replaceable></term>
-
<listitem>
<para>
The data type(s) of the function's arguments (optionally
@@ -185,9 +189,20 @@ COMMENT ON
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><replaceable class="parameter">left_type</replaceable></term>
+ <term><replaceable class="parameter">right_type</replaceable></term>
+ <listitem>
+ <para>
+ The data type(s) of the operator's arguments (optionally
+ schema-qualified). Write <literal>NONE</> for the missing argument
+ of a prefix or postfix operator.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>PROCEDURAL</literal></term>
-
<listitem>
<para>
This is a noise word.
@@ -212,12 +227,11 @@ COMMENT ON
<title>Notes</title>
<para>
- There is presently no security mechanism for comments: any user
+ There is presently no security mechanism for viewing comments: any user
connected to a database can see all the comments for objects in
- that database (although only superusers can change comments for
- objects that they don't own). For shared objects such as
- databases, roles, and tablespaces comments are stored globally
- and any user connected to any database can see all the comments
+ that database. For shared objects such as
+ databases, roles, and tablespaces, comments are stored globally so any
+ user connected to any database in the cluster can see all the comments
for shared objects. Therefore, don't put security-critical
information in comments.
</para>
@@ -257,7 +271,7 @@ COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee ID';
COMMENT ON LANGUAGE plpython IS 'Python support for stored procedures';
COMMENT ON LARGE OBJECT 346344 IS 'Planning document';
COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two texts';
-COMMENT ON OPERATOR - (NONE, text) IS 'This is a prefix operator on text';
+COMMENT ON OPERATOR - (NONE, integer) IS 'Unary minus';
COMMENT ON OPERATOR CLASS int4ops USING btree IS '4 byte integer operators for btrees';
COMMENT ON OPERATOR FAMILY integer_ops USING btree IS 'all integer operators for btrees';
COMMENT ON ROLE my_role IS 'Administration group for finance tables';
diff --git a/doc/src/sgml/ref/create_domain.sgml b/doc/src/sgml/ref/create_domain.sgml
index 83be889c6d..2300edefe3 100644
--- a/doc/src/sgml/ref/create_domain.sgml
+++ b/doc/src/sgml/ref/create_domain.sgml
@@ -89,8 +89,9 @@ CREATE DOMAIN <replaceable class="parameter">name</replaceable> [ AS ] <replacea
<listitem>
<para>
An optional collation for the domain. If no collation is
- specified, the database default collation is used (which can
- be overridden when the domain is used to define a column).
+ specified, the underlying data type's default collation is used.
+ The underlying type must be collatable when <literal>COLLATE</>
+ is specified.
</para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 9d2d99ad2e..0fbe116097 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -248,9 +248,9 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
<term><literal>COLLATE <replaceable>collation</replaceable></literal></term>
<listitem>
<para>
- The <literal>COLLATE</> clause assigns a nondefault collation to
- the column. By default, the locale settings of the database are
- used.
+ The <literal>COLLATE</> clause assigns a collation to
+ the column (which must be of a collatable data type).
+ If not specified, the column data type's default collation is used.
</para>
</listitem>
</varlistentry>
diff --git a/doc/src/sgml/ref/createdb.sgml b/doc/src/sgml/ref/createdb.sgml
index 633881d6f7..7cbf56506d 100644
--- a/doc/src/sgml/ref/createdb.sgml
+++ b/doc/src/sgml/ref/createdb.sgml
@@ -87,7 +87,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-D <replaceable class="parameter">tablespace</replaceable></></term>
- <term><option>--tablespace <replaceable class="parameter">tablespace</replaceable></></term>
+ <term><option>--tablespace=<replaceable class="parameter">tablespace</replaceable></></term>
<listitem>
<para>
Specifies the default tablespace for the database.
@@ -108,7 +108,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-l <replaceable class="parameter">locale</replaceable></></term>
- <term><option>--locale <replaceable class="parameter">locale</replaceable></></term>
+ <term><option>--locale=<replaceable class="parameter">locale</replaceable></></term>
<listitem>
<para>
Specifies the locale to be used in this database. This is equivalent
@@ -118,7 +118,7 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
- <term><option>--lc-collate <replaceable class="parameter">locale</replaceable></></term>
+ <term><option>--lc-collate=<replaceable class="parameter">locale</replaceable></></term>
<listitem>
<para>
Specifies the LC_COLLATE setting to be used in this database.
@@ -127,7 +127,7 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
- <term><option>--lc-ctype <replaceable class="parameter">locale</replaceable></></term>
+ <term><option>--lc-ctype=<replaceable class="parameter">locale</replaceable></></term>
<listitem>
<para>
Specifies the LC_CTYPE setting to be used in this database.
@@ -137,7 +137,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-E <replaceable class="parameter">encoding</replaceable></></term>
- <term><option>--encoding <replaceable class="parameter">encoding</replaceable></></term>
+ <term><option>--encoding=<replaceable class="parameter">encoding</replaceable></></term>
<listitem>
<para>
Specifies the character encoding scheme to be used in this
@@ -150,7 +150,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-O <replaceable class="parameter">owner</replaceable></></term>
- <term><option>--owner <replaceable class="parameter">owner</replaceable></></term>
+ <term><option>--owner=<replaceable class="parameter">owner</replaceable></></term>
<listitem>
<para>
Specifies the database user who will own the new database.
@@ -160,7 +160,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-T <replaceable class="parameter">template</replaceable></></term>
- <term><option>--template <replaceable class="parameter">template</replaceable></></term>
+ <term><option>--template=<replaceable class="parameter">template</replaceable></></term>
<listitem>
<para>
Specifies the template database from which to build this database.
@@ -207,7 +207,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -219,7 +219,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or the local Unix domain socket file
@@ -230,7 +230,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/ref/createlang.sgml b/doc/src/sgml/ref/createlang.sgml
index 0bc1976c15..f01f298322 100644
--- a/doc/src/sgml/ref/createlang.sgml
+++ b/doc/src/sgml/ref/createlang.sgml
@@ -77,7 +77,7 @@ PostgreSQL documentation
<varlistentry>
<term><option><optional>-d</> <replaceable class="parameter">dbname</replaceable></></term>
- <term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></></term>
+ <term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
Specifies the database to which the language should be added.
@@ -138,7 +138,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -151,7 +151,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -163,7 +163,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/ref/createuser.sgml b/doc/src/sgml/ref/createuser.sgml
index fbc184f4c8..0c47fb4997 100644
--- a/doc/src/sgml/ref/createuser.sgml
+++ b/doc/src/sgml/ref/createuser.sgml
@@ -78,7 +78,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-c <replaceable class="parameter">number</replaceable></></term>
- <term><option>--connection-limit <replaceable class="parameter">number</replaceable></></term>
+ <term><option>--connection-limit=<replaceable class="parameter">number</replaceable></></term>
<listitem>
<para>
Set a maximum number of connections for the new user.
@@ -276,7 +276,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -289,7 +289,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -301,7 +301,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as (not the user name to create).
diff --git a/doc/src/sgml/ref/dropdb.sgml b/doc/src/sgml/ref/dropdb.sgml
index c169d7fcd4..1aa76cdb57 100644
--- a/doc/src/sgml/ref/dropdb.sgml
+++ b/doc/src/sgml/ref/dropdb.sgml
@@ -118,7 +118,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -131,7 +131,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -143,7 +143,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/ref/droplang.sgml b/doc/src/sgml/ref/droplang.sgml
index 810c78e521..0ad640b0b4 100644
--- a/doc/src/sgml/ref/droplang.sgml
+++ b/doc/src/sgml/ref/droplang.sgml
@@ -79,7 +79,7 @@ PostgreSQL documentation
<varlistentry>
<term><option><optional>-d</> <replaceable class="parameter">dbname</replaceable></></term>
- <term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></></term>
+ <term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
Specifies from which database the language should be removed.
@@ -140,7 +140,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -153,7 +153,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the Internet TCP/IP port or local Unix domain socket file
@@ -165,7 +165,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/ref/dropuser.sgml b/doc/src/sgml/ref/dropuser.sgml
index 0786612820..3089a21954 100644
--- a/doc/src/sgml/ref/dropuser.sgml
+++ b/doc/src/sgml/ref/dropuser.sgml
@@ -119,7 +119,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -132,7 +132,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -144,7 +144,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as (not the user name to drop).
diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml
index 04f047b063..d816c21c08 100644
--- a/doc/src/sgml/ref/initdb.sgml
+++ b/doc/src/sgml/ref/initdb.sgml
@@ -22,9 +22,9 @@ PostgreSQL documentation
<refsynopsisdiv>
<cmdsynopsis>
<command>initdb</command>
- <arg rep="repeat"><replaceable>option</></arg>
+ <arg rep="repeat"><replaceable>option</replaceable></arg>
<group choice="plain">
- <arg>--pgdata </arg>
+ <arg>--pgdata</arg>
<arg>-D </arg>
<replaceable>directory</replaceable>
</group>
@@ -186,16 +186,14 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
- <term><option>-X <replaceable class="parameter">directory</replaceable></option></term>
- <term><option>--xlogdir=<replaceable class="parameter">directory</replaceable></option></term>
+ <term><option>--pwfile=<replaceable>filename</></option></term>
<listitem>
<para>
- This option specifies the directory where the transaction log
- should be stored.
+ Makes <command>initdb</command> read the database superuser's password
+ from a file. The first line of the file is taken as the password.
</para>
</listitem>
</varlistentry>
-
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></option></term>
<term><option>--username=<replaceable class="parameter">username</replaceable></option></term>
@@ -226,14 +224,16 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
- <term><option>--pwfile=<replaceable>filename</></option></term>
+ <term><option>-X <replaceable class="parameter">directory</replaceable></option></term>
+ <term><option>--xlogdir=<replaceable class="parameter">directory</replaceable></option></term>
<listitem>
<para>
- Makes <command>initdb</command> read the database superuser's password
- from a file. The first line of the file is taken as the password.
+ This option specifies the directory where the transaction log
+ should be stored.
</para>
</listitem>
</varlistentry>
+
</variablelist>
</para>
diff --git a/doc/src/sgml/ref/pg_controldata.sgml b/doc/src/sgml/ref/pg_controldata.sgml
index 50b1909499..d39b6e18f8 100644
--- a/doc/src/sgml/ref/pg_controldata.sgml
+++ b/doc/src/sgml/ref/pg_controldata.sgml
@@ -22,6 +22,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<cmdsynopsis>
<command>pg_controldata</command>
+ <arg><replaceable class="parameter">option</replaceable></arg>
<arg><replaceable class="parameter">datadir</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
diff --git a/doc/src/sgml/ref/pg_ctl-ref.sgml b/doc/src/sgml/ref/pg_ctl-ref.sgml
index 307f66b8da..608749f4c6 100644
--- a/doc/src/sgml/ref/pg_ctl-ref.sgml
+++ b/doc/src/sgml/ref/pg_ctl-ref.sgml
@@ -499,22 +499,22 @@ PostgreSQL documentation
<title>Starting the Server</title>
<para>
- To start up a server:
+ To start the server:
<screen>
<prompt>$</prompt> <userinput>pg_ctl start</userinput>
</screen>
</para>
<para>
- An example of starting the server, and waiting until the server is
- accepting connection:
+ To start the server, waiting until the server is
+ accepting connections:
<screen>
<prompt>$</prompt> <userinput>pg_ctl -w start</userinput>
</screen>
</para>
<para>
- For a server using port 5433, and
+ To start the server using port 5433, and
running without <function>fsync</function>, use:
<screen>
<prompt>$</prompt> <userinput>pg_ctl -o "-F -p 5433" start</userinput>
@@ -530,7 +530,10 @@ PostgreSQL documentation
<prompt>$</prompt> <userinput>pg_ctl stop</userinput>
</screen>
The <option>-m</option> option allows control over
- <emphasis>how</emphasis> the server shuts down.
+ <emphasis>how</emphasis> the server shuts down:
+<screen>
+<prompt>$</prompt> <userinput>pg_ctl stop -m fast</userinput>
+</screen>
</para>
</refsect2>
@@ -557,7 +560,7 @@ PostgreSQL documentation
</para>
<para>
- To restart using port 5433 and disable <function>fsync</> upon restart:
+ To restart using port 5433, disabling <function>fsync</> upon restart:
<screen>
<prompt>$</prompt> <userinput>pg_ctl -o "-F -p 5433" restart</userinput>
</screen>
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index 25dc2a7014..e78d275c0d 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -301,7 +301,8 @@ PostgreSQL documentation
linkend="APP-PSQL-patterns" endterm="APP-PSQL-patterns-title">),
so multiple schemas can also be selected by writing wildcard characters
in the pattern. When using wildcards, be careful to quote the pattern
- if needed to prevent the shell from expanding the wildcards.
+ if needed to prevent the shell from expanding the wildcards; see
+ <xref linkend="pg-dump-examples" endterm="pg-dump-examples-title">.
</para>
<note>
@@ -435,7 +436,8 @@ PostgreSQL documentation
linkend="APP-PSQL-patterns" endterm="APP-PSQL-patterns-title">),
so multiple tables can also be selected by writing wildcard characters
in the pattern. When using wildcards, be careful to quote the pattern
- if needed to prevent the shell from expanding the wildcards.
+ if needed to prevent the shell from expanding the wildcards; see
+ <xref linkend="pg-dump-examples" endterm="pg-dump-examples-title">.
</para>
<para>
@@ -973,7 +975,7 @@ CREATE DATABASE foo WITH TEMPLATE template0;
</refsect1>
<refsect1 id="pg-dump-examples">
- <title>Examples</title>
+ <title id="pg-dump-examples-title">Examples</title>
<para>
To dump a database called <literal>mydb</> into a SQL-script file:
diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml
index 4437bf8997..bd4ae338f7 100644
--- a/doc/src/sgml/ref/postgres-ref.sgml
+++ b/doc/src/sgml/ref/postgres-ref.sgml
@@ -66,9 +66,9 @@ PostgreSQL documentation
The <command>postgres</command> command can also be called in
single-user mode. The primary use for this mode is during
bootstrapping by <xref linkend="app-initdb">. Sometimes it is used
- for debugging or disaster recovery (but note that running a single-user
+ for debugging or disaster recovery; note that running a single-user
server is not truly suitable for debugging the server, since no
- realistic interprocess communication and locking will happen).
+ realistic interprocess communication and locking will happen.
When invoked in single-user
mode from the shell, the user can enter queries and the results
will be printed to the screen, but in a form that is more useful
@@ -413,8 +413,8 @@ PostgreSQL documentation
<term><option>-P</option></term>
<listitem>
<para>
- Ignore system indexes when reading system tables (but still update
- the indexes when modifying the tables). This is useful when
+ Ignore system indexes when reading system tables, but still update
+ the indexes when modifying the tables. This is useful when
recovering from damaged system indexes.
</para>
</listitem>
@@ -745,7 +745,10 @@ PostgreSQL documentation
<para>
Note that the single-user mode server does not provide sophisticated
- line-editing features (no command history, for example).
+ line-editing features (no command history, for example).
+ Single-User mode also does not do any background processing, like
+ automatic checkpoints.
+
</para>
</refsect1>
@@ -763,13 +766,11 @@ PostgreSQL documentation
<para>
To start <command>postgres</command> with a specific
- port:
+ port, e.g. 1234:
<screen>
<prompt>$</prompt> <userinput>postgres -p 1234</userinput>
</screen>
- This command will start up <command>postgres</command>
- communicating through the port 1234. In order to connect to this
- server using <application>psql</>, you would need to run it as
+ To connect to this server using <application>psql</>, specify this port with the -p option:
<screen>
<prompt>$</prompt> <userinput>psql -p 1234</userinput>
</screen>
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index baefb57882..24e8ee0a36 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -74,7 +74,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-c <replaceable class="parameter">command</replaceable></></term>
- <term><option>--command <replaceable class="parameter">command</replaceable></></term>
+ <term><option>--command=<replaceable class="parameter">command</replaceable></></term>
<listitem>
<para>
Specifies that <application>psql</application> is to execute one
@@ -107,7 +107,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-d <replaceable class="parameter">dbname</replaceable></></term>
- <term><option>--dbname <replaceable class="parameter">dbname</replaceable></></term>
+ <term><option>--dbname=<replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
Specifies the name of the database to connect to. This is
@@ -151,7 +151,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-f <replaceable class="parameter">filename</replaceable></></term>
- <term><option>--file <replaceable class="parameter">filename</replaceable></></term>
+ <term><option>--file=<replaceable class="parameter">filename</replaceable></></term>
<listitem>
<para>
Use the file <replaceable class="parameter">filename</replaceable>
@@ -183,7 +183,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-F <replaceable class="parameter">separator</replaceable></></term>
- <term><option>--field-separator <replaceable class="parameter">separator</replaceable></></term>
+ <term><option>--field-separator=<replaceable class="parameter">separator</replaceable></></term>
<listitem>
<para>
Use <replaceable class="parameter">separator</replaceable> as the
@@ -195,7 +195,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-h <replaceable class="parameter">hostname</replaceable></></term>
- <term><option>--host <replaceable class="parameter">hostname</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">hostname</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the
@@ -232,7 +232,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-L <replaceable class="parameter">filename</replaceable></></term>
- <term><option>--log-file <replaceable class="parameter">filename</replaceable></></term>
+ <term><option>--log-file=<replaceable class="parameter">filename</replaceable></></term>
<listitem>
<para>
Write all query output into file <replaceable
@@ -255,7 +255,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-o <replaceable class="parameter">filename</replaceable></></term>
- <term><option>--output <replaceable class="parameter">filename</replaceable></></term>
+ <term><option>--output=<replaceable class="parameter">filename</replaceable></></term>
<listitem>
<para>
Put all query output into file <replaceable
@@ -267,7 +267,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or the local Unix-domain
@@ -281,7 +281,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-P <replaceable class="parameter">assignment</replaceable></></term>
- <term><option>--pset <replaceable class="parameter">assignment</replaceable></></term>
+ <term><option>--pset=<replaceable class="parameter">assignment</replaceable></></term>
<listitem>
<para>
Specifies printing options, in the style of
@@ -310,7 +310,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-R <replaceable class="parameter">separator</replaceable></></term>
- <term><option>--record-separator <replaceable class="parameter">separator</replaceable></></term>
+ <term><option>--record-separator=<replaceable class="parameter">separator</replaceable></></term>
<listitem>
<para>
Use <replaceable class="parameter">separator</replaceable> as the
@@ -365,7 +365,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-T <replaceable class="parameter">table_options</replaceable></></term>
- <term><option>--table-attr <replaceable class="parameter">table_options</replaceable></></term>
+ <term><option>--table-attr=<replaceable class="parameter">table_options</replaceable></></term>
<listitem>
<para>
Specifies options to be placed within the
@@ -377,7 +377,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
Connect to the database as the user <replaceable
@@ -389,8 +389,8 @@ PostgreSQL documentation
<varlistentry>
<term><option>-v <replaceable class="parameter">assignment</replaceable></></term>
- <term><option>--set <replaceable class="parameter">assignment</replaceable></></term>
- <term><option>--variable <replaceable class="parameter">assignment</replaceable></></term>
+ <term><option>--set=<replaceable class="parameter">assignment</replaceable></></term>
+ <term><option>--variable=<replaceable class="parameter">assignment</replaceable></></term>
<listitem>
<para>
Perform a variable assignment, like the <command>\set</command>
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
index fa4d7b41c7..026bdcc718 100644
--- a/doc/src/sgml/ref/reindexdb.sgml
+++ b/doc/src/sgml/ref/reindexdb.sgml
@@ -80,7 +80,7 @@ PostgreSQL documentation
<varlistentry>
<term><option><optional>-d</> <replaceable class="parameter">dbname</replaceable></></term>
- <term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></></term>
+ <term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
<listitem>
<para>
Specifies the name of the database to be reindexed.
@@ -106,7 +106,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-i <replaceable class="parameter">index</replaceable></></term>
- <term><option>--index <replaceable class="parameter">index</replaceable></></term>
+ <term><option>--index=<replaceable class="parameter">index</replaceable></></term>
<listitem>
<para>
Recreate <replaceable class="parameter">index</replaceable> only.
@@ -136,7 +136,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable></></term>
- <term><option>--table <replaceable class="parameter">table</replaceable></></term>
+ <term><option>--table=<replaceable class="parameter">table</replaceable></></term>
<listitem>
<para>
Reindex <replaceable class="parameter">table</replaceable> only.
@@ -176,7 +176,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the server is
@@ -188,7 +188,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -200,7 +200,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml
index b4833f1252..e9022fe947 100644
--- a/doc/src/sgml/ref/vacuumdb.sgml
+++ b/doc/src/sgml/ref/vacuumdb.sgml
@@ -85,7 +85,7 @@ PostgreSQL documentation
<varlistentry>
<term><option><optional>-d</> <replaceable class="parameter">dbname</replaceable></option></term>
- <term><option><optional>--dbname</> <replaceable class="parameter">dbname</replaceable></option></term>
+ <term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></option></term>
<listitem>
<para>
Specifies the name of the database to be cleaned or analyzed.
@@ -141,7 +141,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable> [ (<replaceable class="parameter">column</replaceable> [,...]) ]</option></term>
- <term><option>--table <replaceable class="parameter">table</replaceable> [ (<replaceable class="parameter">column</replaceable> [,...]) ]</option></term>
+ <term><option>--table=<replaceable class="parameter">table</replaceable> [ (<replaceable class="parameter">column</replaceable> [,...]) ]</option></term>
<listitem>
<para>
Clean or analyze <replaceable class="parameter">table</replaceable> only.
@@ -217,7 +217,7 @@ PostgreSQL documentation
<variablelist>
<varlistentry>
<term><option>-h <replaceable class="parameter">host</replaceable></></term>
- <term><option>--host <replaceable class="parameter">host</replaceable></></term>
+ <term><option>--host=<replaceable class="parameter">host</replaceable></></term>
<listitem>
<para>
Specifies the host name of the machine on which the server
@@ -229,7 +229,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-p <replaceable class="parameter">port</replaceable></></term>
- <term><option>--port <replaceable class="parameter">port</replaceable></></term>
+ <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
<listitem>
<para>
Specifies the TCP port or local Unix domain socket file
@@ -241,7 +241,7 @@ PostgreSQL documentation
<varlistentry>
<term><option>-U <replaceable class="parameter">username</replaceable></></term>
- <term><option>--username <replaceable class="parameter">username</replaceable></></term>
+ <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
<listitem>
<para>
User name to connect as.
diff --git a/doc/src/sgml/release-9.1.sgml b/doc/src/sgml/release-9.1.sgml
index 2ea0fd7e21..9f14a46f7c 100644
--- a/doc/src/sgml/release-9.1.sgml
+++ b/doc/src/sgml/release-9.1.sgml
@@ -1,6 +1,6 @@
<!-- doc/src/sgml/release-9.1.sgml -->
-<!-- This is (hopefully) up-to-date with commits through 2011-03-05 -->
+<!-- This is (hopefully) up-to-date with commits through 2011-03-08 -->
<sect1 id="release-9-1-alpha">
<title>Release 9.1alpha4</title>
@@ -122,6 +122,24 @@
</para>
</listitem>
+ <listitem>
+ <para>
+ <emphasis>Synchronous replication</emphasis>
+ </para>
+ <para>
+ When enabled, transaction commit will wait for WAL records to be
+ replicated before informing the client that a transaction has
+ successfully committed.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>When recovery_target_timeline='latest', periodically
+ rescan the archive for new timelines</emphasis>
+ </para>
+ </listitem>
+
</itemizedlist>
</sect3>
@@ -226,7 +244,7 @@
<listitem>
<para>
<emphasis>Allow a table's row type to be cast to the table's supertype
- if it's a type table.</emphasis>
+ if it's a type table</emphasis>
</para>
<para>
This is analagous to the existing facility that allows casting a row
@@ -237,7 +255,7 @@
<listitem>
<para>
<emphasis>Make foreign data wrappers functional, and support FOREIGN
- TABLEs.</emphasis>
+ TABLEs</emphasis>
</para>
<para>
Foreign tables are component of SQL/MED, and provide a framework to
@@ -249,14 +267,14 @@
<listitem>
<para>
<emphasis>Allow a unique or primary key constraint to be created
- using an existing index.</emphasis>
+ using an existing index</emphasis>
</para>
</listitem>
<listitem>
<para>
<emphasis>Implement Serializable Snapshot Isolation, in order to
- provide a more robust serializable transaction mode.</emphasis>
+ provide a more robust serializable transaction mode</emphasis>
</para>
<para>
In previous releases, the REPEATABLE READ and SERIALIZABLE isolation
@@ -290,7 +308,7 @@
<listitem>
<para>
- <emphasis>Teach ALTER TABLE .. SET DATA TYPE to avoid a table write
+ <emphasis>Teach ALTER TABLE ... SET DATA TYPE to avoid a table write
in some cases where it isn't necessary
</emphasis>
</para>
@@ -372,7 +390,7 @@
<listitem>
<para>
- <emphasis>Support unlogged tables.</emphasis>
+ <emphasis>Support unlogged tables</emphasis>
</para>
<para>
The contents of an unlogged table are not WAL-logged; thus, they
@@ -384,7 +402,7 @@
<listitem>
<para>
- <emphasis>Hash joins now support right and full outer joins.</emphasis>
+ <emphasis>Hash joins now support right and full outer joins</emphasis>
</para>
<para>
Previously, full joins could be implemented only as a merge join,
@@ -581,8 +599,7 @@
<listitem>
<para>
- Support host names and host key
- word <literal>all</literal>
+ Support host names and host key word <literal>all</literal>
in <filename>pg_hba.conf</filename>
</para>
</listitem>
@@ -648,7 +665,7 @@
<para>
<emphasis>When an autovacuum worker (other than one performing an
anti-wraparound vacuum) is unable to obtain a lock on the target
- relation without blocking, skip the relation.</emphasis>
+ relation without blocking, skip the relation</emphasis>
</para>
<para>
This avoids pinning down an autovacuum worker. The next autovacuum
@@ -694,7 +711,7 @@
<listitem>
<para>
- <emphasis>Add REPLICATION privilege for ROLEs.</emphasis>
+ <emphasis>Add REPLICATION privilege for ROLEs</emphasis>
</para>
<para>
This makes it possible for replication to be performed by a
@@ -781,7 +798,7 @@
<listitem>
<para>
<emphasis>Change pg_last_xlog_receive_location not to move
- backwards.</emphasis>
+ backwards</emphasis>
</para>
</listitem>
@@ -1011,15 +1028,14 @@
<listitem>
<para>
- <emphasis>Skip dropped attributes when converting Python objects to
- tuples</emphasis>
+ <emphasis>Make plpy.Fatal() raise FATAL, rather than ERROR</emphasis>
</para>
</listitem>
<listitem>
<para>
- <emphasis>Improve messages for errors in compiling anonymous
- PL/Python blocks</emphasis>
+ <emphasis>Skip dropped attributes when converting Python objects to
+ tuples</emphasis>
</para>
</listitem>
@@ -1043,11 +1059,17 @@
<listitem>
<para>
- <emphasis>Do not prefix error messages with the string
- "PL/Python: "</emphasis>
+ <emphasis>Improve error reporting</emphasis>
</para>
- <para>
- It is redundant, given the error context.
+ <para>Better error messages for errors in compiling anonymous
+ PL/Python blocks. Avoid prefixing error messages with the string
+ "PL/Python: ", which is redundant, given the error
+ context. Provide a separate exception class for each error code
+ the backend defines, and make it possible to get the SQLSTATE from
+ the exception object. Report Python errors from iterators
+ using PLy_elog, so that the Python exception is included in the
+ exception, and to avoid setting the errcode to
+ ERRCODE_DATA_EXCEPTION.
</para>
</listitem>
@@ -1097,14 +1119,6 @@
<listitem>
<para>
- <emphasis>Provide a separate exception class for each error code
- the backend defines, and make it possible to get the SQLSTATE from
- the exception object</emphasis>
- </para>
- </listitem>
-
- <listitem>
- <para>
<emphasis>Assorted code cleanup</emphasis>
</para>
<para>
diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml
index b4c4b5e23e..4822394300 100644
--- a/doc/src/sgml/syntax.sgml
+++ b/doc/src/sgml/syntax.sgml
@@ -1259,6 +1259,12 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
<listitem>
<para>
+ A collation expression
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
A scalar subquery
</para>
</listitem>
@@ -1898,8 +1904,8 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
</note>
</sect2>
- <sect2 id="sql-syntax-collate-clause">
- <title>COLLATE Clause</title>
+ <sect2 id="sql-syntax-collate-exprs">
+ <title>Collation Expressions</title>
<indexterm>
<primary>COLLATE</primary>
@@ -1925,7 +1931,7 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
</para>
<para>
- The two typical uses of the <literal>COLLATE</literal> clause are
+ The two common uses of the <literal>COLLATE</literal> clause are
overriding the sort order in an <literal>ORDER BY</> clause, for
example:
<programlisting>
@@ -1934,15 +1940,28 @@ SELECT a, b, c FROM tbl WHERE ... ORDER BY a COLLATE "C";
and overriding the collation of a function or operator call that
has locale-sensitive results, for example:
<programlisting>
-SELECT * FROM tbl WHERE a > 'foo' COLLATE "C";
+SELECT * FROM tbl WHERE a &gt; 'foo' COLLATE "C";
+</programlisting>
+ Note that in the latter case the <literal>COLLATE</> clause is
+ attached to an input argument of the operator we wish to affect.
+ It doesn't matter which argument of the operator or function call the
+ <literal>COLLATE</> clause is attached to, because the collation that is
+ applied by the operator or function is derived by considering all
+ arguments, and an explicit <literal>COLLATE</> clause will override the
+ collations of all other arguments. (Attaching non-matching
+ <literal>COLLATE</> clauses to more than one argument, however, is an
+ error. For more details see <xref linkend="collation">.)
+ Thus, this gives the same result as the previous example:
+<programlisting>
+SELECT * FROM tbl WHERE a COLLATE "C" &gt; 'foo';
+</programlisting>
+ But this is an error:
+<programlisting>
+SELECT * FROM tbl WHERE (a &gt; 'foo') COLLATE "C";
</programlisting>
- In the latter case it doesn't matter which argument of the
- operator of function call the <literal>COLLATE</> clause is
- attached to, because the collation that is applied by the operator
- or function is derived from all arguments, and
- the <literal>COLLATE</> clause will override the collations of all
- other arguments. Attaching nonmatching <literal>COLLATE</>
- clauses to more than one argument, however, is an error.
+ because it attempts to apply a collation to the result of the
+ <literal>&gt;</> operator, which is of the non-collatable data type
+ <type>boolean</>.
</para>
</sect2>
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index c65f8522b3..1a35014170 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -116,9 +116,9 @@
Besides <command>SELECT</command> queries, the commands can include data
modification queries (<command>INSERT</command>,
<command>UPDATE</command>, and <command>DELETE</command>), as well as
- other SQL commands. (The only exception is that you cannot put
- <command>BEGIN</>, <command>COMMIT</>, <command>ROLLBACK</>, or
- <command>SAVEPOINT</> commands into a <acronym>SQL</acronym> function.)
+ other SQL commands. (You cannot use transaction control commands, e.g.
+ <command>COMMIT</>, <command>SAVEPOINT</>, and some utility
+ commands, e.g. <literal>VACUUM</>, in <acronym>SQL</acronym> functions.)
However, the final command
must be a <command>SELECT</command> or have a <literal>RETURNING</>
clause that returns whatever is
diff --git a/src/Makefile b/src/Makefile
index 4469d2cdf2..a0460342e8 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -50,14 +50,19 @@ uninstall: uninstall-local
uninstall-local:
rm -f $(addprefix '$(DESTDIR)$(pgxsdir)/$(subdir)'/, Makefile.global Makefile.port Makefile.shlib nls-global.mk)
+distprep:
+ $(MAKE) -C test/isolation $@
+
clean:
$(MAKE) -C test $@
$(MAKE) -C tutorial NO_PGXS=1 $@
+ $(MAKE) -C test/isolation $@
$(MAKE) -C test/thread $@
distclean maintainer-clean:
$(MAKE) -C test $@
$(MAKE) -C tutorial NO_PGXS=1 $@
+ $(MAKE) -C test/isolation $@
$(MAKE) -C test/thread $@
rm -f Makefile.port Makefile.global
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 2b2c9bb9a2..bbc59f76c7 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -193,10 +193,12 @@ utils/probes.o: utils/probes.d $(SUBDIROBJS)
##########################################################################
+# Be sure that these files get removed by the maintainer-clean target
distprep:
$(MAKE) -C parser gram.c gram.h scan.c
$(MAKE) -C bootstrap bootparse.c bootscanner.c
$(MAKE) -C catalog schemapg.h postgres.bki postgres.description postgres.shdescription
+ $(MAKE) -C replication repl_gram.c repl_scanner.c
$(MAKE) -C utils fmgrtab.c fmgroids.h errcodes.h
$(MAKE) -C utils/misc guc-file.c
@@ -300,12 +302,15 @@ maintainer-clean: distclean
rm -f bootstrap/bootparse.c \
bootstrap/bootscanner.c \
parser/gram.c \
- parser/scan.c \
parser/gram.h \
+ parser/scan.c \
catalog/schemapg.h \
catalog/postgres.bki \
catalog/postgres.description \
catalog/postgres.shdescription \
+ replication/repl_gram.c \
+ replication/repl_gram.h \
+ replication/repl_scanner.c \
utils/fmgroids.h \
utils/fmgrtab.c \
utils/errcodes.h \
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 0cd1f941e3..d78b08381e 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -559,7 +559,8 @@ BuildDescForRelation(List *schema)
attnum++;
attname = entry->colname;
- typenameTypeIdModColl(NULL, entry->typeName, &atttypid, &atttypmod, &attcollation);
+ typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
+ attcollation = GetColumnDefCollation(NULL, entry, atttypid);
attdim = list_length(entry->typeName->arrayBounds);
if (entry->typeName->setof)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ddcad46b7a..15af6693f5 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6482,6 +6482,9 @@ StartupXLOG(void)
{
if (recoveryPauseAtTarget)
{
+ ereport(LOG,
+ (errmsg("recovery has paused"),
+ errhint("Execute pg_xlog_replay_resume() to continue.")));
SetRecoveryPause(true);
recoveryPausesHere();
}
@@ -8597,7 +8600,7 @@ get_sync_bit(int method)
/*
* Optimize writes by bypassing kernel cache with O_DIRECT when using
- * O_SYNC, O_DSYNC or O_FSYNC. But only if archiving and streaming are
+ * O_SYNC/O_FSYNC and O_DSYNC. But only if archiving and streaming are
* disabled, otherwise the archive command or walsender process will read
* the WAL soon after writing it, which is guaranteed to cause a physical
* read if we bypassed the kernel cache. We also skip the
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index a98f918a23..48fa6d48b7 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -4736,6 +4736,36 @@ pg_extension_ownercheck(Oid ext_oid, Oid roleid)
}
/*
+ * Check whether specified role has CREATEROLE privilege (or is a superuser)
+ *
+ * Note: roles do not have owners per se; instead we use this test in
+ * places where an ownership-like permissions test is needed for a role.
+ * Be sure to apply it to the role trying to do the operation, not the
+ * role being operated on! Also note that this generally should not be
+ * considered enough privilege if the target role is a superuser.
+ * (We don't handle that consideration here because we want to give a
+ * separate error message for such cases, so the caller has to deal with it.)
+ */
+bool
+has_createrole_privilege(Oid roleid)
+{
+ bool result = false;
+ HeapTuple utup;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+ if (HeapTupleIsValid(utup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
+ ReleaseSysCache(utup);
+ }
+ return result;
+}
+
+/*
* Fetch pg_default_acl entry for given role, namespace and object type
* (object type must be given in pg_default_acl's encoding).
* Returns NULL if no such entry.
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index b8b89ab7c1..880b95df02 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -808,13 +808,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
NameListToString(objname));
break;
- case OBJECT_ROLE:
- if (!has_privs_of_role(roleid, address.objectId))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be member of role \"%s\"",
- NameListToString(objname))));
- break;
case OBJECT_TSDICTIONARY:
if (!pg_ts_dict_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
@@ -825,6 +818,26 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
NameListToString(objname));
break;
+ case OBJECT_ROLE:
+ /*
+ * We treat roles as being "owned" by those with CREATEROLE priv,
+ * except that superusers are only owned by superusers.
+ */
+ if (superuser_arg(address.objectId))
+ {
+ if (!superuser_arg(roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser")));
+ }
+ else
+ {
+ if (!has_createrole_privilege(roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must have CREATEROLE privilege")));
+ }
+ break;
case OBJECT_FDW:
case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 3f7d7d913a..325d4523e6 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -694,9 +694,5 @@ COMMENT ON FUNCTION ts_debug(text) IS
--
CREATE OR REPLACE FUNCTION
- format_type(oid, int DEFAULT NULL, oid DEFAULT NULL)
- RETURNS text STABLE LANGUAGE internal AS 'format_type';
-
-CREATE OR REPLACE FUNCTION
pg_start_backup(label text, fast boolean DEFAULT false)
RETURNS text STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup';
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 18e88d2653..a52cb351ac 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -98,7 +98,7 @@ DefineCollation(List *names, List *parameters)
Oid collid;
HeapTuple tp;
- collid = LookupCollation(NULL, defGetQualifiedName(fromEl), -1);
+ collid = get_collation_oid(defGetQualifiedName(fromEl), false);
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for collation %u", collid);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 3f25b3bf02..a8ef947240 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -87,7 +87,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
Oid rettype;
Type typtup;
- typtup = LookupTypeName(NULL, returnType, NULL, NULL);
+ typtup = LookupTypeName(NULL, returnType, NULL);
if (typtup)
{
@@ -207,7 +207,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
Oid toid;
Type typtup;
- typtup = LookupTypeName(NULL, t, NULL, NULL);
+ typtup = LookupTypeName(NULL, t, NULL);
if (typtup)
{
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index e71c311faf..5c6212c64c 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -139,9 +139,12 @@ DefineSequence(CreateSeqStmt *seq)
coldef->inhcount = 0;
coldef->is_local = true;
coldef->is_not_null = true;
+ coldef->is_from_type = false;
coldef->storage = 0;
coldef->raw_default = NULL;
coldef->cooked_default = NULL;
+ coldef->collClause = NULL;
+ coldef->collOid = InvalidOid;
coldef->constraints = NIL;
null[i - 1] = false;
@@ -149,53 +152,53 @@ DefineSequence(CreateSeqStmt *seq)
switch (i)
{
case SEQ_COL_NAME:
- coldef->typeName = makeTypeNameFromOid(NAMEOID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(NAMEOID, -1);
coldef->colname = "sequence_name";
namestrcpy(&name, seq->sequence->relname);
value[i - 1] = NameGetDatum(&name);
break;
case SEQ_COL_LASTVAL:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "last_value";
value[i - 1] = Int64GetDatumFast(new.last_value);
break;
case SEQ_COL_STARTVAL:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "start_value";
value[i - 1] = Int64GetDatumFast(new.start_value);
break;
case SEQ_COL_INCBY:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "increment_by";
value[i - 1] = Int64GetDatumFast(new.increment_by);
break;
case SEQ_COL_MAXVALUE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "max_value";
value[i - 1] = Int64GetDatumFast(new.max_value);
break;
case SEQ_COL_MINVALUE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "min_value";
value[i - 1] = Int64GetDatumFast(new.min_value);
break;
case SEQ_COL_CACHE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "cache_value";
value[i - 1] = Int64GetDatumFast(new.cache_value);
break;
case SEQ_COL_LOG:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "log_cnt";
value[i - 1] = Int64GetDatum((int64) 1);
break;
case SEQ_COL_CYCLE:
- coldef->typeName = makeTypeNameFromOid(BOOLOID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
coldef->colname = "is_cycled";
value[i - 1] = BoolGetDatum(new.is_cycled);
break;
case SEQ_COL_CALLED:
- coldef->typeName = makeTypeNameFromOid(BOOLOID, -1, InvalidOid);
+ coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
coldef->colname = "is_called";
value[i - 1] = BoolGetDatum(false);
break;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 3be9a6f348..f1264bfb66 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -339,7 +339,7 @@ static void ATPrepAlterColumnType(List **wqueue,
AlterTableCmd *cmd, LOCKMODE lockmode);
static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno);
static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
- const char *colName, TypeName *typeName, LOCKMODE lockmode);
+ AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode);
static void ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode);
static void change_owner_recurse_to_sequences(Oid relationOid,
@@ -1433,7 +1433,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
(errmsg("merging multiple inherited definitions of column \"%s\"",
attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
- typenameTypeIdModColl(NULL, def->typeName, &defTypeId, &deftypmod, &defCollId);
+ typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod);
if (defTypeId != attribute->atttypid ||
deftypmod != attribute->atttypmod)
ereport(ERROR,
@@ -1443,6 +1443,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
errdetail("%s versus %s",
TypeNameToString(def->typeName),
format_type_be(attribute->atttypid))));
+ defCollId = GetColumnDefCollation(NULL, def, defTypeId);
if (defCollId != attribute->attcollation)
ereport(ERROR,
(errcode(ERRCODE_COLLATION_MISMATCH),
@@ -1478,14 +1479,16 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
def = makeNode(ColumnDef);
def->colname = pstrdup(attributeName);
def->typeName = makeTypeNameFromOid(attribute->atttypid,
- attribute->atttypmod,
- attribute->attcollation);
+ attribute->atttypmod);
def->inhcount = 1;
def->is_local = false;
def->is_not_null = attribute->attnotnull;
+ def->is_from_type = false;
def->storage = attribute->attstorage;
def->raw_default = NULL;
def->cooked_default = NULL;
+ def->collClause = NULL;
+ def->collOid = attribute->attcollation;
def->constraints = NIL;
inhSchema = lappend(inhSchema, def);
newattno[parent_attno - 1] = ++child_attno;
@@ -1616,8 +1619,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
(errmsg("merging column \"%s\" with inherited definition",
attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
- typenameTypeIdModColl(NULL, def->typeName, &defTypeId, &deftypmod, &defcollid);
- typenameTypeIdModColl(NULL, newdef->typeName, &newTypeId, &newtypmod, &newcollid);
+ typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod);
+ typenameTypeIdAndMod(NULL, newdef->typeName, &newTypeId, &newtypmod);
if (defTypeId != newTypeId || deftypmod != newtypmod)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -1626,6 +1629,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
errdetail("%s versus %s",
TypeNameToString(def->typeName),
TypeNameToString(newdef->typeName))));
+ defcollid = GetColumnDefCollation(NULL, def, defTypeId);
+ newcollid = GetColumnDefCollation(NULL, newdef, newTypeId);
if (defcollid != newcollid)
ereport(ERROR,
(errcode(ERRCODE_COLLATION_MISMATCH),
@@ -3092,7 +3097,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
cmd->missing_ok, lockmode);
break;
case AT_AlterColumnType: /* ALTER COLUMN TYPE */
- ATExecAlterColumnType(tab, rel, cmd->name, (TypeName *) cmd->def, lockmode);
+ ATExecAlterColumnType(tab, rel, cmd, lockmode);
break;
case AT_ChangeOwner: /* ALTER OWNER */
ATExecChangeOwner(RelationGetRelid(rel),
@@ -4129,13 +4134,14 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
Oid ccollid;
/* Child column must match by type */
- typenameTypeIdModColl(NULL, colDef->typeName, &ctypeId, &ctypmod, &ccollid);
+ typenameTypeIdAndMod(NULL, colDef->typeName, &ctypeId, &ctypmod);
if (ctypeId != childatt->atttypid ||
ctypmod != childatt->atttypmod)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("child table \"%s\" has different type for column \"%s\"",
RelationGetRelationName(rel), colDef->colname)));
+ ccollid = GetColumnDefCollation(NULL, colDef, ctypeId);
if (ccollid != childatt->attcollation)
ereport(ERROR,
(errcode(ERRCODE_COLLATION_MISMATCH),
@@ -4201,9 +4207,10 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
MaxHeapAttributeNumber)));
}
- typeTuple = typenameType(NULL, colDef->typeName, &typmod, &collOid);
+ typeTuple = typenameType(NULL, colDef->typeName, &typmod);
tform = (Form_pg_type) GETSTRUCT(typeTuple);
typeOid = HeapTupleGetOid(typeTuple);
+ collOid = GetColumnDefCollation(NULL, colDef, typeOid);
/* make sure datatype is legal for a column */
CheckAttributeType(colDef->colname, typeOid, collOid, false);
@@ -4413,7 +4420,7 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC
ColumnDef *cdef = makeNode(ColumnDef);
cdef->colname = pstrdup("oid");
- cdef->typeName = makeTypeNameFromOid(OIDOID, -1, InvalidOid);
+ cdef->typeName = makeTypeNameFromOid(OIDOID, -1);
cdef->inhcount = 0;
cdef->is_local = true;
cdef->is_not_null = true;
@@ -6471,14 +6478,15 @@ ATPrepAlterColumnType(List **wqueue,
AlterTableCmd *cmd, LOCKMODE lockmode)
{
char *colName = cmd->name;
- TypeName *typeName = (TypeName *) cmd->def;
+ ColumnDef *def = (ColumnDef *) cmd->def;
+ TypeName *typeName = def->typeName;
+ Node *transform = def->raw_default;
HeapTuple tuple;
Form_pg_attribute attTup;
AttrNumber attnum;
Oid targettype;
int32 targettypmod;
Oid targetcollid;
- Node *transform;
NewColumnValue *newval;
ParseState *pstate = make_parsestate(NULL);
@@ -6512,7 +6520,10 @@ ATPrepAlterColumnType(List **wqueue,
colName)));
/* Look up the target type */
- typenameTypeIdModColl(NULL, typeName, &targettype, &targettypmod, &targetcollid);
+ typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod);
+
+ /* And the collation */
+ targetcollid = GetColumnDefCollation(NULL, def, targettype);
/* make sure datatype is legal for a column */
CheckAttributeType(colName, targettype, targetcollid, false);
@@ -6527,7 +6538,7 @@ ATPrepAlterColumnType(List **wqueue,
* because we need the expression to be parsed against the original table
* rowtype.
*/
- if (cmd->transform)
+ if (transform)
{
RangeTblEntry *rte;
@@ -6539,7 +6550,7 @@ ATPrepAlterColumnType(List **wqueue,
true);
addRTEtoQuery(pstate, rte, false, true, true);
- transform = transformExpr(pstate, cmd->transform);
+ transform = transformExpr(pstate, transform);
/* It can't return a set */
if (expression_returns_set(transform))
@@ -6592,16 +6603,13 @@ ATPrepAlterColumnType(List **wqueue,
if (ATColumnChangeRequiresRewrite(transform, attnum))
tab->rewrite = true;
}
- else if (tab->relkind == RELKIND_FOREIGN_TABLE)
- {
- if (cmd->transform)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("ALTER TYPE USING is not supported on foreign tables")));
- }
+ else if (transform)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("ALTER TYPE USING is only supported on plain tables")));
- if (tab->relkind == RELKIND_COMPOSITE_TYPE
- || tab->relkind == RELKIND_FOREIGN_TABLE)
+ if (tab->relkind == RELKIND_COMPOSITE_TYPE ||
+ tab->relkind == RELKIND_FOREIGN_TABLE)
{
/*
* For composite types, do this check now. Tables will check
@@ -6667,8 +6675,11 @@ ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno)
static void
ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
- const char *colName, TypeName *typeName, LOCKMODE lockmode)
+ AlterTableCmd *cmd, LOCKMODE lockmode)
{
+ char *colName = cmd->name;
+ ColumnDef *def = (ColumnDef *) cmd->def;
+ TypeName *typeName = def->typeName;
HeapTuple heapTup;
Form_pg_attribute attTup;
AttrNumber attnum;
@@ -6705,9 +6716,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
colName)));
/* Look up the target type (should not fail, since prep found it) */
- typeTuple = typenameType(NULL, typeName, &targettypmod, &targetcollid);
+ typeTuple = typenameType(NULL, typeName, &targettypmod);
tform = (Form_pg_type) GETSTRUCT(typeTuple);
targettype = HeapTupleGetOid(typeTuple);
+ /* And the collation */
+ targetcollid = GetColumnDefCollation(NULL, def, targettype);
/*
* If there is a default expression for the column, get it and ensure we
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index be1f1d791f..3513256b9a 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -292,7 +292,7 @@ DefineType(List *names, List *parameters)
Type likeType;
Form_pg_type likeForm;
- likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL, NULL);
+ likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL);
likeForm = (Form_pg_type) GETSTRUCT(likeType);
internalLength = likeForm->typlen;
byValue = likeForm->typbyval;
@@ -649,7 +649,7 @@ RemoveTypes(DropStmt *drop)
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */
- tup = LookupTypeName(NULL, typename, NULL, NULL);
+ tup = LookupTypeName(NULL, typename, NULL);
if (tup == NULL)
{
if (!drop->missing_ok)
@@ -774,6 +774,7 @@ DefineDomain(CreateDomainStmt *stmt)
Oid basetypeoid;
Oid domainoid;
Oid old_type_oid;
+ Oid domaincoll;
Form_pg_type baseType;
int32 basetypeMod;
Oid baseColl;
@@ -807,7 +808,7 @@ DefineDomain(CreateDomainStmt *stmt)
/*
* Look up the base type.
*/
- typeTup = typenameType(NULL, stmt->typeName, &basetypeMod, &baseColl);
+ typeTup = typenameType(NULL, stmt->typeName, &basetypeMod);
baseType = (Form_pg_type) GETSTRUCT(typeTup);
basetypeoid = HeapTupleGetOid(typeTup);
@@ -825,6 +826,22 @@ DefineDomain(CreateDomainStmt *stmt)
errmsg("\"%s\" is not a valid base type for a domain",
TypeNameToString(stmt->typeName))));
+ /*
+ * Identify the collation if any
+ */
+ baseColl = baseType->typcollation;
+ if (stmt->collClause)
+ domaincoll = get_collation_oid(stmt->collClause->collnames, false);
+ else
+ domaincoll = baseColl;
+
+ /* Complain if COLLATE is applied to an uncollatable type */
+ if (OidIsValid(domaincoll) && !OidIsValid(baseColl))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("collations are not supported by type %s",
+ format_type_be(basetypeoid))));
+
/* passed by value */
byValue = baseType->typbyval;
@@ -1051,7 +1068,7 @@ DefineDomain(CreateDomainStmt *stmt)
basetypeMod, /* typeMod value */
typNDims, /* Array dimensions for base type */
typNotNull, /* Type NOT NULL */
- baseColl);
+ domaincoll);
/*
* Process constraints which refer to the domain ID returned by TypeCreate
@@ -2629,7 +2646,7 @@ AlterTypeOwner(List *names, Oid newOwnerId)
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be processed */
- tup = LookupTypeName(NULL, typename, NULL, NULL);
+ tup = LookupTypeName(NULL, typename, NULL);
if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 63f22d8adc..f13eb2891e 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -58,20 +58,7 @@ static void DelRoleMems(const char *rolename, Oid roleid,
static bool
have_createrole_privilege(void)
{
- bool result = false;
- HeapTuple utup;
-
- /* Superusers can always do everything */
- if (superuser())
- return true;
-
- utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId()));
- if (HeapTupleIsValid(utup))
- {
- result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
- ReleaseSysCache(utup);
- }
- return result;
+ return has_createrole_privilege(GetUserId());
}
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 5576ea259f..794a56e84d 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -120,14 +120,23 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
def->colname = pstrdup(tle->resname);
def->typeName = makeTypeNameFromOid(exprType((Node *) tle->expr),
- exprTypmod((Node *) tle->expr),
- exprCollation((Node *) tle->expr));
+ exprTypmod((Node *) tle->expr));
def->inhcount = 0;
def->is_local = true;
def->is_not_null = false;
+ def->is_from_type = false;
def->storage = 0;
def->raw_default = NULL;
def->cooked_default = NULL;
+ def->collClause = NULL;
+ /*
+ * XXX Temporary kluge to make regression tests pass. We should
+ * be able to trust the result of exprCollation more than this.
+ */
+ if (type_is_collatable(exprType((Node *) tle->expr)))
+ def->collOid = exprCollation((Node *) tle->expr);
+ else
+ def->collOid = InvalidOid;
def->constraints = NIL;
attrList = lappend(attrList, def);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 86a16783f7..b948af604d 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2183,8 +2183,6 @@ _copyTypeName(TypeName *from)
COPY_NODE_FIELD(typmods);
COPY_SCALAR_FIELD(typemod);
COPY_NODE_FIELD(arrayBounds);
- COPY_NODE_FIELD(collnames);
- COPY_SCALAR_FIELD(collOid);
COPY_LOCATION_FIELD(location);
return newnode;
@@ -2295,9 +2293,12 @@ _copyColumnDef(ColumnDef *from)
COPY_SCALAR_FIELD(inhcount);
COPY_SCALAR_FIELD(is_local);
COPY_SCALAR_FIELD(is_not_null);
+ COPY_SCALAR_FIELD(is_from_type);
COPY_SCALAR_FIELD(storage);
COPY_NODE_FIELD(raw_default);
COPY_NODE_FIELD(cooked_default);
+ COPY_NODE_FIELD(collClause);
+ COPY_SCALAR_FIELD(collOid);
COPY_NODE_FIELD(constraints);
return newnode;
@@ -2515,7 +2516,6 @@ _copyAlterTableCmd(AlterTableCmd *from)
COPY_SCALAR_FIELD(subtype);
COPY_STRING_FIELD(name);
COPY_NODE_FIELD(def);
- COPY_NODE_FIELD(transform);
COPY_SCALAR_FIELD(behavior);
COPY_SCALAR_FIELD(missing_ok);
@@ -3063,6 +3063,7 @@ _copyCreateDomainStmt(CreateDomainStmt *from)
COPY_NODE_FIELD(domainname);
COPY_NODE_FIELD(typeName);
+ COPY_NODE_FIELD(collClause);
COPY_NODE_FIELD(constraints);
return newnode;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index c234416cf5..c8ee474436 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1007,7 +1007,6 @@ _equalAlterTableCmd(AlterTableCmd *a, AlterTableCmd *b)
COMPARE_SCALAR_FIELD(subtype);
COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(def);
- COMPARE_NODE_FIELD(transform);
COMPARE_SCALAR_FIELD(behavior);
COMPARE_SCALAR_FIELD(missing_ok);
@@ -1461,6 +1460,7 @@ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
{
COMPARE_NODE_FIELD(domainname);
COMPARE_NODE_FIELD(typeName);
+ COMPARE_NODE_FIELD(collClause);
COMPARE_NODE_FIELD(constraints);
return true;
@@ -2130,8 +2130,6 @@ _equalTypeName(TypeName *a, TypeName *b)
COMPARE_NODE_FIELD(typmods);
COMPARE_SCALAR_FIELD(typemod);
COMPARE_NODE_FIELD(arrayBounds);
- COMPARE_NODE_FIELD(collnames);
- COMPARE_SCALAR_FIELD(collOid);
COMPARE_LOCATION_FIELD(location);
return true;
@@ -2226,9 +2224,12 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
COMPARE_SCALAR_FIELD(inhcount);
COMPARE_SCALAR_FIELD(is_local);
COMPARE_SCALAR_FIELD(is_not_null);
+ COMPARE_SCALAR_FIELD(is_from_type);
COMPARE_SCALAR_FIELD(storage);
COMPARE_NODE_FIELD(raw_default);
COMPARE_NODE_FIELD(cooked_default);
+ COMPARE_NODE_FIELD(collClause);
+ COMPARE_SCALAR_FIELD(collOid);
COMPARE_NODE_FIELD(constraints);
return true;
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 0225f19382..d9f1645238 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -427,16 +427,15 @@ makeTypeNameFromNameList(List *names)
/*
* makeTypeNameFromOid -
- * build a TypeName node to represent a type already known by OID/typmod/collation.
+ * build a TypeName node to represent a type already known by OID/typmod.
*/
TypeName *
-makeTypeNameFromOid(Oid typeOid, int32 typmod, Oid collOid)
+makeTypeNameFromOid(Oid typeOid, int32 typmod)
{
TypeName *n = makeNode(TypeName);
n->typeOid = typeOid;
n->typemod = typmod;
- n->collOid = collOid;
n->location = -1;
return n;
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4aae2b33a6..06fd7ff818 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -2067,9 +2067,12 @@ _outColumnDef(StringInfo str, ColumnDef *node)
WRITE_INT_FIELD(inhcount);
WRITE_BOOL_FIELD(is_local);
WRITE_BOOL_FIELD(is_not_null);
+ WRITE_BOOL_FIELD(is_from_type);
WRITE_INT_FIELD(storage);
WRITE_NODE_FIELD(raw_default);
WRITE_NODE_FIELD(cooked_default);
+ WRITE_NODE_FIELD(collClause);
+ WRITE_OID_FIELD(collOid);
WRITE_NODE_FIELD(constraints);
}
@@ -2085,8 +2088,6 @@ _outTypeName(StringInfo str, TypeName *node)
WRITE_NODE_FIELD(typmods);
WRITE_INT_FIELD(typemod);
WRITE_NODE_FIELD(arrayBounds);
- WRITE_NODE_FIELD(collnames);
- WRITE_OID_FIELD(collOid);
WRITE_LOCATION_FIELD(location);
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 5b96b5b0df..373d2adc71 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -132,6 +132,9 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
static List *mergeTableFuncParameters(List *func_args, List *columns);
static TypeName *TableFuncTypeName(List *columns);
static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner);
+static void SplitColQualList(List *qualList,
+ List **constraintList, CollateClause **collClause,
+ core_yyscan_t yyscanner);
%}
@@ -221,7 +224,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
%type <node> alter_column_default opclass_item opclass_drop alter_using
%type <ival> add_drop opt_asc_desc opt_nulls_order
-%type <node> alter_table_cmd alter_type_cmd
+%type <node> alter_table_cmd alter_type_cmd opt_collate_clause
%type <list> alter_table_cmds alter_type_cmds
%type <dbehavior> opt_drop_behavior
@@ -400,8 +403,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
%type <list> copy_generic_opt_list copy_generic_opt_arg_list
%type <list> copy_options
-%type <typnam> Typename SimpleTypename SimpleTypenameWithoutCollation
- ConstTypename
+%type <typnam> Typename SimpleTypename ConstTypename
GenericType Numeric opt_float
Character ConstCharacter
CharacterWithLength CharacterWithoutLength
@@ -619,6 +621,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
%left '^'
/* Unary Operators */
%left AT ZONE /* sets precedence for AT TIME ZONE */
+%left COLLATE
%right UMINUS
%left '[' ']'
%left '(' ')'
@@ -1746,13 +1749,17 @@ alter_table_cmd:
* ALTER TABLE <name> ALTER [COLUMN] <colname> [SET DATA] TYPE <typename>
* [ USING <expression> ]
*/
- | ALTER opt_column ColId opt_set_data TYPE_P Typename alter_using
+ | ALTER opt_column ColId opt_set_data TYPE_P Typename opt_collate_clause alter_using
{
AlterTableCmd *n = makeNode(AlterTableCmd);
+ ColumnDef *def = makeNode(ColumnDef);
n->subtype = AT_AlterColumnType;
n->name = $3;
- n->def = (Node *) $6;
- n->transform = $7;
+ n->def = (Node *) def;
+ /* We only use these three fields of the ColumnDef node */
+ def->typeName = $6;
+ def->collClause = (CollateClause *) $7;
+ def->raw_default = $8;
$$ = (Node *)n;
}
/* ALTER TABLE <name> ADD CONSTRAINT ... */
@@ -1981,6 +1988,19 @@ opt_drop_behavior:
| /* EMPTY */ { $$ = DROP_RESTRICT; /* default */ }
;
+opt_collate_clause:
+ COLLATE any_name
+ {
+ CollateClause *n = makeNode(CollateClause);
+ n->arg = NULL;
+ n->collnames = $2;
+ n->collOid = InvalidOid;
+ n->location = @1;
+ $$ = (Node *) n;
+ }
+ | /* EMPTY */ { $$ = NULL; }
+ ;
+
alter_using:
USING a_expr { $$ = $2; }
| /* EMPTY */ { $$ = NULL; }
@@ -2077,13 +2097,18 @@ alter_type_cmd:
$$ = (Node *)n;
}
/* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> [RESTRICT|CASCADE] */
- | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_drop_behavior
+ | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_collate_clause opt_drop_behavior
{
AlterTableCmd *n = makeNode(AlterTableCmd);
+ ColumnDef *def = makeNode(ColumnDef);
n->subtype = AT_AlterColumnType;
n->name = $3;
- n->def = (Node *) $6;
- n->behavior = $7;
+ n->def = (Node *) def;
+ n->behavior = $8;
+ /* We only use these three fields of the ColumnDef node */
+ def->typeName = $6;
+ def->collClause = (CollateClause *) $7;
+ def->raw_default = NULL;
$$ = (Node *)n;
}
;
@@ -2454,8 +2479,16 @@ columnDef: ColId Typename ColQualList
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
n->typeName = $2;
- n->constraints = $3;
+ n->inhcount = 0;
n->is_local = true;
+ n->is_not_null = false;
+ n->is_from_type = false;
+ n->storage = 0;
+ n->raw_default = NULL;
+ n->cooked_default = NULL;
+ n->collOid = InvalidOid;
+ SplitColQualList($3, &n->constraints, &n->collClause,
+ yyscanner);
$$ = (Node *)n;
}
;
@@ -2464,8 +2497,17 @@ columnOptions: ColId WITH OPTIONS ColQualList
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
- n->constraints = $4;
+ n->typeName = NULL;
+ n->inhcount = 0;
n->is_local = true;
+ n->is_not_null = false;
+ n->is_from_type = false;
+ n->storage = 0;
+ n->raw_default = NULL;
+ n->cooked_default = NULL;
+ n->collOid = InvalidOid;
+ SplitColQualList($4, &n->constraints, &n->collClause,
+ yyscanner);
$$ = (Node *)n;
}
;
@@ -2486,6 +2528,20 @@ ColConstraint:
}
| ColConstraintElem { $$ = $1; }
| ConstraintAttr { $$ = $1; }
+ | COLLATE any_name
+ {
+ /*
+ * Note: the CollateClause is momentarily included in
+ * the list built by ColQualList, but we split it out
+ * again in SplitColQualList.
+ */
+ CollateClause *n = makeNode(CollateClause);
+ n->arg = NULL;
+ n->collnames = $2;
+ n->collOid = InvalidOid;
+ n->location = @1;
+ $$ = (Node *) n;
+ }
;
/* DEFAULT NULL is already the default for Postgres.
@@ -2973,8 +3029,12 @@ CreateAsElement:
n->inhcount = 0;
n->is_local = true;
n->is_not_null = false;
+ n->is_from_type = false;
+ n->storage = 0;
n->raw_default = NULL;
n->cooked_default = NULL;
+ n->collClause = NULL;
+ n->collOid = InvalidOid;
n->constraints = NIL;
$$ = (Node *)n;
}
@@ -6577,7 +6637,7 @@ opt_column: COLUMN { $$ = COLUMN; }
| /*EMPTY*/ { $$ = 0; }
;
-opt_set_data: SET DATA_P { $$ = 1; }
+opt_set_data: SET DATA_P { $$ = 1; }
| /*EMPTY*/ { $$ = 0; }
;
@@ -7443,7 +7503,8 @@ CreateDomainStmt:
CreateDomainStmt *n = makeNode(CreateDomainStmt);
n->domainname = $3;
n->typeName = $5;
- n->constraints = $6;
+ SplitColQualList($6, &n->constraints, &n->collClause,
+ yyscanner);
$$ = (Node *)n;
}
;
@@ -9084,13 +9145,21 @@ TableFuncElementList:
}
;
-TableFuncElement: ColId Typename
+TableFuncElement: ColId Typename opt_collate_clause
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
n->typeName = $2;
- n->constraints = NIL;
+ n->inhcount = 0;
n->is_local = true;
+ n->is_not_null = false;
+ n->is_from_type = false;
+ n->storage = 0;
+ n->raw_default = NULL;
+ n->cooked_default = NULL;
+ n->collClause = (CollateClause *) $3;
+ n->collOid = InvalidOid;
+ n->constraints = NIL;
$$ = (Node *)n;
}
;
@@ -9151,13 +9220,6 @@ opt_array_bounds:
;
SimpleTypename:
- SimpleTypenameWithoutCollation opt_collate
- {
- $$ = $1;
- $$->collnames = $2;
- }
-
-SimpleTypenameWithoutCollation:
GenericType { $$ = $1; }
| Numeric { $$ = $1; }
| Bit { $$ = $1; }
@@ -9625,6 +9687,14 @@ interval_second:
a_expr: c_expr { $$ = $1; }
| a_expr TYPECAST Typename
{ $$ = makeTypeCast($1, $3, @2); }
+ | a_expr COLLATE any_name
+ {
+ CollateClause *n = makeNode(CollateClause);
+ n->arg = (Expr *) $1;
+ n->collnames = $3;
+ n->location = @2;
+ $$ = (Node *) n;
+ }
| a_expr AT TIME ZONE a_expr
{
FuncCall *n = makeNode(FuncCall);
@@ -10193,14 +10263,6 @@ c_expr: columnref { $$ = $1; }
r->location = @1;
$$ = (Node *)r;
}
- | c_expr COLLATE any_name
- {
- CollateClause *n = makeNode(CollateClause);
- n->arg = (Expr *) $1;
- n->collnames = $3;
- n->location = @2;
- $$ = (Node *)n;
- }
;
/*
@@ -12678,15 +12740,6 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args,
return (Node *) x;
}
-/* parser_init()
- * Initialize to parse one query string
- */
-void
-parser_init(base_yy_extra_type *yyext)
-{
- yyext->parsetree = NIL; /* in case grammar forgets to set it */
-}
-
/*
* Merge the input and output parameters of a table function.
*/
@@ -12774,6 +12827,57 @@ makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner)
return r;
}
+/* Separate Constraint nodes from COLLATE clauses in a ColQualList */
+static void
+SplitColQualList(List *qualList,
+ List **constraintList, CollateClause **collClause,
+ core_yyscan_t yyscanner)
+{
+ ListCell *cell;
+ ListCell *prev;
+ ListCell *next;
+
+ *collClause = NULL;
+ prev = NULL;
+ for (cell = list_head(qualList); cell; cell = next)
+ {
+ Node *n = (Node *) lfirst(cell);
+
+ next = lnext(cell);
+ if (IsA(n, Constraint))
+ {
+ /* keep it in list */
+ prev = cell;
+ continue;
+ }
+ if (IsA(n, CollateClause))
+ {
+ CollateClause *c = (CollateClause *) n;
+
+ if (*collClause)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("multiple COLLATE clauses not allowed"),
+ parser_errposition(c->location)));
+ *collClause = c;
+ }
+ else
+ elog(ERROR, "unexpected node type %d", (int) n->type);
+ /* remove non-Constraint nodes from qualList */
+ qualList = list_delete_cell(qualList, cell, prev);
+ }
+ *constraintList = qualList;
+}
+
+/* parser_init()
+ * Initialize to parse one query string
+ */
+void
+parser_init(base_yy_extra_type *yyext)
+{
+ yyext->parsetree = NIL; /* in case grammar forgets to set it */
+}
+
/*
* Must undefine this stuff before including scan.c, since it has different
* definitions for these macros.
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index ae56532592..7a4f8cc249 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -147,12 +147,6 @@ transformExpr(ParseState *pstate, Node *expr)
{
TypeCast *tc = (TypeCast *) expr;
- if (tc->typeName->collnames)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("COLLATE clause not allowed in cast target"),
- parser_errposition(pstate, tc->typeName->location)));
-
/*
* If the subject of the typecast is an ARRAY[] construct and
* the target type is an array type, we invoke
@@ -2116,13 +2110,16 @@ transformCollateClause(ParseState *pstate, CollateClause *c)
newc->arg = (Expr *) transformExpr(pstate, (Node *) c->arg);
argtype = exprType((Node *) newc->arg);
- /* The unknown type is not collatable, but coerce_type() takes
- * care of it separately, so we'll let it go here. */
+ /*
+ * The unknown type is not collatable, but coerce_type() takes
+ * care of it separately, so we'll let it go here.
+ */
if (!type_is_collatable(argtype) && argtype != UNKNOWNOID)
ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("collations are not supported by type %s",
- format_type_be(argtype))));
+ format_type_be(argtype)),
+ parser_errposition(pstate, c->location)));
newc->collOid = LookupCollation(pstate, c->collnames, c->location);
newc->collnames = c->collnames;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 0af9cbd92b..a2d6c59810 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -1313,7 +1313,7 @@ FuncNameAsType(List *funcname)
Oid result;
Type typtup;
- typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL, NULL);
+ typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL);
if (typtup == NULL)
return InvalidOid;
@@ -1500,7 +1500,7 @@ LookupTypeNameOid(const TypeName *typename)
Oid result;
Type typtup;
- typtup = LookupTypeName(NULL, typename, NULL, NULL);
+ typtup = LookupTypeName(NULL, typename, NULL);
if (typtup == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index c7000b9915..488b1425a3 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1169,7 +1169,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
errmsg("column \"%s\" cannot be declared SETOF",
attrname),
parser_errposition(pstate, n->typeName->location)));
- typenameTypeIdModColl(pstate, n->typeName, &attrtype, &attrtypmod, &attrcollation);
+ typenameTypeIdAndMod(pstate, n->typeName, &attrtype, &attrtypmod);
+ attrcollation = GetColumnDefCollation(pstate, n, attrtype);
eref->colnames = lappend(eref->colnames, makeString(attrname));
rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 20cb47e712..2ba9bf5181 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -29,8 +29,6 @@
static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName,
Type typ);
-static Oid typenameCollation(ParseState *pstate, const TypeName *typeName,
- Type typ);
/*
@@ -38,8 +36,7 @@ static Oid typenameCollation(ParseState *pstate, const TypeName *typeName,
* Given a TypeName object, lookup the pg_type syscache entry of the type.
* Returns NULL if no such type can be found. If the type is found,
* the typmod value represented in the TypeName struct is computed and
- * stored into *typmod_p, and the collation is looked up and stored into
- * *colloid_p.
+ * stored into *typmod_p.
*
* NB: on success, the caller must ReleaseSysCache the type tuple when done
* with it.
@@ -54,18 +51,15 @@ static Oid typenameCollation(ParseState *pstate, const TypeName *typeName,
* found but is a shell, and there is typmod decoration, an error will be
* thrown --- this is intentional.
*
- * colloid_p can also be null.
- *
* pstate is only used for error location info, and may be NULL.
*/
Type
LookupTypeName(ParseState *pstate, const TypeName *typeName,
- int32 *typmod_p, Oid *collid_p)
+ int32 *typmod_p)
{
Oid typoid;
HeapTuple tup;
int32 typmod;
- Oid collid;
if (typeName->names == NIL)
{
@@ -180,28 +174,22 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName,
if (typmod_p)
*typmod_p = typmod;
- collid = typenameCollation(pstate, typeName, (Type) tup);
-
- if (collid_p)
- *collid_p = collid;
-
return (Type) tup;
}
/*
- * typenameType - given a TypeName, return a Type structure, typmod, and
- * collation
+ * typenameType - given a TypeName, return a Type structure and typmod
*
* This is equivalent to LookupTypeName, except that this will report
* a suitable error message if the type cannot be found or is not defined.
* Callers of this can therefore assume the result is a fully valid type.
*/
Type
-typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, Oid *collid_p)
+typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
{
Type tup;
- tup = LookupTypeName(pstate, typeName, typmod_p, collid_p);
+ tup = LookupTypeName(pstate, typeName, typmod_p);
if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -229,7 +217,7 @@ typenameTypeId(ParseState *pstate, const TypeName *typeName)
Oid typoid;
Type tup;
- tup = typenameType(pstate, typeName, NULL, NULL);
+ tup = typenameType(pstate, typeName, NULL);
typoid = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
@@ -248,25 +236,7 @@ typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName,
{
Type tup;
- tup = typenameType(pstate, typeName, typmod_p, NULL);
- *typeid_p = HeapTupleGetOid(tup);
- ReleaseSysCache(tup);
-}
-
-/*
- * typenameTypeIdModColl - given a TypeName, return the type's OID,
- * typmod, and collation
- *
- * This is equivalent to typenameType, but we only hand back the type OID,
- * typmod, and collation, not the syscache entry.
- */
-void
-typenameTypeIdModColl(ParseState *pstate, const TypeName *typeName,
- Oid *typeid_p, int32 *typmod_p, Oid *collid_p)
-{
- Type tup;
-
- tup = typenameType(pstate, typeName, typmod_p, collid_p);
+ tup = typenameType(pstate, typeName, typmod_p);
*typeid_p = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
}
@@ -381,62 +351,6 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
}
/*
- * typenameCollation - given a TypeName, return the collation OID
- *
- * This will throw an error if the TypeName includes a collation but
- * the data type does not support collations.
- *
- * The actual type OID represented by the TypeName must already have been
- * looked up, and is passed as "typ".
- *
- * pstate is only used for error location info, and may be NULL.
- */
-static Oid
-typenameCollation(ParseState *pstate, const TypeName *typeName, Type typ)
-{
- Oid typcollation = ((Form_pg_type) GETSTRUCT(typ))->typcollation;
-
- /* return prespecified collation OID if no collation name specified */
- if (typeName->collnames == NIL)
- {
- if (typeName->collOid == InvalidOid)
- return typcollation;
- else
- return typeName->collOid;
- }
-
- if (!OidIsValid(typcollation))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("collations are not supported by type %s",
- format_type_be(HeapTupleGetOid(typ))),
- parser_errposition(pstate, typeName->location)));
-
- return LookupCollation(pstate, typeName->collnames, typeName->location);
-}
-
-/*
- * LookupCollation
- *
- * Look up collation by name, return OID, with support for error
- * location.
- */
-Oid
-LookupCollation(ParseState *pstate, List *collnames, int location)
-{
- Oid colloid;
- ParseCallbackState pcbstate;
-
- setup_parser_errposition_callback(&pcbstate, pstate, location);
-
- colloid = get_collation_oid(collnames, false);
-
- cancel_parser_errposition_callback(&pcbstate);
-
- return colloid;
-}
-
-/*
* appendTypeNameToBuffer
* Append a string representing the name of a TypeName to a StringInfo.
* This is the shared guts of TypeNameToString and TypeNameListToString.
@@ -516,6 +430,72 @@ TypeNameListToString(List *typenames)
return string.data;
}
+/*
+ * LookupCollation
+ *
+ * Look up collation by name, return OID, with support for error location.
+ */
+Oid
+LookupCollation(ParseState *pstate, List *collnames, int location)
+{
+ Oid colloid;
+ ParseCallbackState pcbstate;
+
+ if (pstate)
+ setup_parser_errposition_callback(&pcbstate, pstate, location);
+
+ colloid = get_collation_oid(collnames, false);
+
+ if (pstate)
+ cancel_parser_errposition_callback(&pcbstate);
+
+ return colloid;
+}
+
+/*
+ * GetColumnDefCollation
+ *
+ * Get the collation to be used for a column being defined, given the
+ * ColumnDef node and the previously-determined column type OID.
+ *
+ * pstate is only used for error location purposes, and can be NULL.
+ */
+Oid
+GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
+{
+ Oid result;
+ Oid typcollation = get_typcollation(typeOid);
+ int location = -1;
+
+ if (coldef->collClause)
+ {
+ /* We have a raw COLLATE clause, so look up the collation */
+ location = coldef->collClause->location;
+ result = LookupCollation(pstate, coldef->collClause->collnames,
+ location);
+ }
+ else if (OidIsValid(coldef->collOid))
+ {
+ /* Precooked collation spec, use that */
+ result = coldef->collOid;
+ }
+ else
+ {
+ /* Use the type's default collation if any */
+ result = typcollation;
+ }
+
+ /* Complain if COLLATE is applied to an uncollatable type */
+ if (OidIsValid(result) && !OidIsValid(typcollation))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("collations are not supported by type %s",
+ format_type_be(typeOid)),
+ parser_errposition(pstate, location)));
+
+ return result;
+}
+
/* return a Type structure, given a type id */
/* NB: caller must ReleaseSysCache the type tuple when done with it */
Type
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 61ce840a5e..e876853af0 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -627,13 +627,16 @@ transformInhRelation(CreateStmtContext *cxt, InhRelation *inhRelation)
def = makeNode(ColumnDef);
def->colname = pstrdup(attributeName);
def->typeName = makeTypeNameFromOid(attribute->atttypid,
- attribute->atttypmod,
- attribute->attcollation);
+ attribute->atttypmod);
def->inhcount = 0;
def->is_local = true;
def->is_not_null = attribute->attnotnull;
+ def->is_from_type = false;
+ def->storage = 0;
def->raw_default = NULL;
def->cooked_default = NULL;
+ def->collClause = NULL;
+ def->collOid = attribute->attcollation;
def->constraints = NIL;
/*
@@ -822,7 +825,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
AssertArg(ofTypename);
- tuple = typenameType(NULL, ofTypename, NULL, NULL);
+ tuple = typenameType(NULL, ofTypename, NULL);
typ = (Form_pg_type) GETSTRUCT(tuple);
ofTypeId = HeapTupleGetOid(tuple);
ofTypename->typeOid = ofTypeId; /* cached for later */
@@ -837,16 +840,24 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
for (i = 0; i < tupdesc->natts; i++)
{
Form_pg_attribute attr = tupdesc->attrs[i];
- ColumnDef *n = makeNode(ColumnDef);
+ ColumnDef *n;
if (attr->attisdropped)
continue;
+ n = makeNode(ColumnDef);
n->colname = pstrdup(NameStr(attr->attname));
- n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod, attr->attcollation);
- n->constraints = NULL;
+ n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
+ n->inhcount = 0;
n->is_local = true;
+ n->is_not_null = false;
n->is_from_type = true;
+ n->storage = 0;
+ n->raw_default = NULL;
+ n->cooked_default = NULL;
+ n->collClause = NULL;
+ n->collOid = attr->attcollation;
+ n->constraints = NIL;
cxt->columns = lappend(cxt->columns, n);
}
DecrTupleDescRefCount(tupdesc);
@@ -2445,9 +2456,28 @@ static void
transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
{
/*
- * All we really need to do here is verify that the type is valid.
+ * All we really need to do here is verify that the type is valid,
+ * including any collation spec that might be present.
*/
- Type ctype = typenameType(cxt->pstate, column->typeName, NULL, NULL);
+ Type ctype = typenameType(cxt->pstate, column->typeName, NULL);
+
+ if (column->collClause)
+ {
+ Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
+ Oid collOid;
+
+ collOid = LookupCollation(cxt->pstate,
+ column->collClause->collnames,
+ column->collClause->location);
+ /* Complain if COLLATE is applied to an uncollatable type */
+ if (!OidIsValid(typtup->typcollation))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("collations are not supported by type %s",
+ format_type_be(HeapTupleGetOid(ctype))),
+ parser_errposition(cxt->pstate,
+ column->collClause->location)));
+ }
ReleaseSysCache(ctype);
}
diff --git a/src/backend/replication/README b/src/backend/replication/README
index 744ddc7fe8..7585429805 100644
--- a/src/backend/replication/README
+++ b/src/backend/replication/README
@@ -4,11 +4,11 @@ Walreceiver - libpqwalreceiver API
----------------------------------
The transport-specific part of walreceiver, responsible for connecting to
-the primary server and receiving WAL files, is loaded dynamically to avoid
-having to link the main server binary with libpq. The dynamically loaded
-module is in libpqwalreceiver subdirectory.
+the primary server, receiving WAL files and sending messages, is loaded
+dynamically to avoid having to link the main server binary with libpq.
+The dynamically loaded module is in libpqwalreceiver subdirectory.
-The dynamically loaded module implements three functions:
+The dynamically loaded module implements four functions:
bool walrcv_connect(char *conninfo, XLogRecPtr startpoint)
@@ -16,7 +16,6 @@ bool walrcv_connect(char *conninfo, XLogRecPtr startpoint)
Establish connection to the primary, and starts streaming from 'startpoint'.
Returns true on success.
-
bool walrcv_receive(int timeout, unsigned char *type, char **buffer, int *len)
Retrieve any message available through the connection, blocking for
@@ -26,6 +25,10 @@ otherwise false. On success, a pointer to the message payload is stored in
returned buffer is valid until the next call to walrcv_* functions, the
caller should not attempt freeing it.
+void walrcv_send(const char *buffer, int nbytes)
+
+Send a message to XLOG stream.
+
void walrcv_disconnect(void);
Disconnect.
@@ -45,11 +48,15 @@ to fetch more WAL (if streaming replication is configured).
Walreceiver is a postmaster subprocess, so the startup process can't fork it
directly. Instead, it sends a signal to postmaster, asking postmaster to launch
it. Before that, however, startup process fills in WalRcvData->conninfo,
-and initializes the starting point in WalRcvData->receivedUpto.
+and initializes the starting point in WalRcvData->receiveStart.
As walreceiver receives WAL from the master server, and writes and flushes
-it to disk (in pg_xlog), it updates WalRcvData->receivedUpto. Startup process
-polls that to know how far it can proceed with WAL replay.
+it to disk (in pg_xlog), it updates WalRcvData->receivedUpto and signals
+the startup process to know how far WAL replay can advance.
+
+Walreceiver sends information about replication progress to the master server
+whenever either it writes or flushes new WAL, or the specified interval elapses.
+This is used for reporting purpose.
Walsender IPC
-------------
@@ -80,11 +87,9 @@ phase. A walsenders will look like a regular backends until it's done with the
initialization and has marked itself in PMSignal array, and at process
termination, after unmarking the PMSignal slot.
-Each walsender allocates an entry from the WalSndCtl array, and advertises
-there how far it has streamed WAL already. This is used at checkpoints, to
-avoid recycling WAL that hasn't been streamed to a slave yet. However,
-that doesn't stop such WAL from being recycled when the connection is not
-established.
+Each walsender allocates an entry from the WalSndCtl array, and tracks
+information about replication progress. User can monitor them via
+statistics views.
Walsender - walreceiver protocol
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index db4cc640e4..d21568cb21 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -219,7 +219,7 @@ perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
ptr.xrecoff = logseg * XLogSegSize + TAR_SEND_SIZE * i;
/*
- * Some old compilers, e.g. 2.95.3/x86, think that passing
+ * Some old compilers, e.g. gcc 2.95.3/x86, think that passing
* a struct in the same function as a longjump might clobber
* a variable. bjm 2011-02-04
* http://lists.apple.com/archives/xcode-users/2003/Dec//msg00051.html
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index f6c3538650..3ef9cdd87c 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -37,7 +37,7 @@
* Portions Copyright (c) 2010-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL$
+ * src/backend/replication/syncrep.c
*
*-------------------------------------------------------------------------
*/
@@ -62,7 +62,7 @@
#include "utils/ps_status.h"
/* User-settable parameters for sync rep */
-bool sync_rep_mode = false; /* Only set in user backends */
+bool synchronous_replication = false; /* Only set in user backends */
char *SyncRepStandbyNames;
static bool sync_standbys_defined = false; /* Is there at least one name? */
@@ -225,7 +225,7 @@ SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
/*
* Insert MyProc into SyncRepQueue, maintaining sorted invariant.
*
- * Usually we will go at tail of queue, though its possible that we arrive
+ * Usually we will go at tail of queue, though it's possible that we arrive
* here out of order, so start at tail and work back to insertion point.
*/
static void
@@ -420,9 +420,7 @@ SyncRepGetStandbyPriority(void)
/* syntax error in list */
pfree(rawstring);
list_free(elemlist);
- ereport(FATAL,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid list syntax for parameter \"synchronous_standby_names\"")));
+ /* GUC machinery will have already complained - no need to do again */
return 0;
}
@@ -447,9 +445,9 @@ SyncRepGetStandbyPriority(void)
}
/*
- * Walk queue from head setting setting the state of any backends that
- * need to be woken, remove them from the queue and then wake them.
- * Set all = true to wake whole queue, or just up to LSN.
+ * Walk queue from head. Set the state of any backends that need to be woken,
+ * remove them from the queue, and then wake them. Pass all = true to wake
+ * whole queue; otherwise, just wake up to the walsender's LSN.
*
* Must hold SyncRepLock.
*/
@@ -563,7 +561,7 @@ assign_synchronous_standby_names(const char *newval, bool doit, GucSource source
/* syntax error in list */
pfree(rawstring);
list_free(elemlist);
- ereport(FATAL,
+ ereport(GUC_complaint_elevel(source),
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid list syntax for parameter \"synchronous_standby_names\"")));
return NULL;
diff --git a/src/backend/storage/ipc/shmqueue.c b/src/backend/storage/ipc/shmqueue.c
index 5d684b2b85..d7ec3013a6 100644
--- a/src/backend/storage/ipc/shmqueue.c
+++ b/src/backend/storage/ipc/shmqueue.c
@@ -157,7 +157,7 @@ SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
/*--------------------
* SHMQueuePrev -- Get the previous element from a queue
*
- * Same as SHMQueueNext, just starting at tail and moving towards head
+ * Same as SHMQueueNext, just starting at tail and moving towards head.
* All other comments and usage applies.
*/
Pointer
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index f85e0bbd00..b56bb74bdc 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -18,7 +18,6 @@
#include <ctype.h>
#include "catalog/namespace.h"
-#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
@@ -29,8 +28,7 @@
#define MAX_INT32_LEN 11
static char *format_type_internal(Oid type_oid, int32 typemod,
- bool typemod_given, bool allow_invalid,
- Oid collation_oid);
+ bool typemod_given, bool allow_invalid);
static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
static char *
psnprintf(size_t len, const char *fmt,...)
@@ -69,7 +67,6 @@ format_type(PG_FUNCTION_ARGS)
{
Oid type_oid;
int32 typemod;
- Oid collation_oid;
char *result;
/* Since this function is not strict, we must test for null args */
@@ -77,14 +74,13 @@ format_type(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
type_oid = PG_GETARG_OID(0);
- collation_oid = PG_ARGISNULL(2) ? InvalidOid : PG_GETARG_OID(2);
if (PG_ARGISNULL(1))
- result = format_type_internal(type_oid, -1, false, true, collation_oid);
+ result = format_type_internal(type_oid, -1, false, true);
else
{
typemod = PG_GETARG_INT32(1);
- result = format_type_internal(type_oid, typemod, true, true, collation_oid);
+ result = format_type_internal(type_oid, typemod, true, true);
}
PG_RETURN_TEXT_P(cstring_to_text(result));
@@ -99,7 +95,7 @@ format_type(PG_FUNCTION_ARGS)
char *
format_type_be(Oid type_oid)
{
- return format_type_internal(type_oid, -1, false, false, InvalidOid);
+ return format_type_internal(type_oid, -1, false, false);
}
/*
@@ -108,15 +104,14 @@ format_type_be(Oid type_oid)
char *
format_type_with_typemod(Oid type_oid, int32 typemod)
{
- return format_type_internal(type_oid, typemod, true, false, InvalidOid);
+ return format_type_internal(type_oid, typemod, true, false);
}
static char *
format_type_internal(Oid type_oid, int32 typemod,
- bool typemod_given, bool allow_invalid,
- Oid collation_oid)
+ bool typemod_given, bool allow_invalid)
{
bool with_typemod = typemod_given && (typemod >= 0);
HeapTuple tuple;
@@ -322,12 +317,6 @@ format_type_internal(Oid type_oid, int32 typemod,
ReleaseSysCache(tuple);
- if (collation_oid && collation_oid != DEFAULT_COLLATION_OID)
- {
- char *collstr = generate_collation_name(collation_oid);
- buf = psnprintf(strlen(buf) + 10 + strlen(collstr), "%s COLLATE %s", buf, collstr);
- }
-
return buf;
}
@@ -431,7 +420,7 @@ oidvectortypes(PG_FUNCTION_ARGS)
for (num = 0; num < numargs; num++)
{
char *typename = format_type_internal(oidArray->values[num], -1,
- false, true, InvalidOid);
+ false, true);
size_t slen = strlen(typename);
if (left < (slen + 2))
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 025edf0838..7cbd0222cb 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -5082,8 +5082,9 @@ get_rule_expr(Node *node, deparse_context *context,
if (!PRETTY_PAREN(context))
appendStringInfoChar(buf, '(');
- get_rule_expr_paren(arg, context, false, node);
- appendStringInfo(buf, " COLLATE %s", generate_collation_name(collate->collOid));
+ get_rule_expr_paren(arg, context, showimplicit, node);
+ appendStringInfo(buf, " COLLATE %s",
+ generate_collation_name(collate->collOid));
if (!PRETTY_PAREN(context))
appendStringInfoChar(buf, ')');
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0bf1845599..d1b1c17427 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -759,7 +759,7 @@ static struct config_bool ConfigureNamesBool[] =
gettext_noop("Requests synchronous replication."),
NULL
},
- &sync_rep_mode,
+ &synchronous_replication,
false, NULL, NULL
},
{
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index ce24d6101d..acd251415d 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1388,6 +1388,8 @@ setup_depend(void)
" FROM pg_ts_template;\n",
"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
" FROM pg_ts_config;\n",
+ "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
+ " FROM pg_collation;\n",
"INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' "
" FROM pg_authid;\n",
NULL
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 12b22bc256..472760edf1 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -54,10 +54,12 @@ static int numTables;
static int numTypes;
static int numFuncs;
static int numOperators;
+static int numCollations;
static DumpableObject **tblinfoindex;
static DumpableObject **typinfoindex;
static DumpableObject **funinfoindex;
static DumpableObject **oprinfoindex;
+static DumpableObject **collinfoindex;
static void flagInhTables(TableInfo *tbinfo, int numTables,
@@ -105,7 +107,6 @@ getSchemaData(int *numTablesPtr)
int numCasts;
int numOpclasses;
int numOpfamilies;
- int numCollations;
int numConversions;
int numTSParsers;
int numTSTemplates;
@@ -187,6 +188,7 @@ getSchemaData(int *numTablesPtr)
if (g_verbose)
write_msg(NULL, "reading user-defined collations\n");
collinfo = getCollations(&numCollations);
+ collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));
if (g_verbose)
write_msg(NULL, "reading user-defined conversions\n");
@@ -784,6 +786,17 @@ findOprByOid(Oid oid)
return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
}
+/*
+ * findCollationByOid
+ * finds the entry (in collinfo) of the collation with the given oid
+ * returns NULL if not found
+ */
+CollInfo *
+findCollationByOid(Oid oid)
+{
+ return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
+}
+
/*
* findParentsByOid
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index 625e093066..540ca5405a 100644
--- a/src/bin/pg_dump/pg_backup_directory.c
+++ b/src/bin/pg_dump/pg_backup_directory.c
@@ -17,7 +17,7 @@
* sync.
*
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2000, Philip Warner
*
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index dfbdcadd14..0884517331 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -5502,6 +5502,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
int i_attalign;
int i_attislocal;
int i_attoptions;
+ int i_attcollation;
PGresult *res;
int ntups;
bool hasdefaults;
@@ -5541,13 +5542,20 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
if (g_fout->remoteVersion >= 90100)
{
- /* attcollation is new in 9.1 */
+ /*
+ * attcollation is new in 9.1. Since we only want to dump
+ * COLLATE clauses for attributes whose collation is different
+ * from their type's default, we use a CASE here to suppress
+ * uninteresting attcollations cheaply.
+ */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
"a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
- "pg_catalog.format_type(t.oid,a.atttypmod,a.attcollation) AS atttypname, "
- "array_to_string(attoptions, ', ') AS attoptions "
+ "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
+ "array_to_string(a.attoptions, ', ') AS attoptions, "
+ "CASE WHEN a.attcollation <> t.typcollation "
+ "THEN a.attcollation ELSE 0 END AS attcollation "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
@@ -5563,7 +5571,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "array_to_string(attoptions, ', ') AS attoptions "
+ "array_to_string(a.attoptions, ', ') AS attoptions, "
+ "0 AS attcollation "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
@@ -5579,7 +5588,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"a.attnotnull, a.atthasdef, a.attisdropped, "
"a.attlen, a.attalign, a.attislocal, "
"pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
- "'' AS attoptions "
+ "'' AS attoptions, 0 AS attcollation "
"FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::pg_catalog.oid "
@@ -5600,7 +5609,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"false AS attisdropped, a.attlen, "
"a.attalign, false AS attislocal, "
"format_type(t.oid,a.atttypmod) AS atttypname, "
- "'' AS attoptions "
+ "'' AS attoptions, 0 AS attcollation "
"FROM pg_attribute a LEFT JOIN pg_type t "
"ON a.atttypid = t.oid "
"WHERE a.attrelid = '%u'::oid "
@@ -5618,7 +5627,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
"attlen, attalign, "
"false AS attislocal, "
"(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, "
- "'' AS attoptions "
+ "'' AS attoptions, 0 AS attcollation "
"FROM pg_attribute a "
"WHERE attrelid = '%u'::oid "
"AND attnum > 0::int2 "
@@ -5645,6 +5654,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
i_attalign = PQfnumber(res, "attalign");
i_attislocal = PQfnumber(res, "attislocal");
i_attoptions = PQfnumber(res, "attoptions");
+ i_attcollation = PQfnumber(res, "attcollation");
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
@@ -5660,6 +5670,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
tbinfo->attoptions = (char **) malloc(ntups * sizeof(char *));
+ tbinfo->attcollation = (Oid *) malloc(ntups * sizeof(Oid));
tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
tbinfo->inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
tbinfo->inhNotNull = (bool *) malloc(ntups * sizeof(bool));
@@ -5685,6 +5696,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
tbinfo->attoptions[j] = strdup(PQgetvalue(res, j, i_attoptions));
+ tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, i_attcollation));
tbinfo->attrdefs[j] = NULL; /* fix below */
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
hasdefaults = true;
@@ -7359,7 +7371,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
"typanalyze::pg_catalog.oid AS typanalyzeoid, "
"typcategory, typispreferred, "
"typdelim, typbyval, typalign, typstorage, "
- "(typcollation = (SELECT oid FROM pg_catalog.pg_collation WHERE collname = 'default')) AS typcollatable, "
+ "(typcollation <> 0) AS typcollatable, "
"pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
"FROM pg_catalog.pg_type "
"WHERE oid = '%u'::pg_catalog.oid",
@@ -7736,6 +7748,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
char *typnotnull;
char *typdefn;
char *typdefault;
+ Oid typcollation;
bool typdefault_is_literal = false;
/* Set proper schema search path so type references list correctly */
@@ -7745,11 +7758,14 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
if (g_fout->remoteVersion >= 90100)
{
/* typcollation is new in 9.1 */
- appendPQExpBuffer(query, "SELECT typnotnull, "
- "pg_catalog.format_type(typbasetype, typtypmod, typcollation) AS typdefn, "
- "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
- "typdefault "
+ appendPQExpBuffer(query, "SELECT t.typnotnull, "
+ "pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, "
+ "pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
+ "t.typdefault, "
+ "CASE WHEN t.typcollation <> u.typcollation "
+ "THEN t.typcollation ELSE 0 END AS typcollation "
"FROM pg_catalog.pg_type t "
+ "LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) "
"WHERE t.oid = '%u'::pg_catalog.oid",
tyinfo->dobj.catId.oid);
}
@@ -7759,7 +7775,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
appendPQExpBuffer(query, "SELECT typnotnull, "
"pg_catalog.format_type(typbasetype, typtypmod) AS typdefn, "
"pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
- "typdefault "
+ "typdefault, 0 AS typcollation "
"FROM pg_catalog.pg_type "
"WHERE oid = '%u'::pg_catalog.oid",
tyinfo->dobj.catId.oid);
@@ -7790,6 +7806,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
}
else
typdefault = NULL;
+ typcollation = atooid(PQgetvalue(res, 0, PQfnumber(res, "typcollation")));
if (binary_upgrade)
binary_upgrade_set_type_oids_by_type_oid(q, tyinfo->dobj.catId.oid);
@@ -7799,6 +7816,22 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
fmtId(tyinfo->dobj.name),
typdefn);
+ /* Print collation only if different from base type's collation */
+ if (OidIsValid(typcollation))
+ {
+ CollInfo *coll;
+
+ coll = findCollationByOid(typcollation);
+ if (coll)
+ {
+ /* always schema-qualify, don't try to be smart */
+ appendPQExpBuffer(q, " COLLATE %s.",
+ fmtId(coll->dobj.namespace->dobj.name));
+ appendPQExpBuffer(q, "%s",
+ fmtId(coll->dobj.name));
+ }
+ }
+
if (typnotnull[0] == 't')
appendPQExpBuffer(q, " NOT NULL");
@@ -11966,6 +11999,22 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
tbinfo->atttypmod[j]));
}
+ /* Add collation if not default for the type */
+ if (OidIsValid(tbinfo->attcollation[j]))
+ {
+ CollInfo *coll;
+
+ coll = findCollationByOid(tbinfo->attcollation[j]);
+ if (coll)
+ {
+ /* always schema-qualify, don't try to be smart */
+ appendPQExpBuffer(q, " COLLATE %s.",
+ fmtId(coll->dobj.namespace->dobj.name));
+ appendPQExpBuffer(q, "%s",
+ fmtId(coll->dobj.name));
+ }
+ }
+
if (has_default)
appendPQExpBuffer(q, " DEFAULT %s",
tbinfo->attrdefs[j]->adef_expr);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 94b7a6bf92..113ecb1846 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -272,6 +272,7 @@ typedef struct _tableInfo
char *attalign; /* attribute align, used by binary_upgrade */
bool *attislocal; /* true if attr has local definition */
char **attoptions; /* per-attribute options */
+ Oid *attcollation; /* per-attribute collation selection */
/*
* Note: we need to store per-attribute notnull, default, and constraint
@@ -510,6 +511,7 @@ extern TableInfo *findTableByOid(Oid oid);
extern TypeInfo *findTypeByOid(Oid oid);
extern FuncInfo *findFuncByOid(Oid oid);
extern OprInfo *findOprByOid(Oid oid);
+extern CollInfo *findCollationByOid(Oid oid);
extern void simple_oid_list_append(SimpleOidList *list, Oid val);
extern void simple_string_list_append(SimpleStringList *list, const char *val);
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e21ee0a835..22a0b89b44 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201103061
+#define CATALOG_VERSION_NO 201103101
#endif
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 42a70e8f25..6decfb13b3 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -5,10 +5,11 @@
* along with the relation's initial contents.
*
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL$
+ * IDENTIFICATION
+ * src/include/catalog/pg_collation.h
*
* NOTES
* the genbki.pl script reads this file and generates .bki
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index ada807ad71..3ab5344c9d 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -3,7 +3,7 @@
* pg_foreign_table.h
* definition of the system "foreign table" relation (pg_foreign_table)
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/catalog/pg_foreign_table.h
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 0533e5a686..cff64ba6b0 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -1100,8 +1100,8 @@ DATA(insert OID = 1078 ( bpcharcmp PGNSP PGUID 12 1 0 0 f f f t f i 2 0 23
DESCR("less-equal-greater");
DATA(insert OID = 1080 ( hashbpchar PGNSP PGUID 12 1 0 0 f f f t f i 1 0 23 "1042" _null_ _null_ _null_ _null_ hashbpchar _null_ _null_ _null_ ));
DESCR("hash");
-DATA(insert OID = 1081 ( format_type PGNSP PGUID 12 1 0 0 f f f f f s 3 0 25 "26 23 26" _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ ));
-DESCR("format a type OID, atttypmod, and collation OID to canonical SQL");
+DATA(insert OID = 1081 ( format_type PGNSP PGUID 12 1 0 0 f f f f f s 2 0 25 "26 23" _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ ));
+DESCR("format a type oid and atttypmod to canonical SQL");
DATA(insert OID = 1084 ( date_in PGNSP PGUID 12 1 0 0 f f f t f s 1 0 1082 "2275" _null_ _null_ _null_ _null_ date_in _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 1085 ( date_out PGNSP PGUID 12 1 0 0 f f f t f s 1 0 2275 "1082" _null_ _null_ _null_ _null_ date_out _null_ _null_ _null_ ));
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 8b7db798b9..6691b0dc77 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -68,7 +68,7 @@ extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location);
extern TypeName *makeTypeName(char *typnam);
extern TypeName *makeTypeNameFromNameList(List *names);
-extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod, Oid collOid);
+extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod);
extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype,
List *args, Oid collid, CoercionForm fformat);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 287e9f523f..9d4515cb27 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -168,8 +168,7 @@ typedef struct Query
* specify the type by OID than by name. If "names" is NIL then the
* actual type OID is given by typeOid, otherwise typeOid is unused.
* Similarly, if "typmods" is NIL then the actual typmod is expected to
- * be prespecified in typemod, otherwise typemod is unused. Similarly
- * for collnames/collOid.
+ * be prespecified in typemod, otherwise typemod is unused.
*
* If pct_type is TRUE, then names is actually a field name and we look up
* the type of that field. Otherwise (the normal case), names is a type
@@ -185,8 +184,6 @@ typedef struct TypeName
List *typmods; /* type modifier expression(s) */
int32 typemod; /* prespecified type modifier */
List *arrayBounds; /* array bounds */
- List *collnames; /* collation name */
- Oid collOid; /* collation by OID */
int location; /* token location, or -1 if unknown */
} TypeName;
@@ -468,6 +465,10 @@ typedef struct RangeFunction
* how this ColumnDef node was created (by parsing, or by inheritance
* from an existing relation). We should never have both in the same node!
*
+ * Similarly, we may have a COLLATE specification in either raw form
+ * (represented as a CollateClause with arg==NULL) or cooked form
+ * (the collation's OID).
+ *
* The constraints list may contain a CONSTR_DEFAULT item in a raw
* parsetree produced by gram.y, but transformCreateStmt will remove
* the item and set raw_default instead. CONSTR_DEFAULT items
@@ -485,6 +486,8 @@ typedef struct ColumnDef
char storage; /* attstorage setting, or 0 for default */
Node *raw_default; /* default value (untransformed parse tree) */
Node *cooked_default; /* default value (transformed expr tree) */
+ CollateClause *collClause; /* untransformed COLLATE spec, if any */
+ Oid collOid; /* collation OID (InvalidOid if not set) */
List *constraints; /* other constraints on column */
} ColumnDef;
@@ -1202,9 +1205,8 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
AlterTableType subtype; /* Type of table alteration to apply */
char *name; /* column, constraint, or trigger to act on,
* or new owner or tablespace */
- Node *def; /* definition of new column, column type,
- * index, constraint, or parent table */
- Node *transform; /* transformation expr for ALTER TYPE */
+ Node *def; /* definition of new column, index,
+ * constraint, or parent table */
DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
bool missing_ok; /* skip error if missing? */
bool validated;
@@ -1819,6 +1821,7 @@ typedef struct CreateDomainStmt
NodeTag type;
List *domainname; /* qualified name (list of Value strings) */
TypeName *typeName; /* the base type */
+ CollateClause *collClause; /* untransformed COLLATE spec, if any */
List *constraints; /* constraints (list of Constraint nodes) */
} CreateDomainStmt;
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
index 8621ab678d..92c9ecba4a 100644
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -20,21 +20,19 @@
typedef HeapTuple Type;
extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName,
- int32 *typmod_p, Oid *collid_p);
+ int32 *typmod_p);
extern Type typenameType(ParseState *pstate, const TypeName *typeName,
- int32 *typmod_p, Oid *collid_p);
-
-extern Oid LookupCollation(ParseState *pstate, List *collnames, int location);
-
+ int32 *typmod_p);
extern Oid typenameTypeId(ParseState *pstate, const TypeName *typeName);
extern void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName,
- Oid *typeid_p, int32 *typmod_p);
-extern void typenameTypeIdModColl(ParseState *pstate, const TypeName *typeName,
- Oid *typeid_p, int32 *typmod_p, Oid *collid_p);
+ Oid *typeid_p, int32 *typmod_p);
extern char *TypeNameToString(const TypeName *typeName);
extern char *TypeNameListToString(List *typenames);
+extern Oid LookupCollation(ParseState *pstate, List *collnames, int location);
+extern Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid);
+
extern Type typeidType(Oid id);
extern Oid typeTypeId(Type tp);
diff --git a/src/include/replication/basebackup.h b/src/include/replication/basebackup.h
index af6a36621f..831c33fb4a 100644
--- a/src/include/replication/basebackup.h
+++ b/src/include/replication/basebackup.h
@@ -3,7 +3,7 @@
* basebackup.h
* Exports from replication/basebackup.c.
*
- * Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2010-2011, PostgreSQL Global Development Group
*
* src/include/replication/walsender.h
*
diff --git a/src/include/replication/syncrep.h b/src/include/replication/syncrep.h
index f4eb3c9f04..9171eb6176 100644
--- a/src/include/replication/syncrep.h
+++ b/src/include/replication/syncrep.h
@@ -3,9 +3,10 @@
* syncrep.h
* Exports from replication/syncrep.c.
*
- * Portions Copyright (c) 2010-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2010-2011, PostgreSQL Global Development Group
*
- * $PostgreSQL$
+ * IDENTIFICATION
+ * src/include/replication/syncrep.h
*
*-------------------------------------------------------------------------
*/
@@ -18,7 +19,8 @@
#include "storage/spin.h"
#include "utils/guc.h"
-#define SyncRepRequested() (sync_rep_mode)
+#define SyncRepRequested() \
+ (synchronous_replication && max_wal_senders > 0)
/* syncRepState */
#define SYNC_REP_NOT_WAITING 0
@@ -27,8 +29,7 @@
#define SYNC_REP_MUST_DISCONNECT 3
/* user-settable parameters for synchronous replication */
-extern bool sync_rep_mode;
-extern int sync_rep_timeout;
+extern bool synchronous_replication;
extern char *SyncRepStandbyNames;
/* called by user backend */
@@ -43,6 +44,6 @@ extern void SyncRepReleaseWaiters(void);
/* called by various procs */
extern int SyncRepWakeQueue(bool all);
-const char *assign_synchronous_standby_names(const char *newval, bool doit, GucSource source);
+extern const char *assign_synchronous_standby_names(const char *newval, bool doit, GucSource source);
#endif /* _SYNCREP_H */
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index 8a8c9398d1..2e5b2096ea 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -74,8 +74,7 @@ typedef struct
/*
* Current location of the head of the queue. All waiters should have
- * a waitLSN that follows this value, or they are currently being woken
- * to remove themselves from the queue. Protected by SyncRepLock.
+ * a waitLSN that follows this value. Protected by SyncRepLock.
*/
XLogRecPtr lsn;
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 1d6642c6c7..f2e063c6cb 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -122,7 +122,7 @@ struct PGPROC
* Info to allow us to wait for synchronous replication, if needed.
* waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.
* syncRepState must not be touched except by owning process or WALSender.
- * syncRep_links used only while holding SyncRepLock.
+ * syncRepLinks used only while holding SyncRepLock.
*/
Latch waitLatch; /* allow us to wait for sync rep */
XLogRecPtr waitLSN; /* waiting for this LSN or higher */
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index c0f7b64d80..e96323efcc 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -317,5 +317,6 @@ extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
+extern bool has_createrole_privilege(Oid roleid);
#endif /* ACL_H */
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index d2b3862ec7..41188a2369 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1565,7 +1565,7 @@ plpgsql_parse_wordtype(char *ident)
* Word wasn't found in the namespace stack. Try to find a data type with
* that name, but ignore shell types and complex types.
*/
- typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL, NULL);
+ typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL);
if (typeTup)
{
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
diff --git a/src/test/isolation/Makefile b/src/test/isolation/Makefile
index 82ce248a07..0f709a1e3c 100644
--- a/src/test/isolation/Makefile
+++ b/src/test/isolation/Makefile
@@ -29,7 +29,7 @@ all: isolationtester pg_isolation_regress
isolationtester: $(OBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
-distprep: specparse.c
+distprep: specparse.c specscanner.c
# There is no correct way to write a rule that generates two files.
# Rules with two targets don't have that meaning, they are merely
@@ -58,7 +58,9 @@ ifdef FLEX
else
@$(missing) flex $< $@
endif
-# specparse.c is in the distribution tarball, so is not cleaned here
+
+# specparse.c and specscanner.c are in the distribution tarball,
+# so do not clean them here
clean distclean:
rm -f isolationtester$(X) pg_isolation_regress$(X) $(OBJS) isolation_main.o
rm -f pg_regress.o
diff --git a/src/test/isolation/isolationtester.h b/src/test/isolation/isolationtester.h
index b092ed16a0..1f86db8727 100644
--- a/src/test/isolation/isolationtester.h
+++ b/src/test/isolation/isolationtester.h
@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
- * bootstrap.h
- * include file for the bootstrapping code
+ * isolationtester.h
+ * include file for isolation tests
*
- *
- * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.44 2006/10/04 00:30:07 momjian Exp $
+ * IDENTIFICATION
+ * src/test/isolation/isolationtester.h
*
*-------------------------------------------------------------------------
*/
diff --git a/src/test/isolation/specscanner.l b/src/test/isolation/specscanner.l
index 6752aca82d..c3193917c0 100644
--- a/src/test/isolation/specscanner.l
+++ b/src/test/isolation/specscanner.l
@@ -32,10 +32,9 @@ static void addlitchar(const char c);
%x qstr
non_newline [^\n\r]
-space [ \t\n\r\f]
+space [ \t\r\f]
comment ("#"{non_newline}*)
-whitespace ({space}+|{comment})
%%
@@ -46,10 +45,10 @@ step { return(STEP); }
teardown { return(TEARDOWN); }
[\n] { yyline++; }
-{whitespace} {
- /* ignore */
- }
+{comment} { /* ignore */ }
+{space} { /* ignore */ }
+ /* Quoted strings: "foo" */
\" {
litbufpos = 0;
BEGIN(qstr);
@@ -61,27 +60,36 @@ teardown { return(TEARDOWN); }
return(string);
}
<qstr>. { addlitchar(yytext[0]); }
+<qstr>\n { yyerror("unexpected newline in quoted string"); }
+<qstr><<EOF>> { yyerror("unterminated quoted string"); }
+ /* SQL blocks: { UPDATE ... } */
"{" {
litbufpos = 0;
BEGIN(sql);
}
-
<sql>"}" {
litbuf[litbufpos] = '\0';
yylval.str = strdup(litbuf);
BEGIN(INITIAL);
return(sqlblock);
}
-<sql>[^}] { addlitchar(yytext[0]);}
-
+<sql>. {
+ addlitchar(yytext[0]);
+ }
+<sql>\n {
+ yyline++;
+ addlitchar(yytext[0]);
+ }
+<sql><<EOF>> {
+ yyerror("unterminated sql block");
+ }
. {
fprintf(stderr, "syntax error at line %d: unexpected character \"%s\"\n", yyline, yytext);
exit(1);
}
-
%%
static void
diff --git a/src/test/regress/expected/collate.linux.utf8.out b/src/test/regress/expected/collate.linux.utf8.out
index caa65b2f37..5ad5de2f00 100644
--- a/src/test/regress/expected/collate.linux.utf8.out
+++ b/src/test/regress/expected/collate.linux.utf8.out
@@ -20,21 +20,21 @@ CREATE TABLE collate_test_fail (
);
ERROR: collation "ja_JP.eucjp" for current database encoding "UTF8" does not exist
LINE 3: b text COLLATE "ja_JP.eucjp"
- ^
+ ^
CREATE TABLE collate_test_fail (
a int,
b text COLLATE "foo"
);
ERROR: collation "foo" for current database encoding "UTF8" does not exist
LINE 3: b text COLLATE "foo"
- ^
+ ^
CREATE TABLE collate_test_fail (
a int COLLATE "en_US.utf8",
b text
);
ERROR: collations are not supported by type integer
LINE 2: a int COLLATE "en_US.utf8",
- ^
+ ^
CREATE TABLE collate_test_like (
LIKE collate_test1
);
@@ -632,9 +632,9 @@ ERROR: no collation was derived for column "b" with collatable type text
HINT: Use the COLLATE clause to set the collation explicitly.
-- casting
SELECT CAST('42' AS text COLLATE "C");
-ERROR: COLLATE clause not allowed in cast target
+ERROR: syntax error at or near "COLLATE"
LINE 1: SELECT CAST('42' AS text COLLATE "C");
- ^
+ ^
SELECT a, CAST(b AS varchar) FROM collate_test1 ORDER BY 2;
a | b
---+-----
@@ -727,6 +727,8 @@ CREATE INDEX collate_test1_idx4 ON collate_test1 (a COLLATE "C"); -- fail
ERROR: collations are not supported by type integer
CREATE INDEX collate_test1_idx5 ON collate_test1 ((a COLLATE "C")); -- fail
ERROR: collations are not supported by type integer
+LINE 1: ...ATE INDEX collate_test1_idx5 ON collate_test1 ((a COLLATE "C...
+ ^
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%';
relname | pg_get_indexdef
--------------------+----------------------------------------------------------------------------------------------
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 00730f25cb..a7473349fd 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -693,7 +693,7 @@ ERROR: "ft1" is not a table or view
ALTER FOREIGN TABLE ft1 ALTER COLUMN c6 SET NOT NULL;
ALTER FOREIGN TABLE ft1 ALTER COLUMN c7 DROP NOT NULL;
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10) using '0'; -- ERROR
-ERROR: ALTER TYPE USING is not supported on foreign tables
+ERROR: ALTER TYPE USING is only supported on plain tables
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10);
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET DATA TYPE text;
-- can't change the column type if it's used elsewhere
diff --git a/src/tools/git-external-diff b/src/tools/git-external-diff
new file mode 100644
index 0000000000..fdc7080f3a
--- /dev/null
+++ b/src/tools/git-external-diff
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# Parameters:
+# $1 $2 $3 $4 $5 $6 $7
+# path old-file old-hash old-mode new-file new-hash new-mode
+# 'path' is the git-tree-relative path of the file being diff'ed
+
+old_hash="$3"
+new_hash=$(git hash-object "$5")
+
+# no change?
+[ "$old_hash" = "$new_hash" ] && exit 0
+
+[ "$DIFF_OPTS" = "" ] && DIFF_OPTS='-pcd'
+
+echo "diff --git a/$1 b/$1"
+echo "new file mode $7"
+echo "index ${old_hash:0:7}..${new_hash:0:7}"
+
+diff --label a/"$1" --label b/"$1" $DIFF_OPTS "$2" "$5"
+
+exit 0