|
62 | 62 | #include "access/htup_details.h"
|
63 | 63 | #include "catalog/indexing.h"
|
64 | 64 | #include "catalog/namespace.h"
|
| 65 | +#include "catalog/pg_constraint_fn.h" |
65 | 66 | #include "pglogical_output/hooks.h"
|
66 | 67 | #include "parser/analyze.h"
|
67 | 68 | #include "parser/parse_relation.h"
|
@@ -2143,7 +2144,9 @@ static void
|
2143 | 2144 | MtmLockCluster(void)
|
2144 | 2145 | {
|
2145 | 2146 | timestamp_t delay = MIN_WAIT_TIMEOUT;
|
2146 |
| - Assert(!MtmClusterLocked); |
| 2147 | + if (MtmClusterLocked) { |
| 2148 | + MtmUnlockCluster(); |
| 2149 | + } |
2147 | 2150 | MtmLock(LW_EXCLUSIVE);
|
2148 | 2151 | if (BIT_CHECK(Mtm->originLockNodeMask, MtmNodeId-1)) {
|
2149 | 2152 | elog(ERROR, "There is already pending exclusive lock");
|
@@ -4876,8 +4879,8 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
|
4876 | 4879 | bool skipCommand = false;
|
4877 | 4880 | bool executed = false;
|
4878 | 4881 |
|
4879 |
| - MTM_LOG3("%d: Process utility statement tag=%d, context=%d, issubtrans=%d, query=%s", |
4880 |
| - MyProcPid, nodeTag(parsetree), context, IsSubTransaction(), queryString); |
| 4882 | + MTM_LOG2("%d: Process utility statement tag=%d, context=%d, issubtrans=%d, creating_extension=%d, query=%s", |
| 4883 | + MyProcPid, nodeTag(parsetree), context, IsSubTransaction(), creating_extension, queryString); |
4881 | 4884 | switch (nodeTag(parsetree))
|
4882 | 4885 | {
|
4883 | 4886 | case T_TransactionStmt:
|
@@ -5130,24 +5133,14 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
|
5130 | 5133 | break;
|
5131 | 5134 | }
|
5132 | 5135 |
|
5133 |
| - /* XXX: dirty. Clear on new tx */ |
5134 |
| - /* Some "black magic here":( We want to avoid redundant execution of utility statement by ProcessUtilitySlow (which is done with PROCESS_UTILITY_SUBCOMMAND). |
5135 |
| - * But if we allow only PROCESS_UTILITY_TOPLEVEL context, then we will not replicated DDL inside dynamic queries in plpgsql functions (see https://jira.postgrespro.ru/browse/CORE-526). |
5136 |
| - * If we disable only PROCESS_UTILITY_SUBCOMMAND, then we will get problems with "create extension" which is executed also in PROCESS_UTILITY_QUERY context. |
5137 |
| - * So workaround at this moment is to treat extension as special case. |
5138 |
| - * TODO: try to find right solution and rewrite this dummy check. |
5139 |
| - */ |
5140 |
| - if (!skipCommand && (context == PROCESS_UTILITY_TOPLEVEL || (context == PROCESS_UTILITY_QUERY && !creating_extension) || MtmUtilityProcessedInXid != GetCurrentTransactionId())) |
5141 |
| - MtmUtilityProcessedInXid = InvalidTransactionId; |
5142 |
| - |
5143 |
| - if (!skipCommand && !MtmTx.isReplicated && (MtmUtilityProcessedInXid == InvalidTransactionId)) { |
| 5136 | + if (!skipCommand && !MtmTx.isReplicated && (context == PROCESS_UTILITY_TOPLEVEL || MtmUtilityProcessedInXid != GetCurrentTransactionId())) |
| 5137 | + { |
5144 | 5138 | MtmUtilityProcessedInXid = GetCurrentTransactionId();
|
5145 |
| - |
5146 |
| - if (context == PROCESS_UTILITY_TOPLEVEL) |
| 5139 | + if (context == PROCESS_UTILITY_TOPLEVEL) { |
5147 | 5140 | MtmProcessDDLCommand(queryString, true);
|
5148 |
| - else |
| 5141 | + } else { |
5149 | 5142 | MtmProcessDDLCommand(ActivePortal->sourceText, true);
|
5150 |
| - |
| 5143 | + } |
5151 | 5144 | executed = true;
|
5152 | 5145 | }
|
5153 | 5146 |
|
@@ -5177,6 +5170,26 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
|
5177 | 5170 | {
|
5178 | 5171 | MtmFinishDDLCommand();
|
5179 | 5172 | }
|
| 5173 | + if (nodeTag(parsetree) == T_CreateStmt) |
| 5174 | + { |
| 5175 | + CreateStmt* create = (CreateStmt*)parsetree; |
| 5176 | + Oid relid = RangeVarGetRelid(create->relation, NoLock, true); |
| 5177 | + if (relid != InvalidOid) { |
| 5178 | + Oid constraint_oid; |
| 5179 | + Bitmapset* pk = get_primary_key_attnos(relid, true, &constraint_oid); |
| 5180 | + if (pk == NULL && !MtmVolksWagenMode) { |
| 5181 | + elog(WARNING, |
| 5182 | + MtmIgnoreTablesWithoutPk |
| 5183 | + ? "Table %s.%s without primary will not be replicated" |
| 5184 | + : "Updates and deletes of table %s.%s without primary will not be replicated", |
| 5185 | + create->relation->schemaname ? create->relation->schemaname : "public", |
| 5186 | + create->relation->relname); |
| 5187 | + } |
| 5188 | + } |
| 5189 | + } |
| 5190 | + if (context == PROCESS_UTILITY_TOPLEVEL) { |
| 5191 | + MtmUtilityProcessedInXid = InvalidTransactionId; |
| 5192 | + } |
5180 | 5193 | }
|
5181 | 5194 |
|
5182 | 5195 | static void
|
|
0 commit comments