Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1v1AA3-005COO-BF for pgsql-general@arkaria.postgresql.org; Tue, 23 Sep 2025 21:02:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1v1AA1-008CYl-Od for pgsql-general@arkaria.postgresql.org; Tue, 23 Sep 2025 21:02:53 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1v1AA1-008CYc-Da for pgsql-general@lists.postgresql.org; Tue, 23 Sep 2025 21:02:53 +0000 Received: from mail-lf1-x133.google.com ([2a00:1450:4864:20::133]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1v1A9x-002V2M-0m for pgsql-general@lists.postgresql.org; Tue, 23 Sep 2025 21:02:53 +0000 Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-57a670b65b9so389866e87.1 for ; Tue, 23 Sep 2025 14:02:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1758661370; x=1759266170; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=NfIbMwHxke8i5VcEcClU/ov4CE5KQD47NRtWhqmgidw=; b=layGNLUsEflssI7SudwL53rafcH/Sh56a58NQh1HQiVtfjUukOOZxhjIYpLP6FdMcG rK7++NCKLT6h3+81dKAh4C6h05/S+ZzQ3SHKSc7P4bseiqTfyYMAiQMeMUEKWUY9IF+B zDd5d4TzKkPf1od3VbmdQiFfHimf6i6DCBvVGh4ske3jqbzh1UsImbncoqTUZ40pRgKB 5F7dVPcxLffut6ppm43t6TQaeS1F2EDTGF0XW/twVaMVFTFuAicGlG8nMVXXGU32lzOB T/55Ie9DqH0tkvWE4snq/+SfGgfFzjFpMFKImonh0U43tlz1vWtwLMSPKiYScV3x4orP F9Wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758661370; x=1759266170; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NfIbMwHxke8i5VcEcClU/ov4CE5KQD47NRtWhqmgidw=; b=HtXuFJv0HMYVZ8epAeR6+3/2O6UIB3gQ9faMdajVmF4DGjlIe/TFGWrMfECnMZYC38 YZXjJccNQbAMBPbxx8Xiq0l7xQe63/9L6mZ48UyFB/Ox0VD6ko/e5P61syp70liIBAVY GbhcegZl7rG99tSmoV1IgybF8BR4sVlx2PkMhSI8XGj+t/gOOyExWJ16gkv1tE6QfsDj SB7gy4ae7Idfbz4xzEU8ERIvkWbRF2QEFF+uU7O9/y4iBP73CanTXzFsFcZBGG6tfEqx 0ossT3IatKDqnPOp1wOlJ3W2oUwgy3Cxp8TQaT/pHeeISqZrgyC/Q5rxbQolfR91ugto UKag== X-Gm-Message-State: AOJu0YyWhnAZIQ3dA+hkI8Xvo07PJQAQqqs/BpG9jM4OPTVJx87Qj3FT 5fG525RW+fwuJX4eIuvI0/EZsEvlj/SJ68SBejY2fiy1vnsJEfuixgO7Tcuy6/Eog755HJf30e8 pdX3RKwnXHgv+wZCtrZvOwD7NxelY0I8= X-Gm-Gg: ASbGncvxBA40QUsuP42LoFmuYDn6ffq1+HTmIt2UqGUgwK5WJFbGwbNjIbNxIQsCQAR 6OPmvgUUlHmfjGUxHZLnfm6Ym7srGdu+UW2y/AvM3oUUsxMItMj1/uXGLjZhOM3vrB6sy4rGUxf aWt9s4r1JctqTde+mI7USmHBraft7Pm7TCOOQScsjB9YAJVudTS49U7Q7NcOF7kYo2Ar7c4dydM hyExU7N X-Google-Smtp-Source: AGHT+IHBmzOm9g493YcKoqh9dvqflG52B5wiTdRkQu8I2Y5QK5ZufINhQc0Qhg2BTrV+zBULVSfEoCWi1+9vsTT2bTY= X-Received: by 2002:a05:651c:31ca:20b0:337:f259:7b7a with SMTP id 38308e7fff4ca-36d16cf1117mr4793061fa.6.1758661369657; Tue, 23 Sep 2025 14:02:49 -0700 (PDT) MIME-Version: 1.0 References: <0bed88ec-d205-4202-81fe-d8ad990e1122@aklaver.com> In-Reply-To: <0bed88ec-d205-4202-81fe-d8ad990e1122@aklaver.com> From: Samuel Marks Date: Tue, 23 Sep 2025 16:02:38 -0500 X-Gm-Features: AS18NWDQHTBCT3yeHTRr4-ePkQlpHb8PS8KLWt9AfAE5A_OCFUkbaGcR-PiF4uA Message-ID: Subject: Re: How do I upsert depending on a second table? To: Adrian Klaver Cc: pgsql-general@lists.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: Archived-At: Precedence: bulk Yeah I know my approach doesn't work, my question is, what is the correct way to do an upsert for this schema? Specifically: - Create a new repo if one by that name doesn't exist + requestor is `owner` of associated `org` - Update an existing repo if one by that name does exist + requestor is `owner` of associated `org` On Tue, Sep 23, 2025 at 3:57=E2=80=AFPM Adrian Klaver wrote: > > On 9/23/25 13:36, Samuel Marks wrote: > > Attempt: > > ```sql > > CREATE TABLE org > > ( > > "name" VARCHAR(50) PRIMARY KEY, > > owner VARCHAR(50) NOT NULL > > ); > > > > CREATE TABLE repo > > ( > > "id" INTEGER PRIMARY KEY, > > full_name VARCHAR(255) UNIQUE NOT NULL, > > org VARCHAR(50) NOT NULL REFERENCES org ("name"= ) > > ); > > > > INSERT INTO org(name, owner) VALUES ('org0', 'user0'); > > > > INSERT INTO repo (id, full_name, org) > > VALUES (0, 'org0/name0 by wrong user', 'org0') > > ON CONFLICT (full_name) DO UPDATE > > SET full_name =3D EXCLUDED.full_name, > > org =3D EXCLUDED.org > > WHERE EXISTS (SELECT 1 > > FROM org org_tbl > > WHERE org_tbl.name =3D EXCLUDED.org > > AND org_tbl.owner =3D 'wrong user') > > RETURNING *; > > > > SELECT * FROM repo WHERE id =3D 0; > > ``` > > Also, as shown, there is no conflict so I don't see the condition being > run per: > > https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT > > " > condition > > An expression that returns a value of type boolean. Only rows for > which this expression returns true will be updated, although all rows > will be locked when the ON CONFLICT DO UPDATE action is taken. Note that > condition is evaluated last, after a conflict has been identified as a > candidate to update. > > " > > > > This all succeeds. It should fail because the 'wrong user' is trying > > to create a new=E2=80=94or update an existing=E2=80=94repo. > > > > Thanks for all suggestions > > > > > > > -- > Adrian Klaver > adrian.klaver@aklaver.com