Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdf3b681

Browse files
committed
Add support for nesting temporary namespaces for ATX transactions.
PGPRO-3882
1 parent55754e0 commitdf3b681

File tree

8 files changed

+169
-33
lines changed

8 files changed

+169
-33
lines changed

‎expected/regression_ee.diff

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,14 +570,43 @@ diff ../../../src/test/regress/expected/rowsecurity.out ../tmp_check/regress_out
570570
diff ../../../src/test/regress/expected/atx.out ../tmp_check/regress_outdir/results/atx.out
571571
--- ../../../src/test/regress/expected/atx.outCENSORED
572572
+++ ../tmp_check/regress_outdir/results/atx.outCENSORED
573-
@@ -1143,6 +1143,7 @@
573+
@@ -1139,6 +1139,7 @@
574574
RESET client_min_messages;
575575
create database regression_atx_test_database;
576576
ALTER DATABASE "regression_atx_test_database" SET lc_messages TO 'C';
577577
+ERROR: [MTM] failed to prepare transaction at peer node
578578
\c regression_atx_test_database
579579
create table atx_test as select 1 as id;
580580
begin;
581+
diff ../../../src/test/regress/expected/atx4.out ../tmp_check/regress_outdir/results/atx4.out
582+
--- ../../../src/test/regress/expected/atx4.outCENSORED
583+
+++ ../tmp_check/regress_outdir/results/atx4.outCENSORED
584+
@@ -142,8 +142,10 @@
585+
(1 row)
586+
587+
commit autonomous;
588+
+ERROR: [MTM] failed to prepare transaction at peer node
589+
-- Multimaster: t2 table will not be created due to pg_temp_N not found on replicas
590+
commit;
591+
+WARNING: there is no transaction in progress
592+
begin;
593+
-- create temp table in top level temptable but abort
594+
begin autonomous;
595+
@@ -213,11 +215,9 @@
596+
commit;
597+
-- Multimaster: t2 were not created
598+
select * from t2;
599+
- a
600+
-----
601+
- hi
602+
-(1 row)
603+
-
604+
+ERROR: relation "t2" does not exist
605+
+LINE 1: select * from t2;
606+
+ ^
607+
select * from t3;
608+
ERROR: relation "t3" does not exist
609+
LINE 1: select * from t3;
581610
diff ../../../src/test/regress/expected/atx5.out ../tmp_check/regress_outdir/results/atx5.out
582611
--- ../../../src/test/regress/expected/atx5.outCENSORED
583612
+++ ../tmp_check/regress_outdir/results/atx5.outCENSORED

‎multimaster--1.0.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ CREATE FUNCTION mtm.set_temp_schema(nsp text) RETURNS void
195195
AS'MODULE_PATHNAME','mtm_set_temp_schema'
196196
LANGUAGE C;
197197

198+
CREATEFUNCTIONmtm.set_temp_schema(nsptext, force bool) RETURNS void
199+
AS'MODULE_PATHNAME','mtm_set_temp_schema'
200+
LANGUAGE C;
201+
198202
CREATETABLEmtm.local_tables(
199203
rel_schema name,
200204
rel_name name,

‎src/commit.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static bool inside_mtm_begin;
4646
staticMtmConfig*mtm_cfg;
4747

4848
MtmCurrentTransMtmTx;
49+
intMtmTxAtxLevel=0;
4950

5051
/* holds state defining cleanup actions in case of failure during commit */
5152
staticstructMtmCommitState
@@ -400,6 +401,9 @@ MtmTwoPhaseCommit(void)
400401
StartTransactionCommand();
401402
}
402403

404+
if (MtmTxAtxLevel>0)
405+
temp_schema_reset(true);
406+
403407
/* prepare for cleanup */
404408
mtm_commit_state.gtx=NULL;
405409
mtm_commit_state.inside_commit_sequence= true;

‎src/ddl.c

Lines changed: 109 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ MtmDDLInProgress DDLApplyInProgress;
9494

9595
staticcharMtmTempSchema[NAMEDATALEN];
9696
staticboolTempDropRegistered;
97+
staticintTempDropAtxLevel;
9798

9899
staticvoidconst*MtmDDLStatement;
99100

