Skip to content

Commit 5343b8b

Browse files
committed
Check GTT indexes before query execution
1 parent f1f10a1 commit 5343b8b

File tree

41 files changed

+681
-100
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+681
-100
lines changed

contrib/pg_prewarm/pg_prewarm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ pg_prewarm(PG_FUNCTION_ARGS)
178178
for (block = first_block; block <= last_block; ++block)
179179
{
180180
CHECK_FOR_INTERRUPTS();
181-
smgrread(rel->rd_smgr, forkNumber, block, blockbuffer.data);
181+
smgrread(rel->rd_smgr, forkNumber, block, blockbuffer.data, false);
182182
++blocks_done;
183183
}
184184
}

src/backend/access/common/reloptions.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ static relopt_bool boolRelOpts[] =
158158
},
159159
true
160160
},
161+
/*
162+
* For global temp table only
163+
* use AccessExclusiveLock for ensure safety
164+
*/
165+
{
166+
{
167+
"on_commit_delete_rows",
168+
"global temp table on commit options",
169+
RELOPT_KIND_HEAP | RELOPT_KIND_PARTITIONED,
170+
ShareUpdateExclusiveLock
171+
},
172+
false
173+
},
161174
/* list terminator */
162175
{{NULL}}
163176
};
@@ -1486,6 +1499,8 @@ bytea *
14861499
default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
14871500
{
14881501
static const relopt_parse_elt tab[] = {
1502+
{"on_commit_delete_rows", RELOPT_TYPE_BOOL,
1503+
offsetof(StdRdOptions, on_commit_delete_rows)},
14891504
{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
14901505
{"autovacuum_enabled", RELOPT_TYPE_BOOL,
14911506
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
@@ -1586,13 +1601,17 @@ build_reloptions(Datum reloptions, bool validate,
15861601
bytea *
15871602
partitioned_table_reloptions(Datum reloptions, bool validate)
15881603
{
1604+
static const relopt_parse_elt tab[] = {
1605+
{"on_commit_delete_rows", RELOPT_TYPE_BOOL,
1606+
offsetof(StdRdOptions, on_commit_delete_rows)}
1607+
};
15891608
/*
15901609
* There are no options for partitioned tables yet, but this is able to do
15911610
* some validation.
15921611
*/
15931612
return (bytea *) build_reloptions(reloptions, validate,
15941613
RELOPT_KIND_PARTITIONED,
1595-
0, NULL, 0);
1614+
sizeof(StdRdOptions), tab, lengthof(tab));
15961615
}
15971616

15981617
/*

src/backend/access/heap/heapam_handler.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ heapam_relation_copy_data(Relation rel, const RelFileNode *newrnode)
670670
* init fork of an unlogged relation.
671671
*/
672672
if (rel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT ||
673+
rel->rd_rel->relpersistence == RELPERSISTENCE_SESSION ||
673674
(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
674675
forkNum == INIT_FORKNUM))
675676
log_smgrcreate(newrnode, forkNum);

src/backend/catalog/catalog.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,9 @@ GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
396396
case RELPERSISTENCE_TEMP:
397397
backend = BackendIdForTempRelations();
398398
break;
399+
case RELPERSISTENCE_SESSION:
400+
backend = BackendIdForSessionRelations();
401+
break;
399402
case RELPERSISTENCE_UNLOGGED:
400403
case RELPERSISTENCE_PERMANENT:
401404
backend = InvalidBackendId;

src/backend/catalog/index.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3707,7 +3707,7 @@ reindex_relation(Oid relid, int flags, int options)
37073707
if (flags & REINDEX_REL_FORCE_INDEXES_UNLOGGED)
37083708
persistence = RELPERSISTENCE_UNLOGGED;
37093709
else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
3710-
persistence = RELPERSISTENCE_PERMANENT;
3710+
persistence = rel->rd_rel->relpersistence == RELPERSISTENCE_SESSION ? RELPERSISTENCE_SESSION : RELPERSISTENCE_PERMANENT;
37113711
else
37123712
persistence = rel->rd_rel->relpersistence;
37133713

src/backend/catalog/storage.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ RelationCreateStorage(RelFileNode rnode, char relpersistence)
9292
backend = InvalidBackendId;
9393
needs_wal = false;
9494
break;
95+
case RELPERSISTENCE_SESSION:
96+
backend = BackendIdForSessionRelations();
97+
needs_wal = false;
98+
break;
9599
case RELPERSISTENCE_PERMANENT:
96100
backend = InvalidBackendId;
97101
needs_wal = true;
@@ -367,7 +371,7 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst,
367371
/* If we got a cancel signal during the copy of the data, quit */
368372
CHECK_FOR_INTERRUPTS();
369373

370-
smgrread(src, forkNum, blkno, buf.data);
374+
smgrread(src, forkNum, blkno, buf.data, false);
371375

372376
if (!PageIsVerified(page, blkno))
373377
ereport(ERROR,

src/backend/catalog/system_views.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,15 @@ LANGUAGE INTERNAL
13691369
STRICT STABLE PARALLEL SAFE
13701370
AS 'jsonb_path_query_first_tz';
13711371

1372+
1373+
--
1374+
-- Statistic for global temporary tables
13721375
--
1376+
1377+
CREATE VIEW pg_gtt_statistic AS
1378+
SELECT s.* from pg_class c,pg_gtt_statistic_for_relation(c.oid) s where c.relpersistence='s';
1379+
1380+
13731381
-- The default permissions for functions mean that anyone can execute them.
13741382
-- A number of functions shouldn't be executable by just anyone, but rather
13751383
-- than use explicit 'superuser()' checks in those functions, we use the GRANT

src/backend/commands/analyze.c

Lines changed: 106 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "commands/vacuum.h"
4141
#include "executor/executor.h"
4242
#include "foreign/fdwapi.h"
43+
#include "funcapi.h"
4344
#include "miscadmin.h"
4445
#include "nodes/nodeFuncs.h"
4546
#include "parser/parse_oper.h"
@@ -103,7 +104,7 @@ static int acquire_inherited_sample_rows(Relation onerel, int elevel,
103104
HeapTuple *rows, int targrows,
104105
double *totalrows, double *totaldeadrows);
105106
static void update_attstats(Oid relid, bool inh,
106-
int natts, VacAttrStats **vacattrstats);
107+
int natts, VacAttrStats **vacattrstats, bool is_global_temp);
107108
static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
108109
static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
109110

@@ -323,6 +324,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
323324
Oid save_userid;
324325
int save_sec_context;
325326
int save_nestlevel;
327+
bool is_global_temp = onerel->rd_rel->relpersistence == RELPERSISTENCE_SESSION;
326328

327329
if (inh)
328330
ereport(elevel,
@@ -586,14 +588,14 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
586588
* pg_statistic for columns we didn't process, we leave them alone.)
587589
*/
588590
update_attstats(RelationGetRelid(onerel), inh,
589-
attr_cnt, vacattrstats);
591+
attr_cnt, vacattrstats, is_global_temp);
590592

591593
for (ind = 0; ind < nindexes; ind++)
592594
{
593595
AnlIndexData *thisdata = &indexdata[ind];
594596

595597
update_attstats(RelationGetRelid(Irel[ind]), false,
596-
thisdata->attr_cnt, thisdata->vacattrstats);
598+
thisdata->attr_cnt, thisdata->vacattrstats, is_global_temp);
597599
}
598600

599601
/*
@@ -1456,7 +1458,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
14561458
* by taking a self-exclusive lock on the relation in analyze_rel().
14571459
*/
14581460
static void
1459-
update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
1461+
update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats, bool is_global_temp)
14601462
{
14611463
Relation sd;
14621464
int attno;
@@ -1558,30 +1560,42 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
15581560
}
15591561
}
15601562

1561-
/* Is there already a pg_statistic tuple for this attribute? */
1562-
oldtup = SearchSysCache3(STATRELATTINH,
1563-
ObjectIdGetDatum(relid),
1564-
Int16GetDatum(stats->attr->attnum),
1565-
BoolGetDatum(inh));
1566-
1567-
if (HeapTupleIsValid(oldtup))
1563+
if (is_global_temp)
15681564
{
1569-
/* Yes, replace it */
1570-
stup = heap_modify_tuple(oldtup,
1571-
RelationGetDescr(sd),
1572-
values,
1573-
nulls,
1574-
replaces);
1575-
ReleaseSysCache(oldtup);
1576-
CatalogTupleUpdate(sd, &stup->t_self, stup);
1565+
stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
1566+
InsertSysCache(STATRELATTINH,
1567+
ObjectIdGetDatum(relid),
1568+
Int16GetDatum(stats->attr->attnum),
1569+
BoolGetDatum(inh),
1570+
0,
1571+
stup);
15771572
}
15781573
else
15791574
{
1580-
/* No, insert new tuple */
1581-
stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
1582-
CatalogTupleInsert(sd, stup);
1583-
}
1575+
/* Is there already a pg_statistic tuple for this attribute? */
1576+
oldtup = SearchSysCache3(STATRELATTINH,
1577+
ObjectIdGetDatum(relid),
1578+
Int16GetDatum(stats->attr->attnum),
1579+
BoolGetDatum(inh));
15841580

1581+
if (HeapTupleIsValid(oldtup))
1582+
{
1583+
/* Yes, replace it */
1584+
stup = heap_modify_tuple(oldtup,
1585+
RelationGetDescr(sd),
1586+
values,
1587+
nulls,
1588+
replaces);
1589+
ReleaseSysCache(oldtup);
1590+
CatalogTupleUpdate(sd, &stup->t_self, stup);
1591+
}
1592+
else
1593+
{
1594+
/* No, insert new tuple */
1595+
stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
1596+
CatalogTupleInsert(sd, stup);
1597+
}
1598+
}
15851599
heap_freetuple(stup);
15861600
}
15871601

