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.98.2) (envelope-from ) id 1x7YTc-00000000TgS-2K6B for pgsql-bugs@arkaria.postgresql.org; Fri, 18 Sep 2026 13:18:04 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x7YTb-00000001JEw-3bR8 for pgsql-bugs@arkaria.postgresql.org; Fri, 18 Sep 2026 13:18:03 +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.98.2) (envelope-from ) id 1x7OZA-00000007PB5-1s6B for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:43:08 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x7OZ6-000000018Iz-3OZf for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:43:08 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=xbCdsDB3RK8PsA+yN85LbkbOegv4yjIME6gBEHfCIxA=; b=3+j09zg7qsZ9sqo+oAs9nBjnYt s0Lp+XcYeamQqwZG/IyfOVz1DzwO3rtqqNd9/Qk7eEOTzBluU7KzC8axs4fK62VLzHPG0F88di57/ q2NBryGE88K0axoerlbLZXWcT434vPFo+VTs46cexwsrNgyOvKNXSlYi0iccfY3DNHCtAsLwPEQEo 2JDov74YGsXYh64wRQDYS+fy2TO6KlH6IIrBoJPlx7ZmVf7UZp9THQToUU75KGmU2LZFMhZ+NJd/3 6lbhsQTJUsvLUg4tFsyoitMePQQdrNMIj78FsSZ+XhaYkgYQuXpe6d5RrBxh4nbziiq2B0kqDrDXl 0spMTxbg==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x7OZ6-001pXI-1b for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:43:04 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x7OZ5-00000006omc-1lh1 for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:43:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19694: MIN()/MAX() fails with "more than one row returned by a subquery" under FETCH FIRST ... WITH TIES To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: chaitanyyachoudhary@gmail.com Reply-To: chaitanyyachoudhary@gmail.com, pgsql-bugs@lists.postgresql.org Date: Fri, 18 Sep 2026 02:42:42 +0000 Message-ID: <19694-4e61bd0475398eef@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19694 Logged by: Chaitanya Choudhary Email address: chaitanyyachoudhary@gmail.com PostgreSQL version: 18.6 Operating system: macOS 26 (aarch64), Homebrew build of 18.6 Description: =20 An aggregate query with ORDER BY and FETCH FIRST n ROWS WITH TIES fails with an error when the planner chooses the index path for MIN() or MAX(). The same query succeeds with ROWS ONLY, with LIMIT, or when the index path is disabled. Steps to reproduce: CREATE TABLE t (v int); INSERT INTO t SELECT g % 100 FROM generate_series(1, 1000) g; CREATE INDEX ON t (v); ANALYZE t; SELECT min(v) FROM t ORDER BY 1 FETCH FIRST 1 ROWS WITH TIES; Result: ERROR: more than one row returned by a subquery used as an expression Expected: one row, min =3D 0. An aggregate without GROUP BY returns exactly one row, so WITH TIES cannot add rows. These all return 0 as expected: SELECT min(v) FROM t ORDER BY 1 FETCH FIRST 1 ROWS ONLY; SELECT min(v) FROM t ORDER BY 1 LIMIT 1; SET enable_indexscan =3D off; SET enable_indexonlyscan =3D off; SET enable_bitmapscan =3D off; SELECT min(v) FROM t ORDER BY 1 FETCH FIRST 1 ROWS WITH TIES; The plan for the failing query: Limit InitPlan 1 -> Limit -> Index Only Scan using t_v_idx on t Index Cond: (v IS NOT NULL) -> Sort Sort Key: ((InitPlan 1).col1) -> Result Cause: build_minmax_path() in src/backend/optimizer/plan/planagg.c builds the subquery for the aggregate by copying the outer Query and then rewriting sortClause, limitOffset and limitCount (LIMIT 1). It does not reset limitOption, so the copy keeps LIMIT_OPTION_WITH_TIES from the outer query. create_minmaxagg_plan() in src/backend/optimizer/plan/createplan.c then builds the initplan's Limit node with subparse->limitOption: plan =3D (Plan *) make_limit(plan, subparse->limitOffset, subparse->limitCount, subparse->limitOption, 0, NULL, NULL, NULL); A Limit node with WITH TIES and no tie columns (uniqNumCols =3D 0) treats every row as a tie, so the initplan returns the whole index scan instead of one row, and the initplan check raises the error. Fix: set parse->limitOption =3D LIMIT_OPTION_COUNT in build_minmax_path() next to where limitCount is set, or pass LIMIT_OPTION_COUNT in create_minmaxagg_plan(). The initplan is always a plain LIMIT 1. The same code is present on REL_18_STABLE and master as of 2026-09-17.