@@ -247,9 +248,11 @@ temp_schema_reset_all(int my_node_id)
247248
"nsp record; "
248249
"begin "
249250
"reset session_authorization; "
250-
"for nsp in select nspname from pg_namespace where nspname ~ '^mtm_tmp_%d_.*' loop "
251+
"for nsp in select nspname from pg_namespace where "
252+
" nspname ~ '^mtm_tmp_%d_.*' and"
253+
" nspname !~ '_toast$' loop "
251254
" perform mtm.set_temp_schema(nsp.nspname); "
252-
" execute format('drop schema if exists %%I cascade',format('%%s_toast',nsp.nspname)); "
255+
" execute format('drop schema if exists %%I cascade', nsp.nspname||'_toast'); "
253256
" execute format('drop schema if exists %%I cascade', nsp.nspname); "
254257
"end loop; "
255258
"end $$; ",
@@ -258,26 +261,27 @@ temp_schema_reset_all(int my_node_id)
258261
}
259262

260263
/* Drop temp schemas on peer nodes */
261-
staticvoid
262-
temp_schema_reset(void)
264+
void
265+
temp_schema_reset(booltransactional)
263266
{
264267
Assert(TempDropRegistered);
268+
Assert(TempDropAtxLevel==MtmTxAtxLevel);
265269

266270
/*
267271
* reset session_authorization restores permissions if previous ddl
268272
* dropped them; set_temp_schema allows us to see temporary objects,
269273
* otherwise they can't be dropped
270274
*
271-
*Itis important to run it as 'V', otherwise it might interfere with
272-
*later (if drop is due to DISCARD) or earlier command using the schema.
275+
*If dropisdue to DISCARD, it isimportant to run it as 'V', otherwise
276+
*it might interfere with later or earlier command using the schema.
273277
*/
274278
MtmProcessDDLCommand(
275279
psprintf("RESET session_authorization; "
276-
"select mtm.set_temp_schema('%s'); "
280+
"select mtm.set_temp_schema('%s', false); "
277281
"DROP SCHEMA IF EXISTS %s_toast CASCADE; "
278282
"DROP SCHEMA IF EXISTS %s CASCADE;",
279283
MtmTempSchema,MtmTempSchema,MtmTempSchema),
280-
false,
284+
transactional,
281285
false
282286
);
283287
MtmFinishDDLCommand();
@@ -290,52 +294,127 @@ temp_schema_at_exit(int status, Datum arg)
290294
Assert(TempDropRegistered);
291295
AbortOutOfAnyTransaction();
292296
StartTransactionCommand();
293-
temp_schema_reset();
297+
for (;MtmTxAtxLevel >=0;MtmTxAtxLevel--)
298+
{
299+
temp_schema_init();
300+
temp_schema_reset(false);
301+
}
294302
CommitTransactionCommand();
295303
}
296304

297305
/* Register cleanup callback and generate temp schema name */
298-
staticvoid
306+
void
299307
temp_schema_init(void)
300308
{
301309
if (!TempDropRegistered)
302310
{
303-
char*temp_schema;
304-
305-
/*
306-
* NB: namespace.c:isMtmTemp() assumes 'mtm_tmp_' prefix for mtm temp
307-
* tables to defuse autovacuum.
308-
*/
309-
temp_schema=psprintf("mtm_tmp_%d_%d",
310-
Mtm->my_node_id,MyBackendId);
311-
memcpy(&MtmTempSchema,temp_schema,strlen(temp_schema)+1);
312-
before_shmem_exit(temp_schema_at_exit, (Datum)0);
313311
TempDropRegistered= true;
314-
pfree(temp_schema);
312+
before_shmem_exit(temp_schema_at_exit, (Datum)0);
313+
}
314+
if (MtmTxAtxLevel==0)
315+
snprintf(MtmTempSchema,sizeof(MtmTempSchema),
316+
"mtm_tmp_%d_%d",Mtm->my_node_id,MyBackendId);
317+
else
318+
snprintf(MtmTempSchema,sizeof(MtmTempSchema),
319+
"mtm_tmp_%d_%d_%d",Mtm->my_node_id,MyBackendId,MtmTxAtxLevel);
320+
TempDropAtxLevel=MtmTxAtxLevel;
321+
}
322+
323+
/*
324+
* temp_schema_valid check format of temp schema name.
325+
* Namespace name should be either mtm_tmp_\d+_\d+ or
326+
* mtm_tmp_\d+_\d+_\d+ for non-zero atx level.
327+
*/
328+
staticbool
329+
temp_schema_valid(constchar*temp_namespace,constchar**atx_level)
330+
{
331+
constchar*c;
332+
constintmtm_tmp_len=strlen("mtm_tmp_");
333+
intunderscores=0;
334+
boolneed_digit= true;
335+
boolvalid= true;
336+
337+
*atx_level=NULL;
338+
if (strlen(temp_namespace)+strlen("_toast")+1>NAMEDATALEN)
339+
valid= false;
340+
elseif(strncmp(temp_namespace,"mtm_tmp_",mtm_tmp_len)!=0)
341+
valid= false;
342+
for (c=temp_namespace+mtm_tmp_len;*c!=0&&valid;c++)
343+
{
344+
if (!need_digit&&*c=='_')
345+
{
346+
underscores++;
347+
if (underscores==2)
348+
*atx_level=c;
349+
need_digit= true;
350+
}
351+
elseif ((unsigned)*c-'0' <='9'-'0')
352+
need_digit= false;
353+
else
354+
valid= false;
315355
}
356+
if (need_digit||underscores<1||underscores>2)
357+
valid= false;
358+
#ifndefPGPRO_EE
359+
if (underscores==2)
360+
valid= false;
361+
#endif
362+
363+
returnvalid;
316364
}
317365

