timescaledb/tsl/test/sql/remote_txn_resolve.sql
Erik Nordström 47d26b422e Allow optional password when adding data node
Add an optional password parameter to `add_data_node` so that users
that don't have a password in a `passfile` on the access node can add
data nodes using password authentication. Together with user mappings,
this allows full multinode configuration without relying on passwords
or certificates provided in external/on-disk files.

While wasswords can be provided in the database via a user mapping
object, such a mapping is created on a per-server basis and requires
the foreign server to exist prior to creating the mapping. When adding
a data node, however, bootstrapping and/or validation of the data node
happens at the same time as the server object is created, which means
no user mapping can be created prior to adding the data
node. Therefore, the password must be provided as an argument to add
data node instead of via a user mapping.

Fortunately, using a function parameter might be preferred to a user
mapping since the (plaintext) password won't be stored in the
database. A user mapping for the user that created the data node can
optionally be added after the data node has been added. But it might
be desirable to only create user mappings for unprivileged users that
will mostly interact only with specific distributed hypertables.
2020-11-10 13:48:21 +01:00

77 lines
3.4 KiB
PL/PgSQL

-- This file and its contents are licensed under the Timescale License.
-- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license.
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE OR REPLACE FUNCTION create_records()
RETURNS VOID
AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_records'
LANGUAGE C;
CREATE OR REPLACE FUNCTION create_records_with_concurrent_heal()
RETURNS VOID
AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_records_with_concurrent_heal'
LANGUAGE C;
CREATE OR REPLACE FUNCTION add_loopback_server(
server_name NAME,
host TEXT = 'localhost',
database NAME = current_database(),
port INTEGER = inet_server_port(),
if_not_exists BOOLEAN = FALSE,
bootstrap BOOLEAN = TRUE,
password TEXT = NULL
) RETURNS TABLE(server_name NAME, host TEXT, port INTEGER, database NAME,
server_created BOOL, database_created BOOL, extension_created BOOL)
AS :TSL_MODULE_PATHNAME, 'ts_unchecked_add_data_node'
LANGUAGE C;
SELECT true FROM add_loopback_server('loopback', database => :'TEST_DBNAME', bootstrap => false);
SELECT true FROM add_loopback_server('loopback2', database => :'TEST_DBNAME', bootstrap => false);
SELECT true FROM add_loopback_server('loopback3', database => :'TEST_DBNAME', bootstrap => false);
create table table_modified_by_txns (
describes text
);
--create records will create 3 records
--1) that is committed
--2) that is prepared but not committed
--3) that is prepared and rolled back
--Thus (1) will be seen right away, (2) will be seen after the heal, (3) will never be seen
SELECT create_records();
SELECT * FROM table_modified_by_txns;
SELECT count(*) FROM pg_prepared_xacts;
SELECT count(*) FROM _timescaledb_catalog.remote_txn;
SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback'));
SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2'));
SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3'));
SELECT * FROM table_modified_by_txns;
SELECT count(*) FROM pg_prepared_xacts;
SELECT count(*) FROM _timescaledb_catalog.remote_txn;
--insert one record where the heal function is run concurrently during different steps of the process
--this tests safety when, for example, the heal function is run while the frontend txn is still ongoing.
SELECT create_records_with_concurrent_heal();
SELECT * FROM table_modified_by_txns;
SELECT count(*) FROM pg_prepared_xacts;
SELECT count(*) FROM _timescaledb_catalog.remote_txn;
--test that it is safe to have non-ts prepared-txns with heal
BEGIN;
INSERT INTO public.table_modified_by_txns VALUES ('non-ts-txn');
PREPARE TRANSACTION 'non-ts-txn';
SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback'));
SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2'));
SELECT _timescaledb_internal.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3'));
COMMIT PREPARED 'non-ts-txn';
SELECT * FROM table_modified_by_txns;
SELECT count(*) FROM pg_prepared_xacts;
SELECT count(*) FROM _timescaledb_catalog.remote_txn;