|
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_tdelay=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 | boolskipCommand= false; |
4877 | 4880 | boolexecuted= 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 | caseT_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 | +Oidrelid=RangeVarGetRelid(create->relation,NoLock, true); |
| 5177 | +if (relid!=InvalidOid) { |
| 5178 | +Oidconstraint_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 | staticvoid |
|