"""Prevent legacy writers from diverging after an explicit PostgreSQL cutover.""" from pathlib import Path def database_arguments(parser): target = parser.add_mutually_exclusive_group(required=True) target.add_argument('--db', help='Writable SQLite sample; never the frozen production backup') target.add_argument('--pg-service', help='Protected libpq service for the published PostgreSQL dataset') parser.add_argument('--pg-schema', help='Optional schema; otherwise use the configured search_path') def open_store(db=None, *, pg_service=None, pg_schema=None): if bool(db) == bool(pg_service) or (pg_schema and not pg_service): raise ValueError('Choose exactly one of SQLite db or PostgreSQL service; schema requires PostgreSQL') if pg_service: from paper_atlas.postgres.writer import PostgresStore return PostgresStore(pg_service, pg_schema) from paper_atlas.db.store import Store return Store(db) def open_read_connection(db=None, *, pg_service=None, pg_schema=None): if bool(db) == bool(pg_service) or (pg_schema and not pg_service): raise ValueError('Choose exactly one of SQLite db or PostgreSQL service; schema requires PostgreSQL') if pg_service: from paper_atlas.postgres.client import ReadConnection return ReadConnection(pg_service, pg_schema) import sqlite3 path = Path(db).resolve() if not path.is_file(): raise ValueError('Existing database required for read-only audit') connection = sqlite3.connect(path.as_uri() + '?mode=ro', uri=True) try: connection.execute('BEGIN') except BaseException: connection.close() raise return connection def inserted_id(connection, sql, params=()): if getattr(connection, 'postgres', False): return connection.execute(sql + ' RETURNING id', params).fetchone()[0] return connection.execute(sql, params).lastrowid def require_sqlite_writable(path): marker = Path(str(Path(path).resolve()) + '.postgresql-cutover.json') if marker.exists(): raise RuntimeError('This SQLite source was cut over to PostgreSQL; use the configured PostgreSQL database. Marker: ' + str(marker))