Skip to content

Commit 4c4eaf3

Browse files
committed
Make PostgresNode version aware
A new PostgresVersion object type is created and this is used in PostgresNode using the output of `pg_config --version` and the result stored in the PostgresNode object. This object can be compared to other PostgresVersion objects, or to a number or string. PostgresNode is currently believed to be compatible with versions down to release 12, so PostgresNode will issue a warning if used with a version prior to that. No attempt has been made to deal with incompatibilities in older versions - that remains work to be undertaken in a subsequent development cycle. Based on code from Mark Dilger and Jehan-Guillaume de Rorthais. Discussion: https://postgr.es/m/a80421c0-3d7e-def1-bcfe-24777f15e344@dunslane.net
1 parent f3b141c commit 4c4eaf3

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

src/test/perl/PostgresNode.pm

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ use File::Spec;
9696
use File::stat qw(stat);
9797
use File::Temp ();
9898
use IPC::Run;
99+
use PostgresVersion;
99100
use RecursiveCopy;
100101
use Socket;
101102
use Test::More;
@@ -350,6 +351,8 @@ sub info
350351
my $_info = '';
351352
open my $fh, '>', \$_info or die;
352353
print $fh "Name: " . $self->name . "\n";
354+
print $fh "Version: " . $self->{_pg_version} . "\n"
355+
if $self->{_pg_version};
353356
print $fh "Data directory: " . $self->data_dir . "\n";
354357
print $fh "Backup directory: " . $self->backup_dir . "\n";
355358
print $fh "Archive directory: " . $self->archive_dir . "\n";
@@ -1196,9 +1199,62 @@ sub get_new_node
11961199
# Add node to list of nodes
11971200
push(@all_nodes, $node);
11981201

1202+
$node->_set_pg_version;
1203+
1204+
my $v = $node->{_pg_version};
1205+
1206+
carp("PostgresNode isn't fully compatible with version " . $v)
1207+
if $v < 12;
1208+
11991209
return $node;
12001210
}
12011211

1212+
# Private routine to run the pg_config binary found in our environment (or in
1213+
# our install_path, if we have one), and set the version from it
1214+
#
1215+
sub _set_pg_version
1216+
{
1217+
my ($self) = @_;
1218+
my $inst = $self->{_install_path};
1219+
my $pg_config = "pg_config";
1220+
1221+
if (defined $inst)
1222+
{
1223+
# If the _install_path is invalid, our PATH variables might find an
1224+
# unrelated pg_config executable elsewhere. Sanity check the
1225+
# directory.
1226+
BAIL_OUT("directory not found: $inst")
1227+
unless -d $inst;
1228+
1229+
# If the directory exists but is not the root of a postgresql
1230+
# installation, or if the user configured using
1231+
# --bindir=$SOMEWHERE_ELSE, we're not going to find pg_config, so
1232+
# complain about that, too.
1233+
$pg_config = "$inst/bin/pg_config";
1234+
BAIL_OUT("pg_config not found: $pg_config")
1235+
unless -e $pg_config;
1236+
BAIL_OUT("pg_config not executable: $pg_config")
1237+
unless -x $pg_config;
1238+
1239+
# Leave $pg_config install_path qualified, to be sure we get the right
1240+
# version information, below, or die trying
1241+
}
1242+
1243+
local %ENV = $self->_get_env();
1244+
1245+
# We only want the version field
1246+
open my $fh, "-|", $pg_config, "--version"
1247+
or
1248+
BAIL_OUT("$pg_config failed: $!");
1249+
my $version_line = <$fh>;
1250+
close $fh or die;
1251+
1252+
$self->{_pg_version} = PostgresVersion->new($version_line);
1253+
1254+
BAIL_OUT("could not parse pg_config --version output: $version_line")
1255+
unless defined $self->{_pg_version};
1256+
}
1257+
12021258
# Private routine to return a copy of the environment with the PATH and
12031259
# (DY)LD_LIBRARY_PATH correctly set when there is an install path set for
12041260
# the node.

