diff --git a/test/io/fixtures/big_schema.sql b/test/io/fixtures/big_schema.sql index 559b434dff..4b16b3c379 100644 --- a/test/io/fixtures/big_schema.sql +++ b/test/io/fixtures/big_schema.sql @@ -11410,3 +11410,41 @@ TO postgrest_test_anonymous; create or replace function apflora.notify_pgrst() returns void as $$ notify pgrst; $$ language sql; + +CREATE SCHEMA bigdata; + +GRANT ALL ON SCHEMA bigdata TO postgrest_test_anonymous; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA bigdata +GRANT SELECT ON TABLES TO PUBLIC; + +CREATE OR REPLACE PROCEDURE bigdata.create_tables( + table_count integer +) LANGUAGE plpgsql AS $$ +DECLARE + table_idx integer; + batch_size integer := 500; +BEGIN + FOR table_idx IN 1..table_count LOOP + EXECUTE format('CREATE TABLE bigdata.data_%s (col text)', table_idx); + + -- This batch_size is to avoid the error: HINT: You might need to increase "max_locks_per_transaction". + IF table_idx % batch_size = 0 THEN + COMMIT; + END IF; + END LOOP; + NOTIFY pgrst; +END; +$$; + +CREATE OR REPLACE FUNCTION bigdata.create_random_table() RETURNS text AS $$ +DECLARE + table_name text := format( + 'new_data_%s', + substring(md5(clock_timestamp()::text || random()::text) from 1 for 12) + ); +BEGIN + EXECUTE format('CREATE TABLE bigdata.%I (col text)', table_name); + NOTIFY pgrst; + RETURN table_name; +END; +$$ LANGUAGE plpgsql; diff --git a/test/io/test_big_schema.py b/test/io/test_big_schema.py index 500087edf4..f2834a553c 100644 --- a/test/io/test_big_schema.py +++ b/test/io/test_big_schema.py @@ -5,6 +5,7 @@ import pytest import requests +from util import psql_as_superuser from postgrest import run @@ -120,3 +121,29 @@ def test_second_request_for_non_existent_table_should_be_quick(defaultenv): first_duration = response.elapsed.total_seconds() response = postgrest.session.get("/unknown-table") assert response.elapsed.total_seconds() < first_duration / 2 + + +def test_new_table_is_immediately_available(defaultenv): + "new table that don't use the schema cache should be immediately available" + + psql_as_superuser("CALL bigdata.create_tables(5000);") + + env = { + **defaultenv, + "PGRST_DB_SCHEMAS": "bigdata", + "PGRST_DB_POOL": "2", + "PGRST_DB_ANON_ROLE": "postgrest_test_anonymous", + } + + with run(env=env, wait_max_seconds=30) as postgrest: + response = postgrest.session.get("/data_1?col=eq.1") + assert response.status_code == 200 + + response = postgrest.session.post("/rpc/create_random_table") + assert response.status_code == 200 + table_name = response.json() + + response = postgrest.session.get(f"/{table_name}?col=eq.1") + if response.status_code == 404: + pytest.xfail("new table returns 404 ") + assert response.status_code == 200 diff --git a/test/io/test_io.py b/test/io/test_io.py index cdaf8cfa73..c273ba2a26 100644 --- a/test/io/test_io.py +++ b/test/io/test_io.py @@ -3,7 +3,6 @@ import os import re import signal -import subprocess import time import pytest import requests @@ -16,6 +15,7 @@ relativeSeconds, drain_stdout, match_log, + psql_as_superuser, ) from postgrest import ( Admin, @@ -33,20 +33,6 @@ ) -def psql_as_superuser(query): - subprocess.check_call( - [ - "psql", - "--username", - "postgres", - "--set", - "ON_ERROR_STOP=1", - "-c", - query, - ] - ) - - def test_connect_with_dburi(dburi, defaultenv): "Connecting with db-uri instead of LIPQ* environment variables should work." defaultenv_without_libpq = { @@ -684,24 +670,15 @@ def test_listener_query_is_visible_in_pg_stat_activity(defaultenv): } with run(env=env): - query = """ -select query -from pg_stat_activity -where application_name = 'listener-query-test' - and query = 'LISTEN "pgrst"' -limit 1; -""" - output = subprocess.check_output( - [ - "psql", - "--set", - "ON_ERROR_STOP=1", - "--tuples-only", - "--no-align", - "-c", - query, - ], - text=True, + output = psql_as_superuser( + """ + select query + from pg_stat_activity + where application_name = 'listener-query-test' + and query = 'LISTEN "pgrst"' + limit 1; + """, + capture_output=True, ).strip() assert output == 'LISTEN "pgrst"' diff --git a/test/io/util.py b/test/io/util.py index 6e0de07473..b9714d6270 100644 --- a/test/io/util.py +++ b/test/io/util.py @@ -1,6 +1,7 @@ import re import threading import jwt +import subprocess from datetime import datetime, timedelta, timezone @@ -75,3 +76,21 @@ def parse_server_timings_header(header): _, duration = duration_text.split("=") timings[name.strip()] = float(duration) return timings + + +def psql_as_superuser(query, capture_output=False): + cmd = [ + "psql", + "--username", + "postgres", + "--set", + "ON_ERROR_STOP=1", + ] + if capture_output: + cmd.extend(["--tuples-only", "--no-align"]) + cmd.extend(["-c", query]) + + if capture_output: + return subprocess.check_output(cmd, text=True) + + subprocess.check_call(cmd)