Skip to content

Commit e0cfda6

Browse files
committed
fix incorrect assert in get_pathman_relation_info(), function drop_range_partition() can drop both foreign and local tables and preserve partition's data, insert a few otimizations into pathman_relcache_hook() and finish_delayed_invalidation()
1 parent 1d8eeb5 commit e0cfda6

File tree

7 files changed

+72
-33
lines changed

7 files changed

+72
-33
lines changed

README.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ add_range_partition(relation REGCLASS,
165165
Create new RANGE partition for `relation` with specified range bounds.
166166

167167
```plpgsql
168-
drop_range_partition(partition TEXT)
168+
drop_range_partition(partition TEXT, delete_data BOOLEAN DEFAULT TRUE)
169169
```
170-
Drop RANGE partition and all its data.
170+
Drop RANGE partition and all of its data if `delete_data` is true.
171171

172172
```plpgsql
173173
attach_range_partition(relation REGCLASS,
@@ -221,8 +221,7 @@ CREATE TABLE IF NOT EXISTS pathman_config (
221221
parttype INTEGER NOT NULL,
222222
range_interval TEXT,
223223

224-
CHECK (parttype IN (1, 2)) /* check for allowed part types */
225-
);
224+
CHECK (parttype IN (1, 2)) /* check for allowed part types */ );
226225
```
227226
This table stores a list of partitioned tables.
228227

@@ -232,8 +231,7 @@ CREATE TABLE IF NOT EXISTS pathman_config_params (
232231
partrel REGCLASS NOT NULL PRIMARY KEY,
233232
enable_parent BOOLEAN NOT NULL DEFAULT TRUE,
234233
auto BOOLEAN NOT NULL DEFAULT TRUE,
235-
init_callback REGPROCEDURE NOT NULL DEFAULT 0
236-
);
234+
init_callback REGPROCEDURE NOT NULL DEFAULT 0);
237235
```
238236
This table stores optional parameters which override standard behavior.
239237

@@ -259,7 +257,7 @@ This view lists all currently running concurrent partitioning tasks.
259257
#### `pathman_partition_list` --- list of all existing partitions
260258
```plpgsql
261259
-- helper SRF function
262-
CREATE OR REPLACE FUNCTION @extschema@.show_partition_list()
260+
CREATE OR REPLACE FUNCTION show_partition_list()
263261
RETURNS TABLE (
264262
parent REGCLASS,
265263
partition REGCLASS,
@@ -471,7 +469,7 @@ Notice that the `Append` node contains only one child scan which corresponds to
471469
> **Important:** pay attention to the fact that `pg_pathman` excludes the parent table from the query plan.
472470
473471
To access parent table use ONLY modifier:
474-
```
472+
```plpgsql
475473
EXPLAIN SELECT * FROM ONLY items;
476474
QUERY PLAN
477475
------------------------------------------------------
@@ -484,8 +482,7 @@ CREATE TABLE journal (
484482
id SERIAL,
485483
dt TIMESTAMP NOT NULL,
486484
level INTEGER,
487-
msg TEXT
488-
);
485+
msg TEXT);
489486

490487
-- similar index will also be created for each partition
491488
CREATE INDEX ON journal(dt);
@@ -515,8 +512,8 @@ CREATE FOREIGN TABLE journal_archive (
515512
id INTEGER NOT NULL,
516513
dt TIMESTAMP NOT NULL,
517514
level INTEGER,
518-
msg TEXT
519-
) SERVER archive_server;
515+
msg TEXT)
516+
SERVER archive_server;
520517