src/test/perl/PostgresVersion.pm

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
############################################################################
2+
#
3+
# PostgresVersion.pm
4+
#
5+
# Module encapsulating Postgres Version numbers
6+
#
7+
# Copyright (c) 2021, PostgreSQL Global Development Group
8+
#
9+
############################################################################
10+
11+
=pod
12+
13+
=head1 NAME
14+
15+
PostgresVersion - class representing PostgreSQL version numbers
16+
17+
=head1 SYNOPSIS
18+
19+
use PostgresVersion;
20+
21+
my $version = PostgresVersion->new($version_arg);
22+
23+
# compare two versions
24+
my $bool = $version1 <= $version2;
25+
26+
# or compare with a number
27+
$bool = $version < 12;
28+
29+
# or with a string
30+
$bool = $version lt "13.1";
31+
32+
# interpolate in a string
33+
my $stringyval = "version: $version";
34+
35+
=head1 DESCRIPTION
36+
37+
PostgresVersion encapsulated Postgres version numbers, providing parsing
38+
of common version formats and comparison operations.
39+
40+
=cut
41+
42+
package PostgresVersion;
43+
44+
use strict;
45+
use warnings;
46+
47+
use Scalar::Util qw(blessed);
48+
49+
use overload
50+
'<=>' => \&_version_cmp,
51+
'cmp' => \&_version_cmp,
52+
'""' => \&_stringify;
53+
54+
=pod
55+
56+
=head1 METHODS
57+
58+
=over
59+
60+
=item PostgresVersion->new($version)
61+
62+
Create a new PostgresVersion instance.
63+
64+
The argument can be a number like 12, or a string like '12.2' or the output
65+
of a Postgres command like `psql --version` or `pg_config --version`;
66+
67+
=back
68+
69+
=cut
70+
71+
sub new
72+
{
73+
my $class = shift;
74+
my $arg = shift;
75+
76+
# Accept standard formats, in case caller has handed us the output of a
77+
# postgres command line tool
78+
$arg = $1
79+
if ($arg =~ m/\(?PostgreSQL\)? (\d+(?:\.\d+)*(?:devel)?)/);
80+
81+
# Split into an array
82+
my @result = split(/\./, $arg);
83+
84+
# Treat development versions as having a minor/micro version one less than
85+
# the first released version of that branch.
86+
if ($result[$#result] =~ m/^(\d+)devel$/)
87+
{
88+
pop(@result);
89+
push(@result, $1, -1);
90+
}
91+
92+
my $res = [@result];
93+
bless $res, $class;
94+
return $res;
95+
}
96+
97+
98+
# Routine which compares the _pg_version_array obtained for the two
99+
# arguments and returns -1, 0, or 1, allowing comparison between two
100+
# PostgresVersion objects or a PostgresVersion and a version string or number.
101+
#
102+
# If the second argument is not a blessed object we call the constructor
103+
# to make one.
104+
#
105+
# Because we're overloading '<=>' and 'cmp' this function supplies us with
106+
# all the comparison operators ('<' and friends, 'gt' and friends)
107+
#
108+
sub _version_cmp
109+
{
110+
my ($a, $b) = @_;
111+
112+
$b = __PACKAGE__->new($b) unless blessed($b);
113+
114+
for (my $idx = 0;; $idx++)
115+
{
116+
return 0 unless (defined $a->[$idx] && defined $b->[$idx]);
117+
return $a->[$idx] <=> $b->[$idx]
118+
if ($a->[$idx] <=> $b->[$idx]);
119+
}
120+
}
121+
122+
# Render the version number in the standard "joined by dots" notation if
123+
# interpolated into a string. Put back 'devel' if we previously turned it
124+
# into a -1.
125+
sub _stringify
126+
{
127+
my $self = shift;
128+
my @sections = @$self;
129+
if ($sections[-1] == -1)
130+
{
131+
pop @sections;
132+
$sections[-1] = "$sections[-1]devel";
133+
}
134+
return join('.', @sections);
135+
}
136+
137+
1;

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