Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kc5PR-0002Dg-0w for psycopg@arkaria.postgresql.org; Mon, 09 Nov 2020 11:32:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kc5PP-0001KJ-Lf for psycopg@arkaria.postgresql.org; Mon, 09 Nov 2020 11:32:27 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kc5PP-0001K6-Dk for psycopg@lists.postgresql.org; Mon, 09 Nov 2020 11:32:27 +0000 Received: from mail-lj1-x231.google.com ([2a00:1450:4864:20::231]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1kc5PN-0003mi-80 for psycopg@postgresql.org; Mon, 09 Nov 2020 11:32:26 +0000 Received: by mail-lj1-x231.google.com with SMTP id v18so9866275ljc.3 for ; Mon, 09 Nov 2020 03:32:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=KCVy9NV4V3Rq3kQgDv6Hro4oXVqbVY2Y0paEappHmy0=; b=Zy2idLxevT4DZEnrjhpwtRbSbbH51orRVBhDh4tfs8+2Ye307RsUdH/DQ5m4hI8sw+ oqCfUgAYAhLZ5Dt12gOaseoALQ0UGRyBDVeqounf6NQgXC1HvNsjuhuxQfRJF48k2TC7 KwIPnvZoIubsGsIYe88GLfBdqN0qzbFfKBUBEOHCziXx7z37/YGeaxQ3u0/xJ5YKwHh4 NZrzBKXZQzZN5Y1NlHbGlcWEwnFoc1GI3lT42WxiY6NsIKxYYko3e4d8iVouoR9Jshe1 Ezx9B6v0Aumx4eWvsxm7uleDiLyqQH86KE6bs5b7DP7gl9guL3Sppd4Hek+Jqw4/B4Ng qS8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=KCVy9NV4V3Rq3kQgDv6Hro4oXVqbVY2Y0paEappHmy0=; b=IGqUtI+v8KaZ5efxMS/hmxpj6qgsE5crL1Tj1zydP8fNpCnQvvidFyRZSbXTymTnPQ IAXKm4dVsoI7BZ4Ot62xTYiNgPhpiLTp55iZTO5yU6TGU5p0BHQRr1bUwbQdvQTACC4B oJKihtiDGbAESn5NMRBe9dkhwuw2jXw8oh0KdeqNjh0zRI3m0pnTKbh+lZqxOnfcHnLe NpvSZi3Y9bi5tdWzxWbKAyMGov3AYpwtzU6Ps7ME1iLmNEyYm1XF4WLjODFjv9SfjTHW Tr1Cmr1wp4P9ORpdvyaucfp4Xw2HsLFVtmAJqQhCIRYq2bHmFPKwvpQgLoG0W0LNl3tC QAsw== X-Gm-Message-State: AOAM532+xQZNN7PfFJISBBaM34Ye7sMe1R7Gonv4lV2F0r9OoS026JGD naj8AUbh2gXbEkUhE/2xYnHvgQ7GiPz7sYOQZyH+38mgBu4naQ== X-Google-Smtp-Source: ABdhPJzkPvd+aPEtbd6mUSLPTt+0P0SwAQxfZo3nSIvW5ctWM45IDZiIZUbiQQ72MGRjbk9UDOGnM2eoooduJgHA9R0= X-Received: by 2002:a05:651c:1025:: with SMTP id w5mr5693444ljm.14.1604921543586; Mon, 09 Nov 2020 03:32:23 -0800 (PST) MIME-Version: 1.0 References: <2b9859f0-0964-2baa-b6bc-13f975ae0f67@aklaver.com> <88fb7a7e-a182-a816-c1a7-8a1f54b65215@aklaver.com> In-Reply-To: From: Daniele Varrazzo Date: Mon, 9 Nov 2020 11:32:12 +0000 Message-ID: Subject: Re: psycopg3 and adaptation choices To: Vladimir Ryabtsev Cc: Adrian Klaver , psycopg@postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Mon, 9 Nov 2020 at 02:49, Vladimir Ryabtsev wrote= : > > A wild idea: support both client-side (like in psycopg2) and server-side = binding. Keep old '%s' syntax and provide a separate method for client-side= binding (not in 'cur.execute()'). This could alleviate cases like paramete= rs roundtripping and other cases of safe query composition. At the same tim= e use '$N' for true server-side binding. > Is it an overcomplication or there are valid use-cases of that? Such a thing exists already: there is a client-side binding library, which is pretty much a direct porting of the psycopg2.sql module (https://www.psycopg.org/docs/sql.html). Using that facility, you can compose argument client-side with `query =3D sql.SQL("select {}, %s").format("hello")` and pass the above to `cursor.execute(query, [42]). It uses `{}` and `{name}`-style parameters to bind client-side so it leaves %s placeholders untouched for execute(). In psycopg3 I've made it slightly easier to use by letting `SQL.format()` to accept any Python object, and automatically wrapping it into a `Literal()` object, whereas in psycopg2 `format()` only accepted "`Composible`" objects, and you should have written the above as `sql.SQL("select {}, %s").format(Literal("hello"))`. -- Daniele