521518
SELECT attach_range_partition('journal', 'journal_archive', '2014-01-01'::date, '2015-01-01'::date);
522519
```

init.sql

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ RETURNS INTEGER AS
511511
$$
512512
DECLARE
513513
v_rec RECORD;
514-
v_rows INTEGER;
514+
v_rows BIGINT;
515515
v_part_count INTEGER := 0;
516516
conf_num_del INTEGER;
517517
v_relkind CHAR;
@@ -539,10 +539,9 @@ BEGIN
539539
ORDER BY inhrelid ASC)
540540
LOOP
541541
IF NOT delete_data THEN
542-
EXECUTE format('WITH part_data AS (DELETE FROM %s RETURNING *)
543-
INSERT INTO %s SELECT * FROM part_data',
544-
v_rec.tbl::TEXT,
545-
parent_relid::text);
542+
EXECUTE format('INSERT INTO %s SELECT * FROM %s',
543+
parent_relid::TEXT,
544+
v_rec.tbl::TEXT);
546545
GET DIAGNOSTICS v_rows = ROW_COUNT;
547546

548547
/* Show number of copied rows */

range.sql

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,12 +1027,15 @@ LANGUAGE plpgsql;
10271027
* Drop range partition
10281028
*/
10291029
CREATE OR REPLACE FUNCTION @extschema@.drop_range_partition(
1030-
p_partition REGCLASS)
1030+
p_partition REGCLASS,
1031+
delete_data BOOLEAN DEFAULT TRUE)
10311032
RETURNS TEXT AS
10321033
$$
10331034
DECLARE
10341035
parent_relid REGCLASS;
10351036
part_name TEXT;
1037+
v_relkind CHAR;
1038+
v_rows BIGINT;
10361039

10371040
BEGIN
10381041
parent_relid := @extschema@.get_parent_of_partition(p_partition);
@@ -1041,16 +1044,39 @@ BEGIN
10411044
/* Acquire lock on parent */
10421045
PERFORM @extschema@.lock_partitioned_relation(parent_relid);
10431046

1044-
/* Drop table */
1045-
EXECUTE format('DROP TABLE %s', part_name);
1047+
IF NOT delete_data THEN
1048+
EXECUTE format('INSERT INTO %s SELECT * FROM %s',
1049+
parent_relid::TEXT,
1050+
p_partition::TEXT);
1051+
GET DIAGNOSTICS v_rows = ROW_COUNT;
1052+
1053+
/* Show number of copied rows */
1054+
RAISE NOTICE '% rows copied from %', v_rows, p_partition::TEXT;
1055+
END IF;
1056+
1057+
SELECT relkind FROM pg_catalog.pg_class
1058+
WHERE oid = p_partition
1059+
INTO v_relkind;
1060+
1061+
/*
1062+
* Determine the kind of child relation. It can be either regular
1063+
* table (r) or foreign table (f). Depending on relkind we use
1064+
* DROP TABLE or DROP FOREIGN TABLE.
1065+
*/
1066+
IF v_relkind = 'f' THEN
1067+
EXECUTE format('DROP FOREIGN TABLE %s', p_partition::TEXT);
1068+
ELSE
1069+
EXECUTE format('DROP TABLE %s', p_partition::TEXT);
1070+
END IF;
10461071

10471072
/* Invalidate cache */
10481073
PERFORM @extschema@.on_update_partitions(parent_relid);
10491074

10501075
RETURN part_name;
10511076
END
10521077
$$
1053-
LANGUAGE plpgsql;
1078+
LANGUAGE plpgsql
1079+
SET pg_pathman.enable_partitionfilter = off; /* ensures that PartitionFilter is OFF */
10541080

10551081

10561082
/*

src/hooks.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "utils.h"
1919
#include "xact_handling.h"
2020

21+
#include "access/transam.h"
2122
#include "miscadmin.h"
2223
#include "optimizer/cost.h"
2324
#include "optimizer/restrictinfo.h"
@@ -546,6 +547,10 @@ pathman_relcache_hook(Datum arg, Oid relid)
546547
if (!IsPathmanReady())
547548
return;
548549

550+
/* We shouldn't even consider special OIDs */
551+
if (relid < FirstNormalObjectId)
552+
return;
553+
549554
/* Invalidation event for PATHMAN_CONFIG table (probably DROP) */
550555
if (relid == get_pathman_config_relid())
551556
delay_pathman_shutdown();
@@ -569,7 +574,8 @@ pathman_relcache_hook(Datum arg, Oid relid)
569574
/* Both syscache and pathman's cache say it isn't a partition */
570575
case PPS_ENTRY_NOT_FOUND:
571576
{
572-
delay_invalidation_parent_rel(partitioned_table);
577+
if (partitioned_table != InvalidOid)
578+
delay_invalidation_parent_rel(partitioned_table);
573579
#ifdef NOT_USED
574580
elog(DEBUG2, "Invalidation message for relation %u [%u]",
575581
relid, MyProcPid);
@@ -588,7 +594,8 @@ pathman_relcache_hook(Datum arg, Oid relid)
588594
break;
589595

590596
default:
591-
elog(ERROR, "Not implemented yet");
597+
elog(ERROR, "Not implemented yet (%s)",
598+
CppAsString(pathman_relcache_hook));
592599
break;
593600
}
594601
}

src/pathman_workers.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ start_bg_worker(const char bgworker_name[BGW_MAXLEN],
213213
case BGW_PM_DIED:
214214
ereport(ERROR,
215215
(errmsg("Postmaster died during the pg_pathman background worker process"),
216-
errhint("More details may be available in the server log.")));
216+
errhint("More details may be available in the server log.")));
217217
break;
218218

219219
default:
@@ -300,9 +300,10 @@ create_partitions_bg_worker(Oid relid, Datum value, Oid value_type)
300300
dsm_detach(segment);
301301

302302
if (child_oid == InvalidOid)
303-
elog(ERROR,
304-
"Attempt to append new partitions to relation \"%s\" failed",
305-
get_rel_name_or_relid(relid));
303+
ereport(ERROR,
304+
(errmsg("Attempt to spawn new partitions of relation \"%s\" failed",
305+
get_rel_name_or_relid(relid)),
306+
errhint("See server log for more details.")));
306307

307308
return child_oid;
308309
}

src/pl_funcs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@ on_partitions_created_internal(Oid partitioned_table, bool add_callbacks)
106106
static void
107107
on_partitions_updated_internal(Oid partitioned_table, bool add_callbacks)
108108
{
109-
bool found;
109+
bool entry_found;
110110

111111
elog(DEBUG2, "on_partitions_updated() [add_callbacks = %s] "
112112
"triggered for relation %u",
113113
(add_callbacks ? "true" : "false"), partitioned_table);
114114

115-
invalidate_pathman_relation_info(partitioned_table, &found);
115+
invalidate_pathman_relation_info(partitioned_table, &entry_found);
116116
}
117117

118118
static void

src/relation_info.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "access/htup_details.h"
1717
#include "access/xact.h"
18+
#include "catalog/catalog.h"
1819
#include "catalog/indexing.h"
1920
#include "catalog/pg_inherits.h"
2021
#include "miscadmin.h"
@@ -242,12 +243,11 @@ get_pathman_relation_info(Oid relid)
242243
part_type = DatumGetPartType(values[Anum_pathman_config_parttype - 1]);
243244
attname = TextDatumGetCString(values[Anum_pathman_config_attname - 1]);
244245

245-
/* Refresh partitioned table cache entry */
246+
/* Refresh partitioned table cache entry (might turn NULL) */
246247
/* TODO: possible refactoring, pass found 'prel' instead of searching */
247248
prel = refresh_pathman_relation_info(relid,
248249
part_type,
249250
attname);
250-
Assert(PrelIsValid(prel)); /* it MUST be valid if we got here */
251251
}
252252
/* Else clear remaining cache entry */
253253
else remove_pathman_relation_info(relid);
@@ -346,7 +346,7 @@ finish_delayed_invalidation(void)
346346
/* Handle the probable 'DROP EXTENSION' case */
347347
if (delayed_shutdown)
348348
{
349-
Oid cur_pathman_config_relid;
349+
Oid cur_pathman_config_relid;
350350

351351
/* Unset 'shutdown' flag */
352352
delayed_shutdown = false;
@@ -376,9 +376,14 @@ finish_delayed_invalidation(void)
376376
{
377377
Oid parent = lfirst_oid(lc);
378378

379+
/* Skip if it's a TOAST table */
380+
if (IsToastNamespace(get_rel_namespace(parent)))
381+
continue;
382+
379383
if (!pathman_config_contains_relation(parent, NULL, NULL, NULL))
380384
remove_pathman_relation_info(parent);
381385
else
386+
/* get_pathman_relation_info() will refresh this entry */
382387
invalidate_pathman_relation_info(parent, NULL);
383388
}
384389

@@ -387,6 +392,10 @@ finish_delayed_invalidation(void)
387392
{
388393
Oid vague_rel = lfirst_oid(lc);
389394

395+
/* Skip if it's a TOAST table */
396+
if (IsToastNamespace(get_rel_namespace(vague_rel)))
397+
continue;
398+
390399
/* It might be a partitioned table or a partition */
391400
if (!try_perform_parent_refresh(vague_rel))
392401
{
@@ -656,7 +665,7 @@ shout_if_prel_is_invalid(Oid parent_oid,
656665
PartType expected_part_type)
657666
{
658667
if (!prel)
659-
elog(ERROR, "relation \"%s\" is not partitioned by pg_pathman",
668+
elog(ERROR, "relation \"%s\" has no partitions",
660669
get_rel_name_or_relid(parent_oid));
661670

662671
if (!PrelIsValid(prel))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy