Skip to content

Commit 116a62f

Browse files
authored
Merge branch 'postgres:master' into master
2 parents f7067ea + 2e2e7ff commit 116a62f

File tree

7 files changed

+303
-4
lines changed

7 files changed

+303
-4
lines changed

.gitattributes

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
*.xsl whitespace=space-before-tab,trailing-space,tab-in-indent
1313

1414
# Avoid confusing ASCII underlines with leftover merge conflict markers
15-
README conflict-marker-size=32
16-
README.* conflict-marker-size=32
15+
README conflict-marker-size=48
16+
README.* conflict-marker-size=48
1717

1818
# Certain data files that contain special whitespace, and other special cases
1919
*.data -whitespace

src/backend/nodes/bitmapset.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1343,7 +1343,7 @@ bms_next_member(const Bitmapset *a, int prevbit)
13431343
*
13441344
* Returns largest member less than "prevbit", or -2 if there is none.
13451345
* "prevbit" must NOT be more than one above the highest possible bit that can
1346-
* be set at the Bitmapset at its current size.
1346+
* be set in the Bitmapset at its current size.
13471347
*
13481348
* To ease finding the highest set bit for the initial loop, the special
13491349
* prevbit value of -1 can be passed to have the function find the highest
@@ -1379,6 +1379,10 @@ bms_prev_member(const Bitmapset *a, int prevbit)
13791379
if (a == NULL || prevbit == 0)
13801380
return -2;
13811381

1382+
/* Validate callers didn't give us something out of range */
1383+
Assert(prevbit <= a->nwords * BITS_PER_BITMAPWORD);
1384+
Assert(prevbit >= -1);
1385+
13821386
/* transform -1 to the highest possible bit we could have set */
13831387
if (prevbit == -1)
13841388
prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;

src/backend/utils/hash/dynahash.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ init_htab(HTAB *hashp, long nelem)
776776
hctl->nelem_alloc = choose_nelem_alloc(hctl->entrysize);
777777