318366
Datum
319367
mtm_set_temp_schema(PG_FUNCTION_ARGS)
320368
{
321369
char*temp_namespace=text_to_cstring(PG_GETARG_TEXT_P(0));
322-
char*temp_toast_namespace=psprintf("%s_toast",temp_namespace);
323-
Oidnsp_oid;
324-
Oidtoast_nsp_oid;
370+
boolforce=PG_NARGS()>1 ?PG_GETARG_BOOL(1) : true;
371+
chartemp_toast_namespace[NAMEDATALEN]= {0};
372+
Oidnsp_oid=InvalidOid;
373+
Oidtoast_nsp_oid=InvalidOid;
374+
constchar*atx_level_start=NULL;
375+
#ifdefPGPRO_EE
376+
chartop_temp_namespace[NAMEDATALEN]= {0};
377+
Oidtop_nsp_oid=InvalidOid;
378+
Oidtop_toast_nsp_oid=InvalidOid;
379+
#endif
380+
381+
if (!temp_schema_valid(temp_namespace,&atx_level_start))
382+
mtm_log(ERROR,"mtm_set_temp_schema: wrong namespace name '%s'",
383+
temp_namespace);
325384

326-
if (!SearchSysCacheExists1(NAMESPACENAME,PointerGetDatum(temp_namespace)))
385+
snprintf(temp_toast_namespace,NAMEDATALEN,"%s_toast",temp_namespace);
386+
if (SearchSysCacheExists1(NAMESPACENAME,PointerGetDatum(temp_namespace)))
387+
{
388+
nsp_oid=get_namespace_oid(temp_namespace, false);
389+
toast_nsp_oid=get_namespace_oid(temp_toast_namespace, false);
390+
}
391+
elseif (force)
327392
{
328393
nsp_oid=NamespaceCreate(temp_namespace,BOOTSTRAP_SUPERUSERID, true);
329394
toast_nsp_oid=NamespaceCreate(temp_toast_namespace,BOOTSTRAP_SUPERUSERID, true);
330395
CommandCounterIncrement();
331396
}
332-
else
397+
398+
#ifdefPGPRO_EE
399+
if (atx_level_start!=NULL)
333400
{
334-
nsp_oid=get_namespace_oid(temp_namespace, false);
335-
toast_nsp_oid=get_namespace_oid(temp_toast_namespace, false);
401+
memcpy(top_temp_namespace,temp_namespace,atx_level_start-temp_namespace);
402+
403+
if (SearchSysCacheExists1(NAMESPACENAME,PointerGetDatum(top_temp_namespace)))
404+
{
405+
top_nsp_oid=get_namespace_oid(top_temp_namespace, false);
406+
strlcat(top_temp_namespace,"_toast",NAMEDATALEN);
407+
top_toast_nsp_oid=get_namespace_oid(top_temp_namespace, false);
408+
}
336409
}
337410

338-
SetTempNamespaceState(nsp_oid,toast_nsp_oid);
411+
SetTempNamespaceForMultimaster();
412+
SetTempNamespaceStateEx(nsp_oid,toast_nsp_oid,
413+
top_nsp_oid,top_toast_nsp_oid,
414+
atx_level_start!=NULL);
415+
#else
416+
SetTempNamespace(nsp_oid,toast_nsp_oid);
417+
#endif
339418
PG_RETURN_VOID();
340419
}
341420

