Skip to content

Commit e31e4b5

Browse files
committed
check pg_pathman's Pl/PgSQL frontend for compatibility with pg_pathman's shared library
1 parent ab33a7e commit e31e4b5

File tree

5 files changed

+120
-0
lines changed

5 files changed

+120
-0
lines changed

init.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ CREATE OR REPLACE FUNCTION @extschema@.debug_capture()
759759
RETURNS VOID AS 'pg_pathman', 'debug_capture'
760760
LANGUAGE C STRICT;
761761

762+
CREATE OR REPLACE FUNCTION @extschema@.get_pathman_lib_version()
763+
RETURNS CSTRING AS 'pg_pathman', 'get_pathman_lib_version'
764+
LANGUAGE C STRICT;
765+
762766

763767
/*
764768
* Invoke init_callback on RANGE partition.

pg_pathman--1.1--1.2.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,11 @@ BEFORE INSERT OR UPDATE OR DELETE ON @extschema@.pathman_config_params
12811281
FOR EACH ROW EXECUTE PROCEDURE @extschema@.pathman_config_params_trigger_func();
12821282

12831283

1284+
CREATE OR REPLACE FUNCTION @extschema@.get_pathman_lib_version()
1285+
RETURNS CSTRING AS 'pg_pathman', 'get_pathman_lib_version'
1286+
LANGUAGE C STRICT;
1287+
1288+
12841289
/* ------------------------------------------------------------------------
12851290
* Alter tables
12861291
* ----------------------------------------------------------------------*/

src/init.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "access/sysattr.h"
2323
#include "catalog/indexing.h"
2424
#include "catalog/pg_constraint.h"
25+
#include "catalog/pg_extension.h"
2526
#include "catalog/pg_inherits.h"
2627
#include "catalog/pg_inherits_fn.h"
2728
#include "catalog/pg_type.h"
@@ -62,6 +63,7 @@ PathmanInitState pg_pathman_init_state;
6263
/* Shall we install new relcache callback? */
6364
static bool relcache_callback_needed = true;
6465