@@ -2890,3 +2904,72 @@ analyze_mcv_list(int *mcv_counts,
28902904
}
28912905
return num_mcv;
28922906
}
2907+
2908+
PG_FUNCTION_INFO_V1(pg_gtt_statistic_for_relation);
2909+
2910+
typedef struct
2911+
{
2912+
int staattnum;
2913+
bool stainherit;
2914+
} PgTempStatIteratorCtx;
2915+
2916+
Datum
2917+
pg_gtt_statistic_for_relation(PG_FUNCTION_ARGS)
2918+
{
2919+
Oid starelid = PG_GETARG_OID(0);
2920+
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2921+
Tuplestorestate *tupstore;
2922+
MemoryContext per_query_ctx;
2923+
MemoryContext oldcontext;
2924+
TupleDesc tupdesc;
2925+
bool stainherit = false;
2926+
2927+
/* check to see if caller supports us returning a tuplestore */
2928+
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2929+
elog(ERROR, "return type must be a row type");
2930+
2931+
/* check to see if caller supports us returning a tuplestore */
2932+
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
2933+
ereport(ERROR,
2934+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2935+
errmsg("set-valued function called in context that cannot accept a set")));
2936+
if (!(rsinfo->allowedModes & SFRM_Materialize))
2937+
ereport(ERROR,
2938+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2939+
errmsg("materialize mode required, but it is not " \
2940+
"allowed in this context")));
2941+
2942+
/* Build tuplestore to hold the result rows */
2943+
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
2944+
oldcontext = MemoryContextSwitchTo(per_query_ctx);
2945+
2946+
/* Build a tuple descriptor for our result type */
2947+
2948+
tupstore = tuplestore_begin_heap(true, false, work_mem);
2949+
rsinfo->returnMode = SFRM_Materialize;
2950+
rsinfo->setResult = tupstore;
2951+
rsinfo->setDesc = tupdesc;
2952+
2953+
do
2954+
{
2955+
int staattnum = 0;
2956+
while (true)
2957+
{
2958+
HeapTuple statup = SearchSysCacheCopy3(STATRELATTINH,
2959+
ObjectIdGetDatum(starelid),
2960+
Int16GetDatum(++staattnum),
2961+
BoolGetDatum(stainherit));
2962+
if (statup != NULL)
2963+
tuplestore_puttuple(tupstore, statup);
2964+
else
2965+
break;
2966+
}
2967+
stainherit = !stainherit;
2968+
} while (stainherit);
2969+
2970+
MemoryContextSwitchTo(oldcontext);
2971+
2972+
tuplestore_donestoring(tupstore);
2973+
2974+
return (Datum) 0;
2975+
}

src/backend/commands/cluster.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,13 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
391391
errmsg("cannot vacuum temporary tables of other sessions")));
392392
}
393393

394+
/* not support cluster global temp table yet */
395+
if (OldHeap->rd_rel->relpersistence == RELPERSISTENCE_SESSION)
396+
ereport(ERROR,
397+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
398+
errmsg("not support cluster global temporary tables yet")));
399+
400+
394401
/*
395402
* Also check for active uses of the relation in the current transaction,
396403
* including open scans and pending AFTER trigger events.
@@ -1399,7 +1406,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
13991406
*/
14001407
if (newrelpersistence == RELPERSISTENCE_UNLOGGED)
14011408
reindex_flags |= REINDEX_REL_FORCE_INDEXES_UNLOGGED;
1402-
else if (newrelpersistence == RELPERSISTENCE_PERMANENT)
1409+
else if (newrelpersistence != RELPERSISTENCE_TEMP)
14031410
reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT;
14041411

14051412
/* Report that we are now reindexing relations */

0 commit comments

Comments
 (0)