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

Diff for: init.sql

+4
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ CREATE OR REPLACE FUNCTION @[email protected]_capture()
759759
RETURNS VOID AS 'pg_pathman', 'debug_capture'
760760
LANGUAGE C STRICT;
761761

762+
CREATE OR REPLACE FUNCTION @[email protected]_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.

Diff for: pg_pathman--1.1--1.2.sql

+5
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,11 @@ BEFORE INSERT OR UPDATE OR DELETE ON @[email protected]_config_params
12811281
FOR EACH ROW EXECUTE PROCEDURE @[email protected]_config_params_trigger_func();
12821282

12831283

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

Diff for: src/init.c

+96
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+
}

Diff for: src/init.h

+5
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
*/

Diff for: src/pl_funcs.c

+10
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)