778778
#ifdef HASH_DEBUG
779-
fprintf(stderr, "init_htab:\n%s%p\n%s%ld\n%s%ld\n%s%d\n%s%ld\n%s%u\n%s%x\n%s%x\n%s%ld\n",
779+
fprintf(stderr, "init_htab:\n%s%p\n%s%ld\n%s%ld\n%s%d\n%s%u\n%s%x\n%s%x\n%s%ld\n",
780780
"TABLE POINTER ", hashp,
781781
"DIRECTORY SIZE ", hctl->dsize,
782782
"SEGMENT SIZE ", hctl->ssize,
@@ -1174,6 +1174,8 @@ hash_update_hash_key(HTAB *hashp,
11741174
HashCompareFunc match;
11751175

11761176
#ifdef HASH_STATISTICS
1177+
HASHHDR *hctl = hashp->hctl;
1178+
11771179
hash_accesses++;
11781180
hctl->accesses++;
11791181
#endif

src/test/ldap/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ tests += {
88
'tests': [
99
't/001_auth.pl',
1010
't/002_bindpasswd.pl',
11+
't/003_ldap_connection_param_lookup.pl',
1112
],
1213
'env': {
1314
'with_ldap': ldap.found() ? 'yes' : 'no',
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
2+
# Copyright (c) 2025, PostgreSQL Global Development Group
3+
4+
use strict;
5+
use warnings FATAL => 'all';
6+
7+
use FindBin;
8+
use lib "$FindBin::RealBin/..";
9+
10+
use File::Copy;
11+
use LdapServer;
12+
use PostgreSQL::Test::Utils;
13+
use PostgreSQL::Test::Cluster;
14+
use Test::More;
15+
16+
if ($ENV{with_ldap} ne 'yes')
17+
{
18+
plan skip_all => 'LDAP not supported by this build';
19+
}
20+
elsif (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bldap\b/)
21+
{
22+
plan skip_all =>
23+
'Potentially unsafe test LDAP not enabled in PG_TEST_EXTRA';
24+
}
25+
elsif (!$LdapServer::setup)
26+
{
27+
plan skip_all => $LdapServer::setup_error;
28+
}
29+
30+
# This tests scenarios related to the service name and the service file,
31+
# for the connection options and their environment variables.
32+
my $dummy_node = PostgreSQL::Test::Cluster->new('dummy_node');
33+
$dummy_node->init;
34+
35+
my $node = PostgreSQL::Test::Cluster->new('node');
36+
$node->init;
37+
$node->start;
38+
39+
note "setting up LDAP server";
40+
41+
my $ldap_rootpw = 'secret';
42+
my $ldap = LdapServer->new($ldap_rootpw, 'anonymous'); # use anonymous auth
43+
$ldap->ldapadd_file('authdata.ldif');
44+
$ldap->ldapsetpw('uid=test1,dc=example,dc=net', 'secret1');
45+
$ldap->ldapsetpw('uid=test2,dc=example,dc=net', 'secret2');
46+
47+
# Windows vs non-Windows: CRLF vs LF for the file's newline, relying on
48+
# the fact that libpq uses fgets() when reading the lines of a service file.
49+
my $newline = $windows_os ? "\r\n" : "\n";
50+
51+
my $td = PostgreSQL::Test::Utils::tempdir;
52+
53+
# create ldap file based on postgres connection info
54+
my $ldif_valid = "$td/connection_params.ldif";
55+
append_to_file($ldif_valid, "version:1");
56+
append_to_file($ldif_valid, $newline);
57+
append_to_file($ldif_valid, "dn:cn=mydatabase,dc=example,dc=net");
58+
append_to_file($ldif_valid, $newline);
59+
append_to_file($ldif_valid, "changetype:add");
60+
append_to_file($ldif_valid, $newline);
61+
append_to_file($ldif_valid, "objectclass:top");
62+
append_to_file($ldif_valid, $newline);
63+
append_to_file($ldif_valid, "objectclass:device");
64+
append_to_file($ldif_valid, $newline);
65+
append_to_file($ldif_valid, "cn:mydatabase");
66+
append_to_file($ldif_valid, $newline);
67+
append_to_file($ldif_valid, "description:host=");
68+
append_to_file($ldif_valid, $node->host);
69+
append_to_file($ldif_valid, $newline);
70+
append_to_file($ldif_valid, "description:port=");
71+
append_to_file($ldif_valid, $node->port);
72+
73+
$ldap->ldapadd_file($ldif_valid);
74+
75+
my ($ldap_server, $ldap_port, $ldaps_port, $ldap_url,
76+
$ldaps_url, $ldap_basedn, $ldap_rootdn
77+
) = $ldap->prop(qw(server port s_port url s_url basedn rootdn));
78+
79+
# don't bother to check the server's cert (though perhaps we should)
80+
$ENV{'LDAPTLS_REQCERT'} = "never";
81+
82+
note "setting up PostgreSQL instance";
83+
84+
# Create the set of service files used in the tests.
85+
86+
# File that includes a valid service name, that uses a decomposed
87+
# connection string for its contents, split on spaces.
88+
my $srvfile_valid = "$td/pg_service_valid.conf";
89+
append_to_file($srvfile_valid, "[my_srv]");
90+
append_to_file($srvfile_valid, $newline);
91+
append_to_file($srvfile_valid, "ldap://localhost:");
92+
append_to_file($srvfile_valid, $ldap_port);
93+
append_to_file($srvfile_valid,
94+
"/dc=example,dc=net?description?one?(cn=mydatabase)");
95+
96+
# File defined with no contents, used as default value for
97+
# PGSERVICEFILE, so that no lookup is attempted in the user's home
98+
# directory.
99+
my $srvfile_empty = "$td/pg_service_empty.conf";
100+
append_to_file($srvfile_empty, '');
101+
102+
# Default service file in PGSYSCONFDIR.
103+
my $srvfile_default = "$td/pg_service.conf";
104+
105+
# Missing service file.
106+
my $srvfile_missing = "$td/pg_service_missing.conf";
107+
108+
# Set the fallback directory lookup of the service file to the
109+
# temporary directory of this test. PGSYSCONFDIR is used if the
110+
# service file defined in PGSERVICEFILE cannot be found, or when a
111+
# service file is found but not the service name.
112+
local $ENV{PGSYSCONFDIR} = $td;
113+
114+
# Force PGSERVICEFILE to a default location, so as this test never
115+
# tries to look at a home directory. This value needs to remain at
116+
# the top of this script before running any tests, and should never be
117+
# changed.
118+
local $ENV{PGSERVICEFILE} = "$srvfile_empty";
119+
120+
# Checks combinations of service name and a valid service file.
121+
{
122+
local $ENV{PGSERVICEFILE} = $srvfile_valid;
123+
124+
$dummy_node->connect_ok(
125+
'service=my_srv',
126+
'connection with correct "service" string and PGSERVICEFILE',
127+
sql => "SELECT 'connect1_1'",
128+
expected_stdout => qr/connect1_1/);
129+
130+
$dummy_node->connect_ok(
131+
'postgres://?service=my_srv',
132+
'connection with correct "service" URI and PGSERVICEFILE',
133+
sql => "SELECT 'connect1_2'",
134+
expected_stdout => qr/connect1_2/);
135+
136+
$dummy_node->connect_fails(
137+
'service=undefined-service',
138+
'connection with incorrect "service" string and PGSERVICEFILE',
139+
expected_stderr =>
140+
qr/definition of service "undefined-service" not found/);
141+
142+
local $ENV{PGSERVICE} = 'my_srv';
143+
144+
$dummy_node->connect_ok(
145+
'',
146+
'connection with correct PGSERVICE and PGSERVICEFILE',
147+
sql => "SELECT 'connect1_3'",
148+
expected_stdout => qr/connect1_3/);
149+
150+
local $ENV{PGSERVICE} = 'undefined-service';
151+
152+
$dummy_node->connect_fails(
153+
'',
154+
'connection with incorrect PGSERVICE and PGSERVICEFILE',
155+
expected_stdout =>
156+
qr/definition of service "undefined-service" not found/);
157+
}
158+
159+
# Checks case of incorrect service file.
160+
{
161+
local $ENV{PGSERVICEFILE} = $srvfile_missing;
162+
163+
$dummy_node->connect_fails(
164+
'service=my_srv',
165+
'connection with correct "service" string and incorrect PGSERVICEFILE',
166+
expected_stderr =>
167+
qr/service file ".*pg_service_missing.conf" not found/);
168+
}
169+
170+
# Checks case of service file named "pg_service.conf" in PGSYSCONFDIR.
171+
{
172+
# Create copy of valid file
173+
my $srvfile_default = "$td/pg_service.conf";
174+
copy($srvfile_valid, $srvfile_default);
175+
176+
$dummy_node->connect_ok(
177+
'service=my_srv',
178+
'connection with correct "service" string and pg_service.conf',
179+
sql => "SELECT 'connect2_1'",
180+
expected_stdout => qr/connect2_1/);
181+
182+
$dummy_node->connect_ok(
183+
'postgres://?service=my_srv',
184+
'connection with correct "service" URI and default pg_service.conf',
185+
sql => "SELECT 'connect2_2'",
186+
expected_stdout => qr/connect2_2/);
187+
188+
$dummy_node->connect_fails(
189+
'service=undefined-service',
190+
'connection with incorrect "service" string and default pg_service.conf',
191+
expected_stderr =>
192+
qr/definition of service "undefined-service" not found/);
193+
194+
local $ENV{PGSERVICE} = 'my_srv';
195+
196+
$dummy_node->connect_ok(
197+
'',
198+
'connection with correct PGSERVICE and default pg_service.conf',
199+
sql => "SELECT 'connect2_3'",
200+
expected_stdout => qr/connect2_3/);
201+
202+
local $ENV{PGSERVICE} = 'undefined-service';
203+
204+
$dummy_node->connect_fails(
205+
'',
206+
'connection with incorrect PGSERVICE and default pg_service.conf',
207+
expected_stdout =>
208+
qr/definition of service "undefined-service" not found/);
209+
210+
# Remove default pg_service.conf.
211+
unlink($srvfile_default);
212+
}
213+
214+
$node->teardown_node;
215+
216+
done_testing();

src/test/regress/expected/vacuum.out

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,3 +686,49 @@ RESET ROLE;
686686
DROP TABLE vacowned;
687687
DROP TABLE vacowned_parted;
688688
DROP ROLE regress_vacuum;
689+
-- Test checking how new toast values are allocated on rewrite.
690+
-- Create table with plain storage (forces inline storage initially).
691+
CREATE TABLE vac_rewrite_toast (id int, f1 TEXT STORAGE plain);
692+
-- Insert tuple large enough to trigger toast storage on rewrite, still
693+
-- small enough to fit on a page.
694+
INSERT INTO vac_rewrite_toast values (1, repeat('a', 7000));
695+
-- Switch to external storage to force toast table usage.
696+
ALTER TABLE vac_rewrite_toast ALTER COLUMN f1 SET STORAGE EXTERNAL;
697+
-- This second tuple is toasted, its value should still be the
698+
-- same after rewrite.
699+
INSERT INTO vac_rewrite_toast values (2, repeat('a', 7000));
700+
SELECT pg_column_toast_chunk_id(f1) AS id_2_chunk FROM vac_rewrite_toast
701+
WHERE id = 2 \gset
702+
-- Check initial state of the data.
703+
SELECT id, pg_column_toast_chunk_id(f1) IS NULL AS f1_chunk_null,
704+
substr(f1, 5, 10) AS f1_data,
705+
pg_column_compression(f1) AS f1_comp
706+
FROM vac_rewrite_toast ORDER BY id;
707+
id | f1_chunk_null | f1_data | f1_comp
708+
----+---------------+------------+---------
709+
1 | t | aaaaaaaaaa |
710+
2 | f | aaaaaaaaaa |
711+
(2 rows)
712+
713+
-- VACUUM FULL forces toast data rewrite.
714+
VACUUM FULL vac_rewrite_toast;
715+
-- Check after rewrite.
716+
SELECT id, pg_column_toast_chunk_id(f1) IS NULL AS f1_chunk_null,
717+
substr(f1, 5, 10) AS f1_data,
718+
pg_column_compression(f1) AS f1_comp
719+
FROM vac_rewrite_toast ORDER BY id;
720+
id | f1_chunk_null | f1_data | f1_comp
721+
----+---------------+------------+---------
722+
1 | f | aaaaaaaaaa |
723+
2 | f | aaaaaaaaaa |
724+
(2 rows)
725+
726+
-- The same value is reused for the tuple toasted before the rewrite.
727+
SELECT pg_column_toast_chunk_id(f1) = :'id_2_chunk' AS same_chunk
728+
FROM vac_rewrite_toast WHERE id = 2;
729+
same_chunk
730+
------------
731+
t
732+
(1 row)
733+
734+
DROP TABLE vac_rewrite_toast;

src/test/regress/sql/vacuum.sql

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,3 +495,33 @@ RESET ROLE;
495495
DROP TABLE vacowned;
496496
DROP TABLE vacowned_parted;
497497
DROP ROLE regress_vacuum;
498+
499+
-- Test checking how new toast values are allocated on rewrite.
500+
-- Create table with plain storage (forces inline storage initially).
501+
CREATE TABLE vac_rewrite_toast (id int, f1 TEXT STORAGE plain);
502+
-- Insert tuple large enough to trigger toast storage on rewrite, still
503+
-- small enough to fit on a page.
504+
INSERT INTO vac_rewrite_toast values (1, repeat('a', 7000));
505+
-- Switch to external storage to force toast table usage.
506+
ALTER TABLE vac_rewrite_toast ALTER COLUMN f1 SET STORAGE EXTERNAL;
507+
-- This second tuple is toasted, its value should still be the
508+
-- same after rewrite.
509+
INSERT INTO vac_rewrite_toast values (2, repeat('a', 7000));
510+
SELECT pg_column_toast_chunk_id(f1) AS id_2_chunk FROM vac_rewrite_toast
511+
WHERE id = 2 \gset
512+
-- Check initial state of the data.
513+
SELECT id, pg_column_toast_chunk_id(f1) IS NULL AS f1_chunk_null,
514+
substr(f1, 5, 10) AS f1_data,
515+
pg_column_compression(f1) AS f1_comp
516+
FROM vac_rewrite_toast ORDER BY id;
517+
-- VACUUM FULL forces toast data rewrite.
518+
VACUUM FULL vac_rewrite_toast;
519+
-- Check after rewrite.
520+
SELECT id, pg_column_toast_chunk_id(f1) IS NULL AS f1_chunk_null,
521+
substr(f1, 5, 10) AS f1_data,
522+
pg_column_compression(f1) AS f1_comp
523+
FROM vac_rewrite_toast ORDER BY id;
524+
-- The same value is reused for the tuple toasted before the rewrite.
525+
SELECT pg_column_toast_chunk_id(f1) = :'id_2_chunk' AS same_chunk
526+
FROM vac_rewrite_toast WHERE id = 2;
527+
DROP TABLE vac_rewrite_toast;

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