@@ -1030,7 +1109,7 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString,
10301109
{
10311110
/* nothing to do if temp schema wasn't created at all */
10321111
if (TempDropRegistered)
1033-
temp_schema_reset();
1112+
temp_schema_reset(false);
10341113
SkipCommand(true);
10351114
MtmGucDiscard();
10361115
}

‎src/include/ddl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ extern MtmDDLInProgress DDLApplyInProgress;
3333
externvoidMtmDDLReplicationInit(void);
3434
externvoidMtmDDLReplicationShmemStartup(void);
3535
externvoidtemp_schema_reset_all(intmy_node_id);
36+
externvoidtemp_schema_reset(booltransactional);
37+
externvoidtemp_schema_init(void);
3638
externboolMtmIsRelationLocal(Relationrel);
3739
externvoidMtmDDLResetStatement(void);
3840
externvoidMtmApplyDDLMessage(constchar*messageBody,booltransactional);

‎src/include/multimaster.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ extern MtmShared *Mtm;
216216

217217
/* XXX: to delete */
218218
externMtmCurrentTransMtmTx;
219+
externintMtmTxAtxLevel;
219220
externMemoryContextMtmApplyContext;
220221

221222
/* bgworker identities */

‎src/multimaster.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,8 @@ MtmSuspendTransaction(void)
369369
MtmCurrentTrans*ctx=malloc(sizeof(MtmCurrentTrans));
370370

371371
*ctx=MtmTx;
372+
MtmTxAtxLevel++;
373+
temp_schema_init();
372374
CallXactCallbacks(XACT_EVENT_START);
373375
returnctx;
374376
}
@@ -378,6 +380,8 @@ MtmResumeTransaction(void *ctx)
378380
{
379381
MtmTx=*(MtmCurrentTrans*)ctx;
380382
free(ctx);
383+
MtmTxAtxLevel--;
384+
temp_schema_init();
381385
}
382386
#endif
383387

‎src/state.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3920,6 +3920,7 @@ MtmMonitor(Datum arg)
39203920
*/
39213921
{
39223922
intrc;
3923+
uint64nfuncs;
39233924

39243925
StartTransactionCommand();
39253926
if (SPI_connect()!=SPI_OK_CONNECT)
@@ -3955,15 +3956,27 @@ MtmMonitor(Datum arg)
39553956
true,0);
39563957
if (rc<0||rc!=SPI_OK_SELECT)
39573958
mtm_log(ERROR,"Failed to query pg_proc");
3958-
if (SPI_processed==0)
3959+
nfuncs=SPI_processed;
3960+
if (nfuncs==0)
39593961
{
39603962
rc=SPI_execute("CREATE FUNCTION mtm.set_temp_schema(nsp text) RETURNS void "
39613963
"AS '$libdir/multimaster','mtm_set_temp_schema' "
39623964
"LANGUAGE C; ", false,0);
39633965
if (rc<0||rc!=SPI_OK_UTILITY)
39643966
mtm_log(ERROR,"Failed to create mtm.set_temp_schema()");
39653967

3966-
mtm_log(LOG,"Creating mtm.set_temp_schema()");
3968+
mtm_log(LOG,"Creating mtm.set_temp_schema(nsp)");
3969+
}
3970+
3971+
if (nfuncs <=1)
3972+
{
3973+
rc=SPI_execute("CREATE FUNCTION mtm.set_temp_schema(nsp text, force bool) RETURNS void "
3974+
"AS '$libdir/multimaster','mtm_set_temp_schema' "
3975+
"LANGUAGE C; ", false,0);
3976+
if (rc<0||rc!=SPI_OK_UTILITY)
3977+
mtm_log(ERROR,"Failed to create mtm.set_temp_schema()");
3978+
3979+
mtm_log(LOG,"Creating mtm.set_temp_schema(nsp, force)");
39673980
}
39683981

39693982
SPI_finish();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp