From e6785a5ca16bfe67b9c74d168ae6e88c6e55c8ac Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Tue, 30 May 2017 15:45:42 -0400 Subject: Fix wording in amvalidate error messages Remove some gratuituous message differences by making the AM name previously embedded in each message be a %s instead. While at it, get rid of terminology that's unclear and unnecessary in one message. Discussion: https://postgr.es/m/20170523001557.bq2hbq7hxyvyw62q@alvherre.pgsql --- contrib/isn/expected/isn.out | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'contrib') diff --git a/contrib/isn/expected/isn.out b/contrib/isn/expected/isn.out index ef9d3a61e7..18fe37a82c 100644 --- a/contrib/isn/expected/isn.out +++ b/contrib/isn/expected/isn.out @@ -10,22 +10,22 @@ FROM (SELECT amname, opcname, opc.oid WHERE opc.oid >= 16384 ORDER BY 1, 2 OFFSET 0) ss WHERE NOT amvalidate(oid); -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: btree operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) -INFO: hash operator family "isn_ops" is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method btree is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) +INFO: operator family "isn_ops" of access method hash is missing cross-type operator(s) amname | opcname --------+------------ btree | ean13_ops -- cgit v1.2.3 From e7941a976688f0f5d13a5227ed4f3efe0718db9d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 4 Jun 2017 16:20:03 -0400 Subject: Replace over-optimistic Assert in partitioning code with a runtime test. get_partition_parent felt that it could simply Assert that systable_getnext found a tuple. This is unlike any other caller of that function, and it's unsafe IMO --- in fact, the reason I noticed it was that the Assert failed. (OK, I was working with known-inconsistent catalog contents, but I wasn't expecting the DB to fall over quite that violently. The behavior in a non-assert-enabled build wouldn't be very nice, either.) Fix it to do what other callers do, namely an actual runtime-test-and-elog. Also, standardize the wording of elog messages that are complaining about unexpected failure of systable_getnext. 90% of them say "could not find tuple for ", so make the remainder do likewise. Many of the holdouts were using the phrasing "cache lookup failed", which is outright misleading since no catcache search is involved. --- contrib/sepgsql/database.c | 2 +- contrib/sepgsql/proc.c | 4 ++-- contrib/sepgsql/relation.c | 8 ++++---- contrib/sepgsql/schema.c | 2 +- src/backend/catalog/aclchk.c | 4 ++-- src/backend/catalog/objectaddress.c | 2 +- src/backend/catalog/partition.c | 3 ++- src/backend/commands/extension.c | 9 +++++---- src/backend/utils/adt/ruleutils.c | 2 +- 9 files changed, 19 insertions(+), 17 deletions(-) (limited to 'contrib') diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c index 69dd290a77..8fc5a87e00 100644 --- a/contrib/sepgsql/database.c +++ b/contrib/sepgsql/database.c @@ -88,7 +88,7 @@ sepgsql_database_post_create(Oid databaseId, const char *dtemplate) SnapshotSelf, 1, &skey); tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "catalog lookup failed for database %u", databaseId); + elog(ERROR, "could not find tuple for database %u", databaseId); datForm = (Form_pg_database) GETSTRUCT(tuple); diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c index 4ccf4a5e60..73564edaa7 100644 --- a/contrib/sepgsql/proc.c +++ b/contrib/sepgsql/proc.c @@ -68,7 +68,7 @@ sepgsql_proc_post_create(Oid functionId) tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "catalog lookup failed for proc %u", functionId); + elog(ERROR, "could not find tuple for function %u", functionId); proForm = (Form_pg_proc) GETSTRUCT(tuple); @@ -261,7 +261,7 @@ sepgsql_proc_setattr(Oid functionId) SnapshotSelf, 1, &skey); newtup = systable_getnext(sscan); if (!HeapTupleIsValid(newtup)) - elog(ERROR, "catalog lookup failed for function %u", functionId); + elog(ERROR, "could not find tuple for function %u", functionId); newform = (Form_pg_proc) GETSTRUCT(newtup); /* diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c index 59a6d9be6e..228869a520 100644 --- a/contrib/sepgsql/relation.c +++ b/contrib/sepgsql/relation.c @@ -83,7 +83,7 @@ sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum) tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "catalog lookup failed for column %d of relation %u", + elog(ERROR, "could not find tuple for column %d of relation %u", attnum, relOid); attForm = (Form_pg_attribute) GETSTRUCT(tuple); @@ -271,7 +271,7 @@ sepgsql_relation_post_create(Oid relOid) tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "catalog lookup failed for relation %u", relOid); + elog(ERROR, "could not find tuple for relation %u", relOid); classForm = (Form_pg_class) GETSTRUCT(tuple); @@ -623,7 +623,7 @@ sepgsql_relation_setattr(Oid relOid) newtup = systable_getnext(sscan); if (!HeapTupleIsValid(newtup)) - elog(ERROR, "catalog lookup failed for relation %u", relOid); + elog(ERROR, "could not find tuple for relation %u", relOid); newform = (Form_pg_class) GETSTRUCT(newtup); /* @@ -700,7 +700,7 @@ sepgsql_relation_setattr_extra(Relation catalog, SnapshotSelf, 1, &skey); tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "catalog lookup failed for object %u in catalog \"%s\"", + elog(ERROR, "could not find tuple for object %u in catalog \"%s\"", extra_oid, RelationGetRelationName(catalog)); datum = heap_getattr(tuple, anum_relation_id, diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c index 940384bf40..d418577b75 100644 --- a/contrib/sepgsql/schema.c +++ b/contrib/sepgsql/schema.c @@ -67,7 +67,7 @@ sepgsql_schema_post_create(Oid namespaceId) SnapshotSelf, 1, &skey); tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "catalog lookup failed for namespace %u", namespaceId); + elog(ERROR, "could not find tuple for namespace %u", namespaceId); nspForm = (Form_pg_namespace) GETSTRUCT(tuple); nsp_name = NameStr(nspForm->nspname); diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 387a3be701..304e3c4bc3 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -2738,7 +2738,7 @@ ExecGrant_Largeobject(InternalGrant *istmt) tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for large object %u", loid); + elog(ERROR, "could not find tuple for large object %u", loid); form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple); @@ -5503,7 +5503,7 @@ recordExtObjInitPriv(Oid objoid, Oid classoid) tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for large object %u", objoid); + elog(ERROR, "could not find tuple for large object %u", objoid); aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl, diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 6bc05cab3a..be16cf66f4 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -3345,7 +3345,7 @@ getObjectDescription(const ObjectAddress *object) tuple = systable_getnext(sscan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for policy %u", + elog(ERROR, "could not find tuple for policy %u", object->objectId); form_policy = (Form_pg_policy) GETSTRUCT(tuple); diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 37fa1458be..5c5a9e11ab 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -874,7 +874,8 @@ get_partition_parent(Oid relid) NULL, 2, key); tuple = systable_getnext(scan); - Assert(HeapTupleIsValid(tuple)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "could not find tuple for parent of relation %u", relid); form = (Form_pg_inherits) GETSTRUCT(tuple); result = form->inhparent; diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index c3718b08c1..e8126a38a9 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -2387,7 +2387,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) extTup = systable_getnext(extScan); if (!HeapTupleIsValid(extTup)) /* should not happen */ - elog(ERROR, "extension with oid %u does not exist", + elog(ERROR, "could not find tuple for extension %u", CurrentExtensionObject); memset(repl_val, 0, sizeof(repl_val)); @@ -2535,7 +2535,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid) extTup = systable_getnext(extScan); if (!HeapTupleIsValid(extTup)) /* should not happen */ - elog(ERROR, "extension with oid %u does not exist", + elog(ERROR, "could not find tuple for extension %u", extensionoid); /* Search extconfig for the tableoid */ @@ -2736,7 +2736,8 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o extTup = systable_getnext(extScan); if (!HeapTupleIsValid(extTup)) /* should not happen */ - elog(ERROR, "extension with oid %u does not exist", extensionOid); + elog(ERROR, "could not find tuple for extension %u", + extensionOid); /* Copy tuple so we can modify it below */ extTup = heap_copytuple(extTup); @@ -3057,7 +3058,7 @@ ApplyExtensionUpdates(Oid extensionOid, extTup = systable_getnext(extScan); if (!HeapTupleIsValid(extTup)) /* should not happen */ - elog(ERROR, "extension with oid %u does not exist", + elog(ERROR, "could not find tuple for extension %u", extensionOid); extForm = (Form_pg_extension) GETSTRUCT(extTup); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 824d7572fa..6a0d273bd2 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -1851,7 +1851,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, heap_close(relation, AccessShareLock); return NULL; } - elog(ERROR, "cache lookup failed for constraint %u", constraintId); + elog(ERROR, "could not find tuple for constraint %u", constraintId); } conForm = (Form_pg_constraint) GETSTRUCT(tup); -- cgit v1.2.3 From ae9bfc5d65123aaa0d1cca9988037489760bdeae Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 7 Jun 2017 15:14:55 -0400 Subject: postgres_fdw: Allow cancellation of transaction control commands. Commit f039eaac7131ef2a4cf63a10cf98486f8bcd09d2, later back-patched with commit 1b812afb0eafe125b820cc3b95e7ca03821aa675, allowed many of the queries issued by postgres_fdw to fetch remote data to respond to cancel interrupts in a timely fashion. However, it didn't do anything about the transaction control commands, which remained noninterruptible. Improve the situation by changing do_sql_command() to retrieve query results using pgfdw_get_result(), which uses the asynchronous interface to libpq so that it can check for interrupts every time libpq returns control. Since this might result in a situation where we can no longer be sure that the remote transaction state matches the local transaction state, add a facility to force all levels of the local transaction to abort if we've lost track of the remote state; without this, an apparently-successful commit of the local transaction might fail to commit changes made on the remote side. Also, add a 60-second timeout for queries issue during transaction abort; if that expires, give up and mark the state of the connection as unknown. Drop all such connections when we exit the local transaction. Together, these changes mean that if we're aborting the local toplevel transaction anyway, we can just drop the remote connection in lieu of waiting (possibly for a very long time) for it to complete an abort. This still leaves quite a bit of room for improvement. PQcancel() has no asynchronous interface, so if we get stuck sending the cancel request we'll still hang. Also, PQsetnonblocking() is not used, which means we could block uninterruptibly when sending a query. There might be some other optimizations possible as well. Nonetheless, this allows us to escape a wait for an unresponsive remote server quickly in many more cases than previously. Report by Suraj Kharage. Patch by me and Rafia Sabih. Review and testing by Amit Kapila and Tushar Ahuja. Discussion: http://postgr.es/m/CAF1DzPU8Kx+fMXEbFoP289xtm3bz3t+ZfxhmKavr98Bh-C0TqQ@mail.gmail.com --- contrib/postgres_fdw/connection.c | 361 ++++++++++++++++++++++++++++++++------ 1 file changed, 308 insertions(+), 53 deletions(-) (limited to 'contrib') diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index c6e3d44515..1b691fb05e 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -14,6 +14,8 @@ #include "postgres_fdw.h" +#include "access/htup_details.h" +#include "catalog/pg_user_mapping.h" #include "access/xact.h" #include "mb/pg_wchar.h" #include "miscadmin.h" @@ -21,6 +23,7 @@ #include "storage/latch.h" #include "utils/hsearch.h" #include "utils/memutils.h" +#include "utils/syscache.h" /* @@ -49,6 +52,7 @@ typedef struct ConnCacheEntry * one level of subxact open, etc */ bool have_prep_stmt; /* have we prepared any stmts in this xact? */ bool have_error; /* have any subxacts aborted in this xact? */ + bool changing_xact_state; /* xact state change in process */ } ConnCacheEntry; /* @@ -74,6 +78,12 @@ static void pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg); +static void pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry); +static bool pgfdw_cancel_query(PGconn *conn); +static bool pgfdw_exec_cleanup_query(PGconn *conn, const char *query, + bool ignore_errors); +static bool pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, + PGresult **result); /* @@ -139,8 +149,12 @@ GetConnection(UserMapping *user, bool will_prep_stmt) entry->xact_depth = 0; entry->have_prep_stmt = false; entry->have_error = false; + entry->changing_xact_state = false; } + /* Reject further use of connections which failed abort cleanup. */ + pgfdw_reject_incomplete_xact_state_change(entry); + /* * We don't check the health of cached connection here, because it would * require some overhead. Broken connection will be detected when the @@ -343,7 +357,9 @@ do_sql_command(PGconn *conn, const char *sql) { PGresult *res; - res = PQexec(conn, sql); + if (!PQsendQuery(conn, sql)) + pgfdw_report_error(ERROR, NULL, conn, false, sql); + res = pgfdw_get_result(conn, sql); if (PQresultStatus(res) != PGRES_COMMAND_OK) pgfdw_report_error(ERROR, res, conn, true, sql); PQclear(res); @@ -376,8 +392,10 @@ begin_remote_xact(ConnCacheEntry *entry) sql = "START TRANSACTION ISOLATION LEVEL SERIALIZABLE"; else sql = "START TRANSACTION ISOLATION LEVEL REPEATABLE READ"; + entry->changing_xact_state = true; do_sql_command(entry->conn, sql); entry->xact_depth = 1; + entry->changing_xact_state = false; } /* @@ -390,8 +408,10 @@ begin_remote_xact(ConnCacheEntry *entry) char sql[64]; snprintf(sql, sizeof(sql), "SAVEPOINT s%d", entry->xact_depth + 1); + entry->changing_xact_state = true; do_sql_command(entry->conn, sql); entry->xact_depth++; + entry->changing_xact_state = false; } } @@ -604,6 +624,8 @@ pgfdw_xact_callback(XactEvent event, void *arg) /* If it has an open remote transaction, try to close it */ if (entry->xact_depth > 0) { + bool abort_cleanup_failure = false; + elog(DEBUG3, "closing remote transaction on connection %p", entry->conn); @@ -611,8 +633,17 @@ pgfdw_xact_callback(XactEvent event, void *arg) { case XACT_EVENT_PARALLEL_PRE_COMMIT: case XACT_EVENT_PRE_COMMIT: + + /* + * If abort cleanup previously failed for this connection, + * we can't issue any more commands against it. + */ + pgfdw_reject_incomplete_xact_state_change(entry); + /* Commit all remote transactions during pre-commit */ + entry->changing_xact_state = true; do_sql_command(entry->conn, "COMMIT TRANSACTION"); + entry->changing_xact_state = false; /* * If there were any errors in subtransactions, and we @@ -660,6 +691,27 @@ pgfdw_xact_callback(XactEvent event, void *arg) break; case XACT_EVENT_PARALLEL_ABORT: case XACT_EVENT_ABORT: + + /* + * Don't try to clean up the connection if we're already + * in error recursion trouble. + */ + if (in_error_recursion_trouble()) + entry->changing_xact_state = true; + + /* + * If connection is already unsalvageable, don't touch it + * further. + */ + if (entry->changing_xact_state) + break; + + /* + * Mark this connection as in the process of changing + * transaction state. + */ + entry->changing_xact_state = true; + /* Assume we might have lost track of prepared statements */ entry->have_error = true; @@ -670,40 +722,35 @@ pgfdw_xact_callback(XactEvent event, void *arg) * command is still being processed by the remote server, * and if so, request cancellation of the command. */ - if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE) + if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE && + !pgfdw_cancel_query(entry->conn)) { - PGcancel *cancel; - char errbuf[256]; - - if ((cancel = PQgetCancel(entry->conn))) - { - if (!PQcancel(cancel, errbuf, sizeof(errbuf))) - ereport(WARNING, - (errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("could not send cancel request: %s", - errbuf))); - PQfreeCancel(cancel); - } + /* Unable to cancel running query. */ + abort_cleanup_failure = true; + } + else if (!pgfdw_exec_cleanup_query(entry->conn, + "ABORT TRANSACTION", + false)) + { + /* Unable to abort remote transaction. */ + abort_cleanup_failure = true; + } + else if (entry->have_prep_stmt && entry->have_error && + !pgfdw_exec_cleanup_query(entry->conn, + "DEALLOCATE ALL", + true)) + { + /* Trouble clearing prepared statements. */ + abort_cleanup_failure = true; } - - /* If we're aborting, abort all remote transactions too */ - res = PQexec(entry->conn, "ABORT TRANSACTION"); - /* Note: can't throw ERROR, it would be infinite loop */ - if (PQresultStatus(res) != PGRES_COMMAND_OK) - pgfdw_report_error(WARNING, res, entry->conn, true, - "ABORT TRANSACTION"); else { - PQclear(res); - /* As above, make sure to clear any prepared stmts */ - if (entry->have_prep_stmt && entry->have_error) - { - res = PQexec(entry->conn, "DEALLOCATE ALL"); - PQclear(res); - } entry->have_prep_stmt = false; entry->have_error = false; } + + /* Disarm changing_xact_state if it all worked. */ + entry->changing_xact_state = abort_cleanup_failure; break; } } @@ -716,11 +763,13 @@ pgfdw_xact_callback(XactEvent event, void *arg) * recover. Next GetConnection will open a new connection. */ if (PQstatus(entry->conn) != CONNECTION_OK || - PQtransactionStatus(entry->conn) != PQTRANS_IDLE) + PQtransactionStatus(entry->conn) != PQTRANS_IDLE || + entry->changing_xact_state) { elog(DEBUG3, "discarding connection %p", entry->conn); PQfinish(entry->conn); entry->conn = NULL; + entry->changing_xact_state = false; } } @@ -763,7 +812,6 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, hash_seq_init(&scan, ConnectionHash); while ((entry = (ConnCacheEntry *) hash_seq_search(&scan))) { - PGresult *res; char sql[100]; /* @@ -779,12 +827,33 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, if (event == SUBXACT_EVENT_PRE_COMMIT_SUB) { + /* + * If abort cleanup previously failed for this connection, we + * can't issue any more commands against it. + */ + pgfdw_reject_incomplete_xact_state_change(entry); + /* Commit all remote subtransactions during pre-commit */ snprintf(sql, sizeof(sql), "RELEASE SAVEPOINT s%d", curlevel); + entry->changing_xact_state = true; do_sql_command(entry->conn, sql); + entry->changing_xact_state = false; } - else + else if (in_error_recursion_trouble()) + { + /* + * Don't try to clean up the connection if we're already in error + * recursion trouble. + */ + entry->changing_xact_state = true; + } + else if (!entry->changing_xact_state) { + bool abort_cleanup_failure = false; + + /* Remember that abort cleanup is in progress. */ + entry->changing_xact_state = true; + /* Assume we might have lost track of prepared statements */ entry->have_error = true; @@ -795,34 +864,220 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, * processed by the remote server, and if so, request cancellation * of the command. */ - if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE) + if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE && + !pgfdw_cancel_query(entry->conn)) + abort_cleanup_failure = true; + else { - PGcancel *cancel; - char errbuf[256]; - - if ((cancel = PQgetCancel(entry->conn))) - { - if (!PQcancel(cancel, errbuf, sizeof(errbuf))) - ereport(WARNING, - (errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("could not send cancel request: %s", - errbuf))); - PQfreeCancel(cancel); - } + /* Rollback all remote subtransactions during abort */ + snprintf(sql, sizeof(sql), + "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d", + curlevel, curlevel); + if (!pgfdw_exec_cleanup_query(entry->conn, sql, false)) + abort_cleanup_failure = true; } - /* Rollback all remote subtransactions during abort */ - snprintf(sql, sizeof(sql), - "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d", - curlevel, curlevel); - res = PQexec(entry->conn, sql); - if (PQresultStatus(res) != PGRES_COMMAND_OK) - pgfdw_report_error(WARNING, res, entry->conn, true, sql); - else - PQclear(res); + /* Disarm changing_xact_state if it all worked. */ + entry->changing_xact_state = abort_cleanup_failure; } /* OK, we're outta that level of subtransaction */ entry->xact_depth--; } } + +/* + * Raise an error if the given connection cache entry is marked as being + * in the middle of an xact state change. This should be called at which no + * such change is expected to be in progress; if one is found to be in + * progress, it means that we aborted in the middle of a previous state change + * and now don't know what the remote transaction state actually is. + * Such connections can't safely be further used. Re-establishing the + * connection would change the snapshot and roll back any writes already + * performed, so that's not an option, either. Thus, we must abort. + */ +static void +pgfdw_reject_incomplete_xact_state_change(ConnCacheEntry *entry) +{ + HeapTuple tup; + Form_pg_user_mapping umform; + ForeignServer *server; + + if (!entry->changing_xact_state) + return; + + tup = SearchSysCache1(USERMAPPINGOID, + ObjectIdGetDatum(entry->key)); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for user mapping %u", entry->key); + umform = (Form_pg_user_mapping) GETSTRUCT(tup); + server = GetForeignServer(umform->umserver); + ReleaseSysCache(tup); + + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_EXCEPTION), + errmsg("connection to server \"%s\" was lost", + server->servername))); +} + +/* + * Cancel the currently-in-progress query (whose query text we do not have) + * and ignore the result. Returns true if we successfully cancel the query + * and discard any pending result, and false if not. + */ +static bool +pgfdw_cancel_query(PGconn *conn) +{ + PGcancel *cancel; + char errbuf[256]; + PGresult *result = NULL; + TimestampTz endtime; + + /* + * If it takes too long to cancel the query and discard the result, assume + * the connection is dead. + */ + endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(), 30000); + + /* + * Issue cancel request. Unfortunately, there's no good way to limit the + * amount of time that we might block inside PQgetCancel(). + */ + if ((cancel = PQgetCancel(conn))) + { + if (!PQcancel(cancel, errbuf, sizeof(errbuf))) + { + ereport(WARNING, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("could not send cancel request: %s", + errbuf))); + PQfreeCancel(cancel); + return false; + } + PQfreeCancel(cancel); + } + + /* Get and discard the result of the query. */ + if (pgfdw_get_cleanup_result(conn, endtime, &result)) + return false; + PQclear(result); + + return true; +} + +/* + * Submit a query during (sub)abort cleanup and wait up to 30 seconds for the + * result. If the query is executed without error, the return value is true. + * If the query is executed successfully but returns an error, the return + * value is true if and only if ignore_errors is set. If the query can't be + * sent or times out, the return value is false. + */ +static bool +pgfdw_exec_cleanup_query(PGconn *conn, const char *query, bool ignore_errors) +{ + PGresult *result = NULL; + TimestampTz endtime; + + /* + * If it takes too long to execute a cleanup query, assume the connection + * is dead. It's fairly likely that this is why we aborted in the first + * place (e.g. statement timeout, user cancel), so the timeout shouldn't + * be too long. + */ + endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(), 30000); + + /* + * Submit a query. Since we don't use non-blocking mode, this also can + * block. But its risk is relatively small, so we ignore that for now. + */ + if (!PQsendQuery(conn, query)) + { + pgfdw_report_error(WARNING, NULL, conn, false, query); + return false; + } + + /* Get the result of the query. */ + if (pgfdw_get_cleanup_result(conn, endtime, &result)) + return false; + + /* Issue a warning if not successful. */ + if (PQresultStatus(result) != PGRES_COMMAND_OK) + { + pgfdw_report_error(WARNING, result, conn, true, query); + return ignore_errors; + } + + return true; +} + +/* + * Get, during abort cleanup, the result of a query that is in progress. This + * might be a query that is being interrupted by transaction abort, or it might + * be a query that was initiated as part of transaction abort to get the remote + * side back to the appropriate state. + * + * It's not a huge problem if we throw an ERROR here, but if we get into error + * recursion trouble, we'll end up slamming the connection shut, which will + * necessitate failing the entire toplevel transaction even if subtransactions + * were used. Try to use WARNING where we can. + * + * endtime is the time at which we should give up and assume the remote + * side is dead. Returns true if the timeout expired, otherwise false. + * Sets *result except in case of a timeout. + */ +static bool +pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result) +{ + PGresult *last_res = NULL; + + for (;;) + { + PGresult *res; + + while (PQisBusy(conn)) + { + int wc; + TimestampTz now = GetCurrentTimestamp(); + long secs; + int microsecs; + long cur_timeout; + + /* If timeout has expired, give up, else get sleep time. */ + if (now >= endtime) + return true; + TimestampDifference(now, endtime, &secs, µsecs); + + /* To protect against clock skew, limit sleep to one minute. */ + cur_timeout = Min(60000, secs * USECS_PER_SEC + microsecs); + + /* Sleep until there's something to do */ + wc = WaitLatchOrSocket(MyLatch, + WL_LATCH_SET | WL_SOCKET_READABLE | WL_TIMEOUT, + PQsocket(conn), + cur_timeout, PG_WAIT_EXTENSION); + ResetLatch(MyLatch); + + CHECK_FOR_INTERRUPTS(); + + /* Data available in socket */ + if (wc & WL_SOCKET_READABLE) + { + if (!PQconsumeInput(conn)) + { + *result = NULL; + return false; + } + } + } + + res = PQgetResult(conn); + if (res == NULL) + break; /* query is complete */ + + PQclear(last_res); + last_res = res; + } + + *result = last_res; + return false; +} -- cgit v1.2.3 From 06c0afe56e7aa6e8ab9ea2dd92bac2220201affe Mon Sep 17 00:00:00 2001 From: Joe Conway Date: Wed, 7 Jun 2017 17:54:33 -0700 Subject: Fix contrib/sepgsql regr tests for tup-routing constraint check change. Commit 15ce775 changed tuple-routing constraint checking logic. This affects the expected output for contrib/sepgsql, because there's no longer LOG entries reporting allowance of int4eq() execution. Per buildfarm. --- contrib/sepgsql/expected/misc.out | 2 -- 1 file changed, 2 deletions(-) (limited to 'contrib') diff --git a/contrib/sepgsql/expected/misc.out b/contrib/sepgsql/expected/misc.out index 7b55142653..98f8005a60 100644 --- a/contrib/sepgsql/expected/misc.out +++ b/contrib/sepgsql/expected/misc.out @@ -32,9 +32,7 @@ LOG: SELinux: allowed { execute } scontext=unconfined_u:unconfined_r:sepgsql_re (6 rows) SELECT * FROM t1p WHERE o > 50 AND p like '%64%'; -LOG: SELinux: allowed { execute } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0-s0:c0.c255 tcontext=system_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="pg_catalog.int4eq(integer,integer)" LOG: SELinux: allowed { execute } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0-s0:c0.c255 tcontext=system_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="pg_catalog.int4le(integer,integer)" -LOG: SELinux: allowed { execute } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0-s0:c0.c255 tcontext=system_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="pg_catalog.int4eq(integer,integer)" LOG: SELinux: allowed { execute } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0-s0:c0.c255 tcontext=system_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="pg_catalog.int4le(integer,integer)" LOG: SELinux: allowed { execute } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0-s0:c0.c255 tcontext=system_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="pg_catalog.int4le(integer,integer)" LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0-s0:c0.c255 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="public.t1p" -- cgit v1.2.3 From 272171279f8676c57b3a8edf7daf792ad55b2c2c Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 13 Jun 2017 14:38:35 -0400 Subject: psql: Use more consistent capitalization of some output headings --- .../hstore_plperl/expected/create_transform.out | 6 +- contrib/postgres_fdw/expected/postgres_fdw.out | 84 +++++------ src/bin/psql/describe.c | 20 +-- .../test_extensions/expected/test_extensions.out | 14 +- .../test_extensions/sql/test_extensions.sql | 4 +- src/test/regress/expected/foreign_data.out | 158 ++++++++++----------- 6 files changed, 143 insertions(+), 143 deletions(-) (limited to 'contrib') diff --git a/contrib/hstore_plperl/expected/create_transform.out b/contrib/hstore_plperl/expected/create_transform.out index 02dc62af0d..dc72395376 100644 --- a/contrib/hstore_plperl/expected/create_transform.out +++ b/contrib/hstore_plperl/expected/create_transform.out @@ -44,7 +44,7 @@ DROP FUNCTION plperl_to_hstore(val internal); CREATE EXTENSION hstore_plperl; \dx+ hstore_plperl Objects in extension "hstore_plperl" - Object Description + Object description -------------------------------------- function hstore_to_plperl(internal) function plperl_to_hstore(internal) @@ -54,7 +54,7 @@ CREATE EXTENSION hstore_plperl; ALTER EXTENSION hstore_plperl DROP TRANSFORM FOR hstore LANGUAGE plperl; \dx+ hstore_plperl Objects in extension "hstore_plperl" - Object Description + Object description ------------------------------------- function hstore_to_plperl(internal) function plperl_to_hstore(internal) @@ -63,7 +63,7 @@ Objects in extension "hstore_plperl" ALTER EXTENSION hstore_plperl ADD TRANSFORM FOR hstore LANGUAGE plperl; \dx+ hstore_plperl Objects in extension "hstore_plperl" - Object Description + Object description -------------------------------------- function hstore_to_plperl(internal) function plperl_to_hstore(internal) diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 4d86ab54dd..b112c197ab 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -181,7 +181,7 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); \det+ List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------+------------+-----------+--------------------------------------------------+------------- public | ft1 | loopback | (schema_name 'S 1', table_name 'T 1') | public | ft2 | loopback | (schema_name 'S 1', table_name 'T 1') | @@ -6948,7 +6948,7 @@ CREATE SCHEMA import_dest1; IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1; \det+ import_dest1.* List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------------+-------+----------+-------------------------------------------------+------------- import_dest1 | t1 | loopback | (schema_name 'import_source', table_name 't1') | import_dest1 | t2 | loopback | (schema_name 'import_source', table_name 't2') | @@ -6960,51 +6960,51 @@ IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1; \d import_dest1.* Foreign table "import_dest1.t1" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-------------------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') c2 | character varying | | not null | | (column_name 'c2') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't1') +FDW options: (schema_name 'import_source', table_name 't1') Foreign table "import_dest1.t2" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-------------------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') c2 | character varying | | | | (column_name 'c2') c3 | text | POSIX | | | (column_name 'c3') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't2') +FDW options: (schema_name 'import_source', table_name 't2') Foreign table "import_dest1.t3" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+--------------------------+-----------+----------+---------+-------------------- c1 | timestamp with time zone | | | | (column_name 'c1') c2 | typ1 | | | | (column_name 'c2') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't3') +FDW options: (schema_name 'import_source', table_name 't3') Foreign table "import_dest1.t4" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+---------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't4') +FDW options: (schema_name 'import_source', table_name 't4') Foreign table "import_dest1.x 4" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------+-----------+----------+---------+--------------------- c1 | double precision | | | | (column_name 'c1') C 2 | text | | | | (column_name 'C 2') c3 | character varying(42) | | | | (column_name 'c3') Server: loopback -FDW Options: (schema_name 'import_source', table_name 'x 4') +FDW options: (schema_name 'import_source', table_name 'x 4') Foreign table "import_dest1.x 5" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+------------- Server: loopback -FDW Options: (schema_name 'import_source', table_name 'x 5') +FDW options: (schema_name 'import_source', table_name 'x 5') -- Options CREATE SCHEMA import_dest2; @@ -7012,7 +7012,7 @@ IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2 OPTIONS (import_default 'true'); \det+ import_dest2.* List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------------+-------+----------+-------------------------------------------------+------------- import_dest2 | t1 | loopback | (schema_name 'import_source', table_name 't1') | import_dest2 | t2 | loopback | (schema_name 'import_source', table_name 't2') | @@ -7024,58 +7024,58 @@ IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2 \d import_dest2.* Foreign table "import_dest2.t1" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-------------------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') c2 | character varying | | not null | | (column_name 'c2') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't1') +FDW options: (schema_name 'import_source', table_name 't1') Foreign table "import_dest2.t2" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-------------------+-----------+----------+---------+-------------------- c1 | integer | | | 42 | (column_name 'c1') c2 | character varying | | | | (column_name 'c2') c3 | text | POSIX | | | (column_name 'c3') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't2') +FDW options: (schema_name 'import_source', table_name 't2') Foreign table "import_dest2.t3" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+--------------------------+-----------+----------+---------+-------------------- c1 | timestamp with time zone | | | now() | (column_name 'c1') c2 | typ1 | | | | (column_name 'c2') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't3') +FDW options: (schema_name 'import_source', table_name 't3') Foreign table "import_dest2.t4" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+---------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't4') +FDW options: (schema_name 'import_source', table_name 't4') Foreign table "import_dest2.x 4" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------+-----------+----------+---------+--------------------- c1 | double precision | | | | (column_name 'c1') C 2 | text | | | | (column_name 'C 2') c3 | character varying(42) | | | | (column_name 'c3') Server: loopback -FDW Options: (schema_name 'import_source', table_name 'x 4') +FDW options: (schema_name 'import_source', table_name 'x 4') Foreign table "import_dest2.x 5" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+------------- Server: loopback -FDW Options: (schema_name 'import_source', table_name 'x 5') +FDW options: (schema_name 'import_source', table_name 'x 5') CREATE SCHEMA import_dest3; IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3 OPTIONS (import_collate 'false', import_not_null 'false'); \det+ import_dest3.* List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------------+-------+----------+-------------------------------------------------+------------- import_dest3 | t1 | loopback | (schema_name 'import_source', table_name 't1') | import_dest3 | t2 | loopback | (schema_name 'import_source', table_name 't2') | @@ -7087,51 +7087,51 @@ IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3 \d import_dest3.* Foreign table "import_dest3.t1" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-------------------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') c2 | character varying | | | | (column_name 'c2') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't1') +FDW options: (schema_name 'import_source', table_name 't1') Foreign table "import_dest3.t2" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-------------------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') c2 | character varying | | | | (column_name 'c2') c3 | text | | | | (column_name 'c3') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't2') +FDW options: (schema_name 'import_source', table_name 't2') Foreign table "import_dest3.t3" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+--------------------------+-----------+----------+---------+-------------------- c1 | timestamp with time zone | | | | (column_name 'c1') c2 | typ1 | | | | (column_name 'c2') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't3') +FDW options: (schema_name 'import_source', table_name 't3') Foreign table "import_dest3.t4" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+---------+-----------+----------+---------+-------------------- c1 | integer | | | | (column_name 'c1') Server: loopback -FDW Options: (schema_name 'import_source', table_name 't4') +FDW options: (schema_name 'import_source', table_name 't4') Foreign table "import_dest3.x 4" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------+-----------+----------+---------+--------------------- c1 | double precision | | | | (column_name 'c1') C 2 | text | | | | (column_name 'C 2') c3 | character varying(42) | | | | (column_name 'c3') Server: loopback -FDW Options: (schema_name 'import_source', table_name 'x 4') +FDW options: (schema_name 'import_source', table_name 'x 4') Foreign table "import_dest3.x 5" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+------------- Server: loopback -FDW Options: (schema_name 'import_source', table_name 'x 5') +FDW options: (schema_name 'import_source', table_name 'x 5') -- Check LIMIT TO and EXCEPT CREATE SCHEMA import_dest4; @@ -7139,7 +7139,7 @@ IMPORT FOREIGN SCHEMA import_source LIMIT TO (t1, nonesuch) FROM SERVER loopback INTO import_dest4; \det+ import_dest4.* List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------------+-------+----------+------------------------------------------------+------------- import_dest4 | t1 | loopback | (schema_name 'import_source', table_name 't1') | (1 row) @@ -7148,7 +7148,7 @@ IMPORT FOREIGN SCHEMA import_source EXCEPT (t1, "x 4", nonesuch) FROM SERVER loopback INTO import_dest4; \det+ import_dest4.* List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------------+-------+----------+-------------------------------------------------+------------- import_dest4 | t1 | loopback | (schema_name 'import_source', table_name 't1') | import_dest4 | t2 | loopback | (schema_name 'import_source', table_name 't2') | diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index d536b4b2fc..10c8a789b7 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -1726,7 +1726,7 @@ describeOneTableDetails(const char *schemaname, headers[cols++] = gettext_noop("Definition"); if (tableinfo.relkind == RELKIND_FOREIGN_TABLE && pset.sversion >= 90200) - headers[cols++] = gettext_noop("FDW Options"); + headers[cols++] = gettext_noop("FDW options"); if (verbose) { @@ -2786,7 +2786,7 @@ describeOneTableDetails(const char *schemaname, ftoptions = PQgetvalue(result, 0, 1); if (ftoptions && ftoptions[0] != '\0') { - printfPQExpBuffer(&buf, _("FDW Options: (%s)"), ftoptions); + printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions); printTableAddFooter(&cont, buf.data); } PQclear(result); @@ -3473,12 +3473,12 @@ listLanguages(const char *pattern, bool verbose, bool showSystem) ",\n NOT l.lanispl AS \"%s\",\n" " l.lanplcallfoid::regprocedure AS \"%s\",\n" " l.lanvalidator::regprocedure AS \"%s\",\n ", - gettext_noop("Internal Language"), - gettext_noop("Call Handler"), + gettext_noop("Internal language"), + gettext_noop("Call handler"), gettext_noop("Validator")); if (pset.sversion >= 90000) appendPQExpBuffer(&buf, "l.laninline::regprocedure AS \"%s\",\n ", - gettext_noop("Inline Handler")); + gettext_noop("Inline handler")); printACLColumn(&buf, "l.lanacl"); } @@ -4612,7 +4612,7 @@ listForeignDataWrappers(const char *pattern, bool verbose) " quote_literal(option_value) FROM " " pg_options_to_table(fdwoptions)), ', ') || ')' " " END AS \"%s\"", - gettext_noop("FDW Options")); + gettext_noop("FDW options")); if (pset.sversion >= 90100) appendPQExpBuffer(&buf, @@ -4696,7 +4696,7 @@ listForeignServers(const char *pattern, bool verbose) " d.description AS \"%s\"", gettext_noop("Type"), gettext_noop("Version"), - gettext_noop("FDW Options"), + gettext_noop("FDW options"), gettext_noop("Description")); } @@ -4767,7 +4767,7 @@ listUserMappings(const char *pattern, bool verbose) " quote_literal(option_value) FROM " " pg_options_to_table(umoptions)), ', ') || ')' " " END AS \"%s\"", - gettext_noop("FDW Options")); + gettext_noop("FDW options")); appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n"); @@ -4831,7 +4831,7 @@ listForeignTables(const char *pattern, bool verbose) " pg_options_to_table(ftoptions)), ', ') || ')' " " END AS \"%s\",\n" " d.description AS \"%s\"", - gettext_noop("FDW Options"), + gettext_noop("FDW options"), gettext_noop("Description")); appendPQExpBufferStr(&buf, @@ -5017,7 +5017,7 @@ listOneExtensionContents(const char *extname, const char *oid) "FROM pg_catalog.pg_depend\n" "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n" "ORDER BY 1;", - gettext_noop("Object Description"), + gettext_noop("Object description"), oid); res = PSQLexec(buf.data); diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out index ba8b90e742..28d86c4b87 100644 --- a/src/test/modules/test_extensions/expected/test_extensions.out +++ b/src/test/modules/test_extensions/expected/test_extensions.out @@ -44,7 +44,7 @@ create table old_table1 (col1 serial primary key); create extension test_ext7; \dx+ test_ext7 Objects in extension "test_ext7" - Object Description + Object description ------------------------------- sequence ext7_table1_col1_seq sequence ext7_table2_col2_seq @@ -57,7 +57,7 @@ Objects in extension "test_ext7" alter extension test_ext7 update to '2.0'; \dx+ test_ext7 Objects in extension "test_ext7" - Object Description + Object description ------------------------------- sequence ext7_table2_col2_seq table ext7_table2 @@ -67,12 +67,12 @@ Objects in extension "test_ext7" create extension test_ext8; -- \dx+ would expose a variable pg_temp_nn schema name, so we can't use it here select regexp_replace(pg_describe_object(classid, objid, objsubid), - 'pg_temp_\d+', 'pg_temp', 'g') as "Object Description" + 'pg_temp_\d+', 'pg_temp', 'g') as "Object description" from pg_depend where refclassid = 'pg_extension'::regclass and deptype = 'e' and refobjid = (select oid from pg_extension where extname = 'test_ext8') order by 1; - Object Description + Object description ----------------------------------------- function ext8_even(posint) function pg_temp.ext8_temp_even(posint) @@ -85,12 +85,12 @@ order by 1; drop extension test_ext8; create extension test_ext8; select regexp_replace(pg_describe_object(classid, objid, objsubid), - 'pg_temp_\d+', 'pg_temp', 'g') as "Object Description" + 'pg_temp_\d+', 'pg_temp', 'g') as "Object description" from pg_depend where refclassid = 'pg_extension'::regclass and deptype = 'e' and refobjid = (select oid from pg_extension where extname = 'test_ext8') order by 1; - Object Description + Object description ----------------------------------------- function ext8_even(posint) function pg_temp.ext8_temp_even(posint) @@ -112,7 +112,7 @@ end'; -- extension should now contain no temp objects \dx+ test_ext8 Objects in extension "test_ext8" - Object Description + Object description ---------------------------- function ext8_even(posint) table ext8_table1 diff --git a/src/test/modules/test_extensions/sql/test_extensions.sql b/src/test/modules/test_extensions/sql/test_extensions.sql index 0bfc559295..9e64503eb5 100644 --- a/src/test/modules/test_extensions/sql/test_extensions.sql +++ b/src/test/modules/test_extensions/sql/test_extensions.sql @@ -31,7 +31,7 @@ create extension test_ext8; -- \dx+ would expose a variable pg_temp_nn schema name, so we can't use it here select regexp_replace(pg_describe_object(classid, objid, objsubid), - 'pg_temp_\d+', 'pg_temp', 'g') as "Object Description" + 'pg_temp_\d+', 'pg_temp', 'g') as "Object description" from pg_depend where refclassid = 'pg_extension'::regclass and deptype = 'e' and refobjid = (select oid from pg_extension where extname = 'test_ext8') @@ -42,7 +42,7 @@ drop extension test_ext8; create extension test_ext8; select regexp_replace(pg_describe_object(classid, objid, objsubid), - 'pg_temp_\d+', 'pg_temp', 'g') as "Object Description" + 'pg_temp_\d+', 'pg_temp', 'g') as "Object description" from pg_depend where refclassid = 'pg_extension'::regclass and deptype = 'e' and refobjid = (select oid from pg_extension where extname = 'test_ext8') diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out index 699309b3b2..7f2f529393 100644 --- a/src/test/regress/expected/foreign_data.out +++ b/src/test/regress/expected/foreign_data.out @@ -53,7 +53,7 @@ DROP FOREIGN DATA WRAPPER foo; CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1'); \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+---------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | (testing '1') | @@ -66,7 +66,7 @@ ERROR: option "testing" provided more than once CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2'); \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+----------------------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | (testing '1', another '2') | @@ -82,7 +82,7 @@ RESET ROLE; CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator; \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+-------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | postgresql_fdw_validator | | | @@ -99,7 +99,7 @@ ERROR: function bar(text[], oid) does not exist ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR; \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+-------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | | @@ -114,7 +114,7 @@ ERROR: option "c" not found ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x); \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+----------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | (a '1', b '2') | @@ -124,7 +124,7 @@ ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x); ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4'); \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+----------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | (b '3', c '4') | @@ -136,7 +136,7 @@ ALTER FOREIGN DATA WRAPPER foo OPTIONS (b '4'); -- ERROR ERROR: option "b" provided more than once \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+-----------------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | (b '3', c '4', a '2') | @@ -151,7 +151,7 @@ SET ROLE regress_test_role_super; ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5'); \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+------------------------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | (b '3', c '4', a '2', d '5') | @@ -170,7 +170,7 @@ HINT: Must be superuser to alter a foreign-data wrapper. RESET ROLE; \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+------------------------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_test_role_super | - | - | | (b '3', c '4', a '2', d '5') | @@ -180,7 +180,7 @@ RESET ROLE; ALTER FOREIGN DATA WRAPPER foo RENAME TO foo1; \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+------------------------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo1 | regress_test_role_super | - | - | | (b '3', c '4', a '2', d '5') | @@ -195,7 +195,7 @@ DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent; NOTICE: foreign-data wrapper "nonexistent" does not exist, skipping \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+------------------------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_test_role_super | - | - | | (b '3', c '4', a '2', d '5') | @@ -211,7 +211,7 @@ RESET ROLE; DROP ROLE regress_test_role_super; \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+-------------+------------- dummy | regress_foreign_data_user | - | - | | | useless postgresql | regress_foreign_data_user | - | postgresql_fdw_validator | | | @@ -227,7 +227,7 @@ CREATE USER MAPPING IF NOT EXISTS FOR current_user SERVER s1; -- NOTICE NOTICE: user mapping for "regress_foreign_data_user" already exists for server s1, skipping \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+-------------+------------- dummy | regress_foreign_data_user | - | - | | | useless foo | regress_foreign_data_user | - | - | | | @@ -236,14 +236,14 @@ NOTICE: user mapping for "regress_foreign_data_user" already exists for server \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+---------------------------+----------------------+-------------------+------+---------+-------------+---------------- s1 | regress_foreign_data_user | foo | | | | | foreign server (1 row) \deu+ List of user mappings - Server | User name | FDW Options + Server | User name | FDW options --------+---------------------------+------------- s1 | regress_foreign_data_user | (1 row) @@ -263,7 +263,7 @@ DETAIL: drop cascades to server s1 drop cascades to user mapping for regress_foreign_data_user on server s1 \dew+ List of foreign-data wrappers - Name | Owner | Handler | Validator | Access privileges | FDW Options | Description + Name | Owner | Handler | Validator | Access privileges | FDW options | Description ------------+---------------------------+---------+--------------------------+-------------------+-------------+------------- dummy | regress_foreign_data_user | - | - | | | useless postgresql | regress_foreign_data_user | - | postgresql_fdw_validator | | | @@ -271,13 +271,13 @@ drop cascades to user mapping for regress_foreign_data_user on server s1 \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+-------+----------------------+-------------------+------+---------+-------------+------------- (0 rows) \deu+ List of user mappings - Server | User name | FDW Options + Server | User name | FDW options --------+-----------+------------- (0 rows) @@ -302,7 +302,7 @@ HINT: Valid options in this context are: authtype, service, connect_timeout, db CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db'); \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+---------------------------+----------------------+-------------------+--------+---------+-----------------------------------+------------- s1 | regress_foreign_data_user | foo | | | | | s2 | regress_foreign_data_user | foo | | | | (host 'a', dbname 'b') | @@ -324,7 +324,7 @@ CREATE SERVER t1 FOREIGN DATA WRAPPER foo; RESET ROLE; \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+---------------------------+----------------------+-------------------+--------+---------+-----------------------------------+------------- s1 | regress_foreign_data_user | foo | | | | | s2 | regress_foreign_data_user | foo | | | | (host 'a', dbname 'b') | @@ -348,7 +348,7 @@ SET ROLE regress_test_role; CREATE SERVER t2 FOREIGN DATA WRAPPER foo; \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+---------------------------+----------------------+-------------------+--------+---------+-----------------------------------+------------- s1 | regress_foreign_data_user | foo | | | | | s2 | regress_foreign_data_user | foo | | | | (host 'a', dbname 'b') | @@ -378,7 +378,7 @@ GRANT USAGE ON FOREIGN SERVER s1 TO regress_test_role; GRANT USAGE ON FOREIGN SERVER s6 TO regress_test_role2 WITH GRANT OPTION; \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+---------------------------+----------------------+-------------------------------------------------------+--------+---------+-----------------------------------+------------- s1 | regress_foreign_data_user | foo | regress_foreign_data_user=U/regress_foreign_data_user+| | 1.0 | (servername 's1') | | | | regress_test_role=U/regress_foreign_data_user | | | | @@ -429,7 +429,7 @@ DETAIL: owner of server s1 privileges for foreign-data wrapper foo \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description ------+---------------------------+----------------------+-------------------------------------------------------+--------+---------+--------------------------------------+------------- s1 | regress_test_indirect | foo | regress_test_indirect=U/regress_test_indirect | | 1.1 | (servername 's1') | s2 | regress_foreign_data_user | foo | | | 1.1 | (host 'a', dbname 'b') | @@ -447,7 +447,7 @@ privileges for foreign-data wrapper foo ALTER SERVER s8 RENAME to s8new; \des+ List of foreign servers - Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW options | Description -------+---------------------------+----------------------+-------------------------------------------------------+--------+---------+--------------------------------------+------------- s1 | regress_test_indirect | foo | regress_test_indirect=U/regress_test_indirect | | 1.1 | (servername 's1') | s2 | regress_foreign_data_user | foo | | | 1.1 | (host 'a', dbname 'b') | @@ -615,7 +615,7 @@ ALTER USER MAPPING FOR public SERVER t1 OPTIONS (ADD modified '1'); RESET ROLE; \deu+ List of user mappings - Server | User name | FDW Options + Server | User name | FDW options --------+---------------------------+---------------------------------- s4 | public | ("this mapping" 'is public') s4 | regress_foreign_data_user | @@ -709,7 +709,7 @@ COMMENT ON FOREIGN TABLE ft1 IS 'ft1'; COMMENT ON COLUMN ft1.c1 IS 'ft1.c1'; \d+ ft1 Foreign table "public.ft1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+--------------------------------+----------+--------------+------------- c1 | integer | | not null | | ("param 1" 'val1') | plain | | ft1.c1 c2 | text | | | | (param2 'val2', param3 'val3') | extended | | @@ -718,11 +718,11 @@ Check constraints: "ft1_c2_check" CHECK (c2 <> ''::text) "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') \det+ List of foreign tables - Schema | Table | Server | FDW Options | Description + Schema | Table | Server | FDW options | Description --------+-------+--------+-------------------------------------------------+------------- public | ft1 | s0 | (delimiter ',', quote '"', "be quoted" 'value') | ft1 (1 row) @@ -764,7 +764,7 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STATISTICS -1; ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STORAGE PLAIN; \d+ ft1 Foreign table "public.ft1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+--------------------------------+----------+--------------+------------- c1 | integer | | not null | | ("param 1" 'val1') | plain | 10000 | c2 | text | | | | (param2 'val2', param3 'val3') | extended | | @@ -780,7 +780,7 @@ Check constraints: "ft1_c2_check" CHECK (c2 <> ''::text) "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') -- can't change the column type if it's used elsewhere CREATE TABLE use_ft1_column_type (x ft1); @@ -814,7 +814,7 @@ ALTER FOREIGN TABLE foreign_schema.ft1 RENAME c1 TO foreign_column_1; ALTER FOREIGN TABLE foreign_schema.ft1 RENAME TO foreign_table_1; \d foreign_schema.foreign_table_1 Foreign table "foreign_schema.foreign_table_1" - Column | Type | Collation | Nullable | Default | FDW Options + Column | Type | Collation | Nullable | Default | FDW options ------------------+---------+-----------+----------+---------+-------------------------------- foreign_column_1 | integer | | not null | | ("param 1" 'val1') c2 | text | | | | (param2 'val2', param3 'val3') @@ -829,7 +829,7 @@ Check constraints: "ft1_c2_check" CHECK (c2 <> ''::text) "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date) Server: s0 -FDW Options: (quote '~', "be quoted" 'value', escape '@') +FDW options: (quote '~', "be quoted" 'value', escape '@') -- alter noexisting table ALTER FOREIGN TABLE IF EXISTS doesnt_exist_ft1 ADD COLUMN c4 integer; @@ -1208,7 +1208,7 @@ GRANT USAGE ON FOREIGN SERVER s10 TO regress_unprivileged_role; -- owner of server can see option fields \deu+ List of user mappings - Server | User name | FDW Options + Server | User name | FDW options --------+---------------------------+------------------- s10 | public | ("user" 'secret') s4 | regress_foreign_data_user | @@ -1224,7 +1224,7 @@ RESET ROLE; -- superuser can see option fields \deu+ List of user mappings - Server | User name | FDW Options + Server | User name | FDW options --------+---------------------------+--------------------- s10 | public | ("user" 'secret') s4 | regress_foreign_data_user | @@ -1240,7 +1240,7 @@ RESET ROLE; SET ROLE regress_unprivileged_role; \deu+ List of user mappings - Server | User name | FDW Options + Server | User name | FDW options --------+---------------------------+------------- s10 | public | s4 | regress_foreign_data_user | @@ -1318,13 +1318,13 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 DROP FOREIGN TABLE ft2; @@ -1343,13 +1343,13 @@ CREATE FOREIGN TABLE ft2 ( ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') ALTER FOREIGN TABLE ft2 INHERIT pt1; \d+ pt1 @@ -1363,13 +1363,13 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 CREATE TABLE ct3() INHERITS(ft2); @@ -1384,13 +1384,13 @@ NOTICE: merging column "c2" with inherited definition NOTICE: merging column "c3" with inherited definition \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 Child tables: ct3, ft3 @@ -1406,7 +1406,7 @@ Inherits: ft2 \d+ ft3 Foreign table "public.ft3" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1436,7 +1436,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1447,7 +1447,7 @@ Child tables: ft2 c7 | integer | | not null | | | plain | | c8 | integer | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 Child tables: ct3, ft3 @@ -1468,7 +1468,7 @@ Inherits: ft2 \d+ ft3 Foreign table "public.ft3" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1510,7 +1510,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | 10000 | c2 | text | | | | | extended | | @@ -1521,7 +1521,7 @@ Child tables: ft2 c7 | integer | | | | | plain | | c8 | text | | | | | external | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 Child tables: ct3, ft3 @@ -1543,13 +1543,13 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | 10000 | c2 | text | | | | | extended | | c3 | date | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 Child tables: ct3, ft3 @@ -1583,7 +1583,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | 10000 | c2 | text | | | | | extended | | @@ -1591,7 +1591,7 @@ Child tables: ft2 Check constraints: "pt1chk2" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 Child tables: ct3, ft3 @@ -1630,7 +1630,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1638,7 +1638,7 @@ Child tables: ft2 Check constraints: "pt1chk2" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 -- drop constraints recursively @@ -1660,7 +1660,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1669,7 +1669,7 @@ Check constraints: "pt1chk2" CHECK (c2 <> ''::text) "pt1chk3" CHECK (c2 <> ''::text) NOT VALID Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 -- VALIDATE CONSTRAINT need do nothing on foreign tables @@ -1687,7 +1687,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1696,7 +1696,7 @@ Check constraints: "pt1chk2" CHECK (c2 <> ''::text) "pt1chk3" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 -- OID system column @@ -1715,7 +1715,7 @@ Has OIDs: yes \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1724,7 +1724,7 @@ Check constraints: "pt1chk2" CHECK (c2 <> ''::text) "pt1chk3" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 Has OIDs: yes @@ -1744,7 +1744,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1753,7 +1753,7 @@ Check constraints: "pt1chk2" CHECK (c2 <> ''::text) "pt1chk3" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 -- changes name of an attribute recursively @@ -1775,7 +1775,7 @@ Child tables: ft2 \d+ ft2 Foreign table "public.ft2" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- f1 | integer | | not null | | | plain | | f2 | text | | | | | extended | | @@ -1784,7 +1784,7 @@ Check constraints: "f2_check" CHECK (f2 <> ''::text) "pt1chk2" CHECK (f2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: pt1 -- TRUNCATE doesn't work on foreign tables, either directly or recursively @@ -1838,7 +1838,7 @@ Partitions: pt2_1 FOR VALUES IN (1) \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1846,7 +1846,7 @@ Partitions: pt2_1 FOR VALUES IN (1) Partition of: pt2 FOR VALUES IN (1) Partition constraint: ((c1 IS NOT NULL) AND (c1 = ANY (ARRAY[1]))) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') -- partition cannot have additional columns DROP FOREIGN TABLE pt2_1; @@ -1858,14 +1858,14 @@ CREATE FOREIGN TABLE pt2_1 ( ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+--------------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | c4 | character(1) | | | | | extended | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') ALTER TABLE pt2 ATTACH PARTITION pt2_1 FOR VALUES IN (1); -- ERROR ERROR: table "pt2_1" contains column "c4" not found in parent "pt2" @@ -1887,13 +1887,13 @@ CREATE FOREIGN TABLE pt2_1 ( ) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value'); \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') -- no attach partition validation occurs for foreign tables ALTER TABLE pt2 ATTACH PARTITION pt2_1 FOR VALUES IN (1); @@ -1909,7 +1909,7 @@ Partitions: pt2_1 FOR VALUES IN (1) \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1917,7 +1917,7 @@ Partitions: pt2_1 FOR VALUES IN (1) Partition of: pt2 FOR VALUES IN (1) Partition constraint: ((c1 IS NOT NULL) AND (c1 = ANY (ARRAY[1]))) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') -- cannot add column to a partition ALTER TABLE pt2_1 ADD c4 char; @@ -1937,7 +1937,7 @@ Partitions: pt2_1 FOR VALUES IN (1) \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1947,7 +1947,7 @@ Partition constraint: ((c1 IS NOT NULL) AND (c1 = ANY (ARRAY[1]))) Check constraints: "p21chk" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') -- cannot drop inherited NOT NULL constraint from a partition ALTER TABLE pt2_1 ALTER c1 DROP NOT NULL; @@ -1966,7 +1966,7 @@ Partition key: LIST (c1) \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | @@ -1974,7 +1974,7 @@ Partition key: LIST (c1) Check constraints: "p21chk" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') ALTER TABLE pt2 ATTACH PARTITION pt2_1 FOR VALUES IN (1); -- ERROR ERROR: column "c2" in child table must be marked NOT NULL @@ -1995,7 +1995,7 @@ Check constraints: \d+ pt2_1 Foreign table "public.pt2_1" - Column | Type | Collation | Nullable | Default | FDW Options | Storage | Stats target | Description + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description --------+---------+-----------+----------+---------+-------------+----------+--------------+------------- c1 | integer | | not null | | | plain | | c2 | text | | not null | | | extended | | @@ -2003,7 +2003,7 @@ Check constraints: Check constraints: "p21chk" CHECK (c2 <> ''::text) Server: s0 -FDW Options: (delimiter ',', quote '"', "be quoted" 'value') +FDW options: (delimiter ',', quote '"', "be quoted" 'value') ALTER TABLE pt2 ATTACH PARTITION pt2_1 FOR VALUES IN (1); -- ERROR ERROR: child table is missing constraint "pt2chk1" -- cgit v1.2.3