@@ -945,18 +945,31 @@ def refresh_pygeoapi_materialized_views(
945945):
946946 from sqlalchemy import text
947947
948- from db .engine import session_ctx
948+ from db .engine import engine , session_ctx
949949
950950 target_views = tuple (view ) if view else PYGEOAPI_MATERIALIZED_VIEWS
951- refresh_clause = "CONCURRENTLY " if concurrently else ""
952951
953- with session_ctx () as session :
954- for view_name in target_views :
955- safe_view = _validate_sql_identifier (view_name )
956- session .execute (
957- text (f"REFRESH MATERIALIZED VIEW { refresh_clause } { safe_view } " )
958- )
959- session .commit ()
952+ if concurrently :
953+ # PostgreSQL requires REFRESH MATERIALIZED VIEW CONCURRENTLY to run
954+ # outside of a transaction block, so we use an AUTOCOMMIT connection
955+ # instead of a Session (which would wrap the call in a transaction).
956+ with engine .connect ().execution_options (
957+ isolation_level = "AUTOCOMMIT"
958+ ) as conn :
959+ for view_name in target_views :
960+ safe_view = _validate_sql_identifier (view_name )
961+ conn .execute (
962+ text (f"REFRESH MATERIALIZED VIEW CONCURRENTLY { safe_view } " )
963+ )
964+ else :
965+ # Non-concurrent refresh can safely run inside a transaction.
966+ with session_ctx () as session :
967+ for view_name in target_views :
968+ safe_view = _validate_sql_identifier (view_name )
969+ session .execute (
970+ text (f"REFRESH MATERIALIZED VIEW { safe_view } " )
971+ )
972+ session .commit ()
960973
961974 typer .echo (f"Refreshed { len (target_views )} materialized view(s)." )
962975
0 commit comments