добавленные пикодата опции перетирают пользовательские опции

в рамках #64 (closed) были введены дополнительные опции для соединений (см STMT_INVALIDATION_OPTION)

несмотря на то, что опция добавляется в server_settings, расширяя, а не заменяя -- тут затесался баг. дело в том, что asyncpg при конфликте опций в DSN и в connect_kwargs, разрешает их в сторону connect_kwargs. таким образом, если в DSN указать options, то они затрутся (т.к. общий ключ option)

в рамках починки мы также не можем перенести специальные опции пикодата в DSN, т.к. если пользователь задаст опции в connect_kwargs -- уже они перетрут опции пикодата

таким образом, нам нужно учитывать DSN на этапе обогащения опций. необходимо проверять, есть ли в DSN опции и если есть -- добавлять их тоже, при этом оставить опции connect_kwargs в приоритете

репро:


import asyncio
import os

from picopyn.asynchronous.connection import Connection

BASE = os.environ.get("PICODATA_TEST_CONN", "postgresql://admin:T0psecret@localhost:5433")
DSN = f"{BASE}?options=sql_vdbe_opcode_max%3D1"

QUERY = "SELECT 1"

async def main():
    print(f"option asked for in DSN {DSN}")

    conn = Connection(DSN)
    try:
        await conn.connect()
    except RuntimeError as e:
        print(f"cannot connect: {e}")
        return

    try:
        rows = await conn.fetch(QUERY)
    except Exception as e:
        text = str(e).lower()
        if "vdbe" in text or "opcode" in text:
            print(f"query `{QUERY}` failed on the limit: {e}")
            print("the option from DSN reached Picodata")
            return
        print(f"query failed for an unrelated reason, so possibly the DSN option never Picodata: {e!r}")
        return
    else:
        print(f"query succeeded, returned {len(rows)} row(s)")
        print("the DSN option never reached Picodata")
        return
    finally:
        await conn.close()


asyncio.run(main())
Edited by Asya Lomakina