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 1tpBBk-001W7j-FO for pgsql-general@arkaria.postgresql.org; Mon, 03 Mar 2025 19:10:52 +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 1tpBBh-00Ec47-IU for pgsql-general@arkaria.postgresql.org; Mon, 03 Mar 2025 19:10:49 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1tpBBh-00Ec3z-8G for pgsql-general@lists.postgresql.org; Mon, 03 Mar 2025 19:10:49 +0000 Received: from sss.pgh.pa.us ([68.162.161.243]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1tpBBf-000lxR-1Q for pgsql-general@lists.postgresql.org; Mon, 03 Mar 2025 19:10:48 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 523JAk4U4063620; Mon, 3 Mar 2025 14:10:46 -0500 From: Tom Lane To: Jakob Teuber cc: pgsql-general@lists.postgresql.org Subject: Re: Infinite loop for generate_series with timestamp arguments In-reply-to: <05676a44-9408-4c15-9309-c0f39ecd511a@tum.de> References: <05676a44-9408-4c15-9309-c0f39ecd511a@tum.de> Comments: In-reply-to Jakob Teuber message dated "Mon, 03 Mar 2025 17:05:10 +0100" MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-ID: <4063618.1741029046.1@sss.pgh.pa.us> Content-Transfer-Encoding: 8bit Date: Mon, 03 Mar 2025 14:10:46 -0500 Message-ID: <4063619.1741029046@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Jakob Teuber writes: > I noticed, that the following query will send Postgres into an infinite > loop: > (a)  select generate_series(timestamp '2025-01-30', timestamp > '2025-02-01', interval '1 month -29 days'); > One could certainly argue that “go and do an infinite loop” is plainly > the intended semantics of this query, but in other cases, Postgres tries > to guard against these types of looping generate_series statements: > (b)  select generate_series(timestamp '2025-03-31', timestamp > '2025-04-01', interval '1 month -30 days'); >         → ERROR:  step size cannot equal zero It does what it can, but there's no chance of being entirely perfect. The core problem here is to figure out which direction the series is intended to advance, so as to know whether the termination test should be "less than" or "greater than" the end timestamp. The way generate_series_timestamp does that is to see whether interval comparison thinks the interval value is less than or greater than a zero interval --- and if it happens to be exactly equal, you get the whine about zero step size. But interval comparison is far from bright: * Interval comparison is based on converting interval values to a linear * representation expressed in the units of the time field (microseconds, * in the case of integer timestamps) with days assumed to be always 24 hours * and months assumed to be always 30 days. We could perhaps do better by doing the initial addition of the interval and seeing if that produces a value greater than, less than, or equal to the start timestamp. But I'm afraid that doesn't move the goalposts very far, because as this example shows, we might get different results in different months. Another idea is to check, after doing each addition, to make sure that the timestamp actually advanced in the expected direction. But should we error out if not, or just stop? regards, tom lane