>From 5c4a2c308f084632be8bb5d6293fca92c10de3f8 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Wed, 5 Mar 2014 00:15:39 +0100 Subject: [PATCH 4/4] Documentation for logical decoding. Craig Ringer, Andres Freund, Christian Kruse --- doc/src/sgml/catalogs.sgml | 27 +- doc/src/sgml/changesetextraction.sgml | 586 ++++++++++++++++++++++++++++++++++ doc/src/sgml/filelist.sgml | 2 + doc/src/sgml/func.sgml | 102 +++++- doc/src/sgml/postgres.sgml | 1 + doc/src/sgml/protocol.sgml | 95 +++++- doc/src/sgml/ref/alter_table.sgml | 2 +- doc/src/sgml/ref/create_table.sgml | 15 +- 8 files changed, 808 insertions(+), 22 deletions(-) create mode 100644 doc/src/sgml/changesetextraction.sgml diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 908f947..727a201 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -5177,7 +5177,7 @@ For more on replication slots, - see . + see and . @@ -5210,6 +5210,13 @@ + plugin + text + + The basename of the shared object containing the output plugin this logical slot is using, or null for physical slots. + + + datoid oid pg_database.oid @@ -5243,6 +5250,24 @@ + xmin + xid + + The oldest transaction that this slot needs the database to + retain. VACUUM cannot remove catalog tuples deleted + by any later transaction. + + + + + catalog_xmin + xid + + The xmin, or oldest transaction ID, that this + slot forces to be retained in the system catalogs. + + + restart_lsn pg_lsn diff --git a/doc/src/sgml/changesetextraction.sgml b/doc/src/sgml/changesetextraction.sgml new file mode 100644 index 0000000..60b915c --- /dev/null +++ b/doc/src/sgml/changesetextraction.sgml @@ -0,0 +1,586 @@ + + + Changeset Extraction + + Changeset Extraction + + + PostgreSQL provides infrastructure to stream the modifications performed + via SQL to external consumers which can be used to implement replication + solutions, perform auditing and similar tasks. + + + + Changeset Extraction Slot + A changeset extraction slot ("logical replication slot") is a persistent + server-side record of the replay progress of a stream of changes. A stream of + changes is read from the slot to a receiving client program. + + + The format in which those changes are streamed is determined by the output + plugin used. While an example plugin is provided, additional plugins can be + written to extend the choice of available formats without modifying any + core code. + Every output plugin has access to each individual new row produced + by INSERT, and the new row version created + by UPDATE. Which data is available for rows affected + by DELETE and for the old row version in + an UPDATE depends on the relation's + configured REPLICA + IDENTITY. + + + Changes can be consumed either using one streaming replication protocol + (see and + ), or by calling functions + via SQL (see ). It is also possible + to write additional methods of consuming the output of a replication slot + without modifying core code + (see ). + + + + Changeset Extraction Example + + The following example shows usage of the SQL interface. + + + Before you can use changeset extraction you must edit + postgresql.conf and ensure the following parameters are + set to at least: + +wal_level = logical +max_replication_slots = 1 +max_wal_senders = 1 + + and restart PostgreSQL. Then connect to the target database (in the example + below, postgres) as a superuser. + + +postgres=# -- max_replication_slots must be nonzero and wal_level must be logical +postgres=# SHOW max_replication_slots; + max_replication_slots +----------------------- + 1 +(1 row) + +postgres=# SHOW wal_level; + wal_level +----------- + logical +(1 row) + +postgres=# SELECT * FROM pg_replication_slots; + slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn +-----------+--------+-----------+--------+----------+--------+------+--------------+------------- +(0 rows) + +postgres=# -- Create a slot named 'regression_slot' using the output plugin 'test_decoding' +postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding'); + slotname | xlog_position +-----------------+--------------- + regression_slot | 0/16B1970 +(1 row) + +postgres=# SELECT * FROM pg_replication_slots; + slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn +-----------------+---------------+-----------+--------+----------+--------+--------+--------------+------------- + regression_slot | test_decoding | logical | 12052 | postgres | f | | 684 | 0/16A4408 +(1 row) + +postgres=# -- There are no changes to see yet +postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL); + location | xid | data +----------+-----+------ +(0 rows) + +postgres=# CREATE TABLE data(id serial primary key, data text); +CREATE TABLE + +postgres=# -- DDL isn't replicated, so all you'll see is the transaction +postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL); + location | xid | data +-----------+-----+------------ + 0/16D5D48 | 688 | BEGIN 688 + 0/16E0380 | 688 | COMMIT 688 +(2 rows) + +postgres=# -- Once changes are read, they're consumed and not emitted +postgres=# -- in a subsequent call: +postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL); + location | xid | data +----------+-----+------ +(0 rows) + +postgres=# BEGIN; +postgres=# INSERT INTO data(data) VALUES('1'); +postgres=# INSERT INTO data(data) VALUES('2'); +postgres=# COMMIT; + +postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL); + location | xid | data +-----------+-----+----------------------------------------------- + 0/16E0478 | 689 | BEGIN 689 + 0/16E0478 | 689 | table public.data: INSERT: id[int4]:1 data[text]:'1' + 0/16E0580 | 689 | table public.data: INSERT: id[int4]:2 data[text]:'2' + 0/16E0650 | 689 | COMMIT 689 +(4 rows) + +postgres=# INSERT INTO data(data) VALUES('3'); + +postgres=# -- You can also peek ahead in the change stream without consuming changes +postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL); + location | xid | data +-----------+-----+----------------------------------------------- + 0/16E09C0 | 690 | BEGIN 690 + 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3' + 0/16E0B90 | 690 | COMMIT 690 +(3 rows) + +postgres=# -- You can also peek ahead in the change stream without consuming changes +postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL); + location | xid | data +-----------+-----+----------------------------------------------- + 0/16E09C0 | 690 | BEGIN 690 + 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3' + 0/16E0B90 | 690 | COMMIT 690 +(3 rows) + +postgres=# -- options can be passed to output plugin, to influence the formatting +postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL, 'include-timestamp', 'on'); + location | xid | data +-----------+-----+----------------------------------------------- + 0/16E09C0 | 690 | BEGIN 690 + 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3' + 0/16E0B90 | 690 | COMMIT 690 (at 2014-02-27 16:41:51.863092+01) +(3 rows) + +postgres=# -- Remember to destroy a slot you no longer need to stop it consuming +postgres=# -- server resources: +postgres=# SELECT pg_drop_replication_slot('regression_slot'); + pg_drop_replication_slot +----------------------- + +(1 row) + + + The following example shows usage of the walsender interface using + the pg_recvlogical + shell command. It requires the replication configurations to be allowed + (see ) + and max_wal_senders to be set sufficiently high for + another connection. + + +# pg_recvlogical -d testdb --slot test --create +# pg_recvlogical -d testdb --slot test --start -f - +CTRL-Z +# psql -c "INSERT INTO data(data) VALUES('4');" +# fg +BEGIN 693 +table public.data: INSERT: id[int4]:4 data[text]:'4' +COMMIT 693 +CTRL-C +# pg_recvlogical -d testdb --slot test --drop + + + + Changeset Extraction Concepts + + + Changeset Extraction + + + Changeset Generation + + Changeset Extraction + + Changeset Extraction is the the process of extracting all persistent + changes to a database's tables into a coherent, easy to understand format + which can be interpreted without detailed knowledge of the database's + internal state. + + + In PostgreSQL changeset extraction is + implemented by decoding the WAL's contents, + which describe changes on a storage level, into an application-specific + form such as a stream of tuples or SQL statements. + + + + + + Logical Replication Slot + + + Replication Slot + + Replication Slots + + In the context of changeset extraction a replication slot represents a + stream of changes which can be replayed to a client in the order they + were made on the origin server. Each slot streams a sequence of changes + from a single database, sending each change exactly once (unless peeking + forward in the stream). + + + PostgreSQL also has streaming replication slots + (see ), but they are used somewhat + differently there. + + + + Replication slots have an identifier which is unique across all databases + in a PostgreSQL cluster. Slots persist + independently of the connection using them and are crash-safe. They can + be allocated in primary servers and hot-standby servers (streaming + replicas or archive-replaying hot standbys), so it's possible to + replicate changes over physical replication then read a logical change + stream from a physical replica server. + + + Multiple independent slots may exist for a single database. Each slot has + its own state, allowing different consumers to receive changes from + different points in the database change stream. For most applications a + separate slot is required for each changeset consumer. + + + A changeset extraction slot knows nothing about the state of the + receiver(s). It's even possible to have multiple different receivers use + the same slot at different times; they'll just get the changes following + on from when the last receiver stopped consuming them. Only one receiver + may consume changes from a slot at any given time. + + + Unused/abandoned slots + + Changeset extraction slots persist across crashes and know nothing about + the state of their consumer(s). They will prevent removal of required + resources even when there is no connection using them. This consumes + storage because neither required WAL nor required rows from the system + catalogs can be removed by VACUUM as long as they are required by a + replication slot, so if a slot is no longer required it should be + dropped. + + + Slots may be created manually, or using a client like a replication + tool. Keep this in mind when you retire a client that uses a changeset + extraction slot, like a logical replica - you may need to give it a + specific command to remove its changeset extraction slot, or drop the + slot yourself, even if you did not initially create the slot by hand. + + + + + Exported Snapshots + + When a new replication slot is created over the walsender interface a + snapshot is exported + (see ) which will show + exactly the state of the database after which all changes will be + included in the changestream. This can be used to create a new replica by + using SET TRANSACTION + SNAPSHOT to read the state of the database at the moment + the slot was created. This transaction can then be used to dump the + database's state at that point in time which afterwards can be updated + using the slot's contents without loosing any changes. + + + + + Streaming Replication Protocol Interface + + The CREATE_REPLICATION_SLOT SLOT slotname LOGICAL + options, DROP_REPLICATION_SLOT SLOT slotname + and START_REPLICATION SLOT slotname LOGICAL options + commands can be used to create, drop and stream changes from a replication + slot respectively. These commands are only available over a replication + connection; the won't work from the SQL + level. See . + + + The pg_recvlogical command + (see ) can be used to control changeset + extraction over a walsender connection. + + + + Changeset Extraction <acronym>SQL</acronym> Interface + + See for detailed + documentation on the SQL-level API for interacting with changeset + extraction. + + + Synchronous replication (see ) is + only supported on replication slots used over the walsender interface. The + function interface and additional, non-core, interfaces, do not support + synchronous replication. + + + + System catalogs related to changeset extraction + + The view and the + pg_stat_replication view + in provide information about + the current state of replication slots and walsender connections + respectively. These views apply to both physical and logical replication. + + + + Changeset Extraction Output Plugins + + An example output plugin can be found in the + + contrib/test_decoding + + subdirectory of the PostgreSQL source tree. + + + Initialization Function + + _PG_output_plugin_init + + + An output plugin is loaded by dynamically loading a shared library with + the output plugin's name as the library basename. The normal library + search path is used to locate the library. To provide the required output + plugin callbacks and to indicate that the library is actually an output + plugin it needs to provide a function named + _PG_output_plugin_init. This function is passed a + struct that needs to be filled with the callback function pointers for + individual actions. + +typedef struct OutputPluginCallbacks +{ + LogicalDecodeStartupCB startup_cb; + LogicalDecodeBeginCB begin_cb; + LogicalDecodeChangeCB change_cb; + LogicalDecodeCommitCB commit_cb; + LogicalDecodeShutdownCB shutdown_cb; +} OutputPluginCallbacks; +typedef void (*LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb); + + The begin_cb, change_cb + and commit_cb callbacks are required, + while startup_cb + and shutdown_cb are optional. + + + + + Capabilities + + To decode, format and output changes, output plugins can use most of the + backend's normal infrastructure, including calling output functions. Read + only access to relations is permitted as long as only relations are + accessed that either have been created by initdb in + the pg_catalog schema, or have are marked as user + provided catalog tables using + +ALTER TABLE user_catalog_table SET (user_catalog_table = true); +CREATE TABLE another_catalog_table(data text) WITH (user_catalog_table = true); + + Any actions leading to XID assignment are prohibited. That, among others, + includes writing to tables, performing DDL changes and + calling txid_current(). + + + + + Output Plugin Callbacks + + An output plugin gets notified about changes that are happening via + various callbacks it needs to provide. + + + Concurrent transactions are decoded in commit order and only changes + belonging to a specific transaction are decoded inbetween + the begin and commit + callbacks. Transaction that were rolled back explicitly or implicitly + will never be + decoded. Successfull SAVEPOINTs are + folded into the transaction containing them in the order they were + exectuded within that transaction. + + + + Only transactions that have already safely been flushed to disk will be + decoded. That can lead to a COMMIT not immediately being decoded in a + directly following pg_logical_slot_get_changes() + when synchronous_commit is set + to off. + + + + Startup Callback + + The optional startup_cb callback is called whenever + an replication slot is created or asked to stream changes, independent + of the number of changes that are ready to be output. + +typedef void (*LogicalDecodeStartupCB) ( + struct LogicalDecodingContext *ctx, + OutputPluginOptions *options, + bool is_init +); + + The is_init paramter will be true when the + replication slot is being created and false + otherwise. options points to a struct of options + that output plugins can set: + +typedef struct OutputPluginOptions +{ + OutputPluginOutputType output_type; +} OutputPluginOptions; + + output_type has to either be set to + OUTPUT_PLUGIN_TEXTUAL_OUTPUT + or OUTPUT_PLUGIN_BINARY_OUTPUT. + + + The startup callback should validate the options present in + ctx->output_plugin_options. If the output plugin + needs to have a state, it can + use ctx->output_plugin_private to store it. + + + + Shutdown Callback + + The optional shutdown_cb callback is called + whenever a formerly active replication slot is not used anymore and can + be used to deallocate resources private to the output plugin. The slot + isn't necessarily being dropped, streaming is just being stopped. + +typedef void (*LogicalDecodeShutdownCB) ( + struct LogicalDecodingContext *ctx +); + + + + + Transaction Begin Callback + + The required begin_cb callback is called whenever a + transaction start has been decoded, but only if we know that the + transaction has committed. Aborted transactions and their contents are + never decoded. + +typedef void (*LogicalDecodeBeginCB) ( + struct LogicalDecodingContext *, + ReorderBufferTXN *txn +); + + The txn parameter contains meta information about + the transaction, like the timestamp at which it committed and its XID. + + + + Transaction End Callback + + The required commit_cb callback is called whenever + a transaction commit has been + decoded. The change_cb callbacks for all modified + rows will have been called before this, if there have been any modified + rows. + +typedef void (*LogicalDecodeCommitCB) ( + struct LogicalDecodingContext *, + ReorderBufferTXN *txn +); + + + + + Callback called for each individual change in a + transaction + + The required change_cb callback is called for every + individual row modification inside a transaction, may it be + an INSERT, UPDATE + or DELETE. Even if the original command modified + several rows at once the callback will be called indvidually for each + row. + +typedef void (*LogicalDecodeChangeCB) ( + struct LogicalDecodingContext *ctx, + ReorderBufferTXN *txn, + Relation relation, + ReorderBufferChange *change +); + + The ctx and txn parameters + have the same contents as for the begin_cb + and commit_cb callbacks, but additionally the + relation descriptor relation for the relation the + row belongs to and a struct + change describing the row modification are passed + in. + + + + Only changes in user defined tables that are not unlogged + (see ) and not temporary + (see ) can be extracted using + changeset extraction. + + + + + + Functions for producing output from an output plugin + + To actually produce output, output plugins can write data to + the StringInfo output buffer + in ctx->out when inside + the begin_cb, commit_cb + or change_cb callbacks. Before writing to the output + buffer OutputPluginPrepareWrite(ctx, last_write) has + to be called, and after finishing writing to the + buffer OutputPluginWrite(ctx, last_write) has to be + called to perform the write. The last_write + indicates whether a particular write was the callback's last write. + + + The following example shows how to output data to the consumer of an + output plugin: + +OutputPluginPrepareWrite(ctx, true); +appendStringInfo(ctx->out, "BEGIN %u", txn->xid); +OutputPluginWrite(ctx, true); + + + + + + Changeset Extraction Output Writers + + It is possible to add more output methods in addition to the SQL + and replication protocol variants for consuming changeset extraction + data. For details look at the implementation of the SQL interface + functions + in src/backend/replication/logical/logicalfuncs.c. + Essentially three functions need to be provided, one to read WAL, one to + prepare writing output and one to write the output + (see ). + + + + Synchronous replication support for Changeset Extraction + + The Changeset Extraction support in PostgreSQL + may be used to to + build synchronous + replication solutions with the same user interface as synchronous + replication for streaming + replication if the walsender interface + (see ) is used to stream out + data. Clients have to send Standby status update (F) + (see ), just like streaming + replication clients do. + + + diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 0e863ee..0208ca2 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -91,6 +91,7 @@ + @@ -146,6 +147,7 @@ + diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index a1f627c..8a18602 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -16363,8 +16363,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); PostgreSQL exposes a number of functions for controlling and interacting - with replication features. See - and . + with replication features. See , + + and . @@ -16423,9 +16424,106 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup()); command DROP_REPLICATION_SLOT. + + + + + pg_create_logical_replication_slot + + pg_create_logical_replication_slot(slotname name, plugin name) + + + (slotname name, xlog_position pg_lsn) + + + Creates a new logical (decoding) replication slot named + slotname using the output plugin + plugin. Output plugins are listed amongst the + extensions in pg_catalog.pg_available_extensions, + but there is no specific listing of only output plugins. Same as + walsender protocol command CREATE REPLICATION SLOT ... LOGICAL. + + + + + + + pg_logical_slot_get_changes + + pg_logical_slot_get_changes(slotname name, upto_lsn pg_lsn, upto_nchanges int, VARIADIC options text[]) + + + (location pg_lsn, xid xid, data text) + + + Returns changes in the slot slotname, starting + from the point at which since changes have been consumed last. Changes + are extracted upto the current end of the WAL, or if nonnull only if + their transactions have committed + before upto_lsn, or if nonnull + until upto_nchanges rows have been + collected. Note that the upto_nchanges limit is + only enforced everytime a transaction commits. Changes will not be + consumed. + + + + + + + pg_logical_slot_peek_changes + + pg_logical_slot_peek_changes(slotname name, upto_lsn pg_lsn, upto_nchanges int, VARIADIC options text[]) + + + (location text, xid xid, data text) + + + Behaves just like + the pg_logical_slot_get_changes() function, + except that changes are not consumed, i.e. will be returned again on + future calls. + + + + + + + pg_logical_slot_get_binary_changes + + pg_logical_slot_get_binary_changes(slotname name, upto_lsn pg_lsn, upto_nchanges int, VARIADIC options text[]) + + + (location pg_lsn, xid xid, data bytea) + + + Behaves just like + the pg_logical_slot_get_changes() function, + except that changes are returned as bytea. + + + + + + + pg_logical_slot_peek_binary_changes + + pg_logical_slot_peek_binary_changes(slotname name, upto_lsn pg_lsn, upto_nchanges int, VARIADIC options text[]) + + + (location pg_lsn, xid xid, data bytea) + + + Behaves just like + the pg_logical_slot_get_changes() function, + except that changes are returned as bytea and that + changes are not consumed, i.e. will be returned again on future calls. + +
+ diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index b47bf52..dd1709f 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -219,6 +219,7 @@ &spi; &bgworker; + &changesetextraction; diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 510bf9a..3621772 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1301,24 +1301,48 @@ Streaming Replication Protocol -To initiate streaming replication, the frontend sends the -replication parameter in the startup message. A boolean value -of true tells the backend to go into walsender mode, wherein a -small set of replication commands can be issued instead of SQL statements. Only -the simple query protocol can be used in walsender mode. -Passing a database as the value instructs walsender to connect to -the database specified in the dbname paramter which will in future -allow some additional commands to the ones specified below to be run. + To initiate streaming replication, the frontend sends the + replication parameter in the startup message. This accepts the + values true, false (and their 1/0 + numeric equivalents) or in 9.4 and above, database. + + + Any valid non-false value tells the backend to go into walsender mode, wherein + the small set of replication commands documented below can be issued instead + of SQL statements. Only the simple query protocol can be used in walsender + mode. + + + If replication is true, no specific + database is connected to. In this mode only a subset of walsender subcommands + are available. To use database-specific walsender commands like the logical + replication commands, replication must be set to + database and the name of a database to connect to must be + specified in the database startup packet field. + + + For the purpose of testing replication commands, you can make a replication + connection via psql or any other libpq-using + tool with a connection string including the replication option, + e.g.: + + psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" + + However it is usually more useful to use + pg_receivexlog (for physical replication) or + pg_recvlogical (for logical replication). + + The commands accepted in walsender mode are: - IDENTIFY_SYSTEM - Requests the server to identify itself. Server replies with a result - set of a single row, containing four fields: + Requests the server to identify itself. Does not require a database name + to be specified for the connection. Server replies with a result set of a + single row, containing four fields: @@ -1381,7 +1405,8 @@ The commands accepted in walsender mode are: Requests the server to send over the timeline history file for timeline - tli. Server replies with a + tli. Does not require a database + name to be specified for the connection. Server replies with a result set of a single row, containing two fields: @@ -1764,17 +1789,55 @@ The commands accepted in walsender mode are: + + START_REPLICATION SLOT slotname LOGICAL XXX/XXX + + + Instructs server to start streaming WAL for logical replication, starting + at WAL position XXX/XXX. The server can + reply with an error, e.g. if the requested section of WAL has already + been recycled. On success, server responds with a CopyBothResponse + message, and then starts to stream WAL to the frontend. + + + The output plugin associated with the selected slot is used + to process the output for streaming. + + + + SLOT slotname + + + The name of the slot to stream changes from. This parameter is required, + and must correspond to an existing logical replication slot created + with CREATE_REPLICATION_SLOT in + LOGICAL mode. + + + + + XXX/XXX + + + The WAL position to begin streaming at. + + + + + + - DROP_REPLICATION_SLOT slotname + DROP_REPLICATION_SLOT SLOT slotname - Drops a replication slot, freeing any reserved server-side resources. If - the slot is currently in use by an active connection, this command fails. + Drops a physical or logical replication slot, freeing any reserved server-side + resources. If the slot is currently in use by an active connection this command + fails. - slotname + SLOT slotname The name of the slot to drop. diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 2b02e66..4847d66 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -580,7 +580,7 @@ ALTER TABLE [ IF EXISTS ] name - + REPLICA IDENTITY diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index fc7ad09..f5a3e3e 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -137,7 +137,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI - + TEMPORARY or TEMP @@ -171,7 +171,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI - + UNLOGGED @@ -1051,6 +1051,17 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI + + user_catalog_table (boolean) + + + Declare a table as an additional catalog table, e.g. for the purpose of + logical replication. See + for details. + + + + -- 1.8.3.251.g1462b67