66+
6567
/* Functions for various local caches */
6668
static bool init_pathman_relation_oids(void);
6769
static void fini_pathman_relation_oids(void);
@@ -89,6 +91,11 @@ static bool read_opexpr_const(const OpExpr *opexpr,
8991
static int oid_cmp(const void *p1, const void *p2);
9092

9193

94+
/* Validate SQL facade */
95+
static uint32 build_sql_facade_version(char *version_cstr);
96+
static uint32 get_sql_facade_version(void);
97+
static void validate_sql_facade_version(uint32 ver);
98+
9299
/*
93100
* Save and restore main init state.
94101
*/
@@ -167,6 +174,9 @@ load_config(void)
167174
if (!init_pathman_relation_oids())
168175
return false; /* remain 'uninitialized', exit before creating main caches */
169176

177+
/* Validate pg_pathman's Pl/PgSQL facade (might be outdated) */
178+
validate_sql_facade_version(get_sql_facade_version());
179+
170180
init_local_cache(); /* create 'partitioned_rels' hash table */
171181
read_pathman_config(); /* read PATHMAN_CONFIG table & fill cache */
172182

@@ -1098,3 +1108,89 @@ oid_cmp(const void *p1, const void *p2)
10981108
return 1;
10991109
return 0;
11001110
}
1111+
1112+
1113+
/* Parse cstring and build uint32 representing the version */
1114+
static uint32
1115+
build_sql_facade_version(char *version_cstr)
1116+
{
1117+
uint32 version;
1118+
1119+
/* expect to see x+.y+.z+ */
1120+
version = strtol(version_cstr, &version_cstr, 10) & 0xFF;
1121+
1122+
version <<= 8;
1123+
if (strlen(version_cstr) > 1)
1124+
version |= (strtol(version_cstr + 1, &version_cstr, 10) & 0xFF);
1125+
1126+
version <<= 8;
1127+
if (strlen(version_cstr) > 1)
1128+
version |= (strtol(version_cstr + 1, &version_cstr, 10) & 0xFF);
1129+
1130+
return version;
1131+
}
1132+
1133+
/* Get version of pg_pathman's facade written in Pl/PgSQL */
1134+
static uint32
1135+
get_sql_facade_version(void)
1136+
{
1137+
Relation pg_extension_rel;
1138+
ScanKeyData skey;
1139+
SysScanDesc scan;
1140+
HeapTuple htup;
1141+
1142+
Datum datum;
1143+
bool isnull;
1144+
char *version_cstr;
1145+
1146+
/* Look up the extension */
1147+
pg_extension_rel = heap_open(ExtensionRelationId, AccessShareLock);
1148+
1149+
ScanKeyInit(&skey,
1150+
Anum_pg_extension_extname,
1151+
BTEqualStrategyNumber, F_NAMEEQ,
1152+
CStringGetDatum("pg_pathman"));
1153+
1154+
scan = systable_beginscan(pg_extension_rel,
1155+
ExtensionNameIndexId,
1156+
true, NULL, 1, &skey);
1157+
1158+
htup = systable_getnext(scan);
1159+
1160+
/* Exit if pg_pathman's missing */
1161+
if (!HeapTupleIsValid(htup))
1162+
return 0;
1163+
1164+
datum = heap_getattr(htup, Anum_pg_extension_extversion,
1165+
RelationGetDescr(pg_extension_rel), &isnull);
1166+
Assert(isnull == false); /* extversion should not be NULL */
1167+
1168+
/* Extract pg_pathman's version as cstring */
1169+
version_cstr = text_to_cstring(DatumGetTextPP(datum));
1170+
1171+
systable_endscan(scan);
1172+
heap_close(pg_extension_rel, AccessShareLock);
1173+
1174+
return build_sql_facade_version(version_cstr);
1175+
}
1176+
1177+
/* Check that current Pl/PgSQL facade is compatible with internals */
1178+
static void
1179+
validate_sql_facade_version(uint32 ver)
1180+
{
1181+
Assert(ver > 0);
1182+
1183+
/* Compare ver to 'lowest compatible frontend' version */
1184+
if (ver < LOWEST_COMPATIBLE_FRONT)
1185+
{
1186+
elog(DEBUG1, "current version: %x, lowest compatible: %x",
1187+
ver, LOWEST_COMPATIBLE_FRONT);
1188+
1189+
DisablePathman(); /* disable pg_pathman since config is broken */
1190+
ereport(ERROR,
1191+
(errmsg("pg_pathman's Pl/PgSQL frontend is incompatible with "
1192+
"its shared library"),
1193+
errdetail("consider performing an update procedure"),
1194+
errhint(INIT_ERROR_HINT)));
1195+
}
1196+
}

src/init.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ extern PathmanInitState pg_pathman_init_state;
9595
#define DEFAULT_SPAWN_USING_BGW false
9696

9797

98+
/* Lowest version of Pl/PgSQL frontend compatible with internals (0xAA_BB_CC) */
99+
#define LOWEST_COMPATIBLE_FRONT 0x010200
100+
#define CURRENT_LIB_VERSION 0x010200
101+
102+
98103
/*
99104
* Save and restore PathmanInitState.
100105
*/

src/pl_funcs.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ PG_FUNCTION_INFO_V1( invoke_on_partition_created_callback );
6767
PG_FUNCTION_INFO_V1( check_security_policy );
6868

6969
PG_FUNCTION_INFO_V1( debug_capture );
70+
PG_FUNCTION_INFO_V1( get_pathman_lib_version );
7071

7172

7273
/*
@@ -913,3 +914,12 @@ debug_capture(PG_FUNCTION_ARGS)
913914

914915
PG_RETURN_VOID();
915916
}
917+
918+
/*
919+
* NOTE: just in case.
920+
*/
921+
Datum
922+
get_pathman_lib_version(PG_FUNCTION_ARGS)
923+
{
924+
PG_RETURN_CSTRING(psprintf("%x", CURRENT_LIB_VERSION));
925+
}

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