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 1tUslZ-003X8U-OM for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jan 2025 19:27:58 +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 1tUslZ-00Bfqs-84 for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jan 2025 19:27:56 +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 1tUslY-00Bfqk-Rq for pgsql-hackers@lists.postgresql.org; Mon, 06 Jan 2025 19:27:56 +0000 Received: from mail-pl1-x62d.google.com ([2607:f8b0:4864:20::62d]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1tUslV-000DDr-1k for pgsql-hackers@postgresql.org; Mon, 06 Jan 2025 19:27:56 +0000 Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-21a1e6fd923so15187785ad.1 for ; Mon, 06 Jan 2025 11:27:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1736191672; x=1736796472; darn=postgresql.org; h=user-agent:content-disposition:mime-version:message-id:subject:to :from:date:from:to:cc:subject:date:message-id:reply-to; bh=SFp/6KFGCBzW13nouCGnkRi8M8T9oOdn3y4wpXT05qw=; b=VuC4xxFKCme3X18NIh/I0x+iu91GvUNS2wkfk8+/3T6YKPFw0RINU0dYXQcFAOmr50 lUbrmwgbqF6lJxPW/nYJqAZuA/fD4qLcfpwpyDVt5zbtsvp7wb32q6qMTD8R1Y65O37z nUz/QeQlfgSs3m3hnsLL41jPqahRofbyr+R+Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736191672; x=1736796472; h=user-agent:content-disposition:mime-version:message-id:subject:to :from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=SFp/6KFGCBzW13nouCGnkRi8M8T9oOdn3y4wpXT05qw=; b=b3l4s0oB28dgPvTjVNiiHaMvfQMVY2AJYeU16v9RmluLzMiJC75SA5Iv7sUOfdJ6+i SpHTwY1w91dF7jELwYaL2K77qW9Ms3PG1H+Chifk2f3i8eglH3D2YEvFZ61KNMHfEL6k UOZawngXpfMmNo1ws2PhVFlaYA+Xb29KGQdKws19RzNJp/stOvmAMSZQdS3Qxd600BB+ 26GvD2qKFajp3WNDb+GJrVql+xx30l2I2AXiOJ3niYvXSvGxM3BT/qh+70LvGAzfJBos z/zsaevIEFw+lyMA089CqVo1T/6peYFUl4RyY5BBz2qG6NOe0s3Pmk3XpXc0ZQmNi77N eIdA== X-Gm-Message-State: AOJu0YwMl3s55sq9HrzISfvxMwMI1jZgfqKzspR0qpiP7FmL2LEsELvl Z3qFqiApWDVLboZwHHA3BEOgQfNglm3nS28gMevedjHqre5TaU7mbhCbwe44/k5+YgfQ9wZ8pSC aOg== X-Gm-Gg: ASbGncvl4E3ijM9biBt6mojS87WLWRgyWPvBSCGse9/4wRioCyCJTL4b8sJMOaEtmid VTHRR01xgQZFD5As/0RXrGym4joihHS3yEoRsY+oqNgOlIg9PoOO+oB+TL+TLcqqrj8rctaTkwt yIjnfTvNLkiOSKJQJam9zLdikMXSkasGbc2Wnrx9XsATi99ttpcrKcfRMfOHP15YpYspU9kKXYI 9ttDX1Lw1dJIg2WK0J7nRAexVHrwcGZcixEJGfK68U6/qSBf5k= X-Google-Smtp-Source: AGHT+IHL9s6uoQp4uif6WbYINwykO1OQsKTaZNObgZ4/CZzBM5K1deqJGFqxjflXiCUV+OVp415G3A== X-Received: by 2002:a05:6a00:91cb:b0:725:eb85:f7f7 with SMTP id d2e1a72fcca58-72abdd20f5emr81295531b3a.5.1736191671444; Mon, 06 Jan 2025 11:27:51 -0800 (PST) Received: from google.com ([2600:1702:a20:5750::48]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72aad90c149sm31818460b3a.191.2025.01.06.11.27.50 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Jan 2025 11:27:50 -0800 (PST) Date: Mon, 6 Jan 2025 11:27:48 -0800 From: Noah Misch To: pgsql-hackers@postgresql.org Subject: ECPG deccall3 functions vs. risnull() inputs Message-ID: <20250106192748.cf.nmisch@google.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="JvxchO/wJ+olBE97" Content-Disposition: inline User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --JvxchO/wJ+olBE97 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline When I compiled with -ftrivial-auto-var-init=pattern, ECPG's dec_test reported a diff. Nothing else reported a diff. dec_test calls informix.c numeric functions like decadd() and decmul(). One test operand, decarr[14], is risnull(). When these informix.c functions get an risnull() input, they just return 0 without changing the output parameter. Our ecpg.sgml docs don't discuss this. Applicable Informix doc https://www.ibm.com/docs/en/informix-servers/15.0.0?topic=information-null-values-in-host-variables just says "do not attempt to perform arithmetic", which I take to assign undefined behavior for risnull() input. If someone can easily check how Informix works for this, would you do so? Before commit 757fb0e (2004-03), these functions would rsetnull() the output parameter if given risnull() input. That's like the effect of SQL NULL input to a SQL arithmetic operator. I suspect the change for risnull() input was an unintentional side effect of that commit's mission to make dec*() functions support callers passing the same var as both an input and an output. Two patches attached. The first patch just makes the test clarify what's happening. The second would restore the pre-2004 behavior, but I plan to commit that one only if someone's Informix testing confirms it. --JvxchO/wJ+olBE97 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="test-deccall3-null-v1.patch" Author: Noah Misch Commit: Noah Misch Test ECPG decadd(), decdiv(), decmul(), and decsub() for risnull() input. Since commit 757fb0e5a9a61ac8d3a67e334faeea6dc0084b3f, these Informix-compat functions return 0 without changing the output parameter. Initialize the output parameter before the test call, making that obvious. Before this, the expected test output has been depending on freed stack memory. "gcc -ftrivial-auto-var-init=pattern" revealed that. Back-patch to v13 (all supported versions). Reviewed by FIXME. Discussion: https://postgr.es/m/FIXME diff --git a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc index f6a9f42..830ab58 100644 --- a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc +++ b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc @@ -142,6 +142,16 @@ main(void) c = deccmp(decarr[i], decarr[j]); printf("dec[c,%d,%d]: %d\n", i, j, c); + /* + * decarr[count-1] is risnull(), which makes these functions + * return 0 without changing the output parameter. Make that + * clear by initializing each output parameter. + */ + deccvint(7654321, &a); + deccvint(7654321, &s); + deccvint(7654321, &m); + deccvint(7654321, &d); + r = decadd(decarr[i], decarr[j], &a); if (r) { diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c index 8586650..3e68b2e 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c +++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c @@ -195,6 +195,16 @@ main(void) c = deccmp(decarr[i], decarr[j]); printf("dec[c,%d,%d]: %d\n", i, j, c); + /* + * decarr[count-1] is risnull(), which makes these functions + * return 0 without changing the output parameter. Make that + * clear by initializing each output parameter. + */ + deccvint(7654321, &a); + deccvint(7654321, &s); + deccvint(7654321, &m); + deccvint(7654321, &d); + r = decadd(decarr[i], decarr[j], &a); if (r) { diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout index 71a5afa..7e50493 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout +++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout @@ -222,10 +222,10 @@ dec[s,0,13]: dec[m,0,13]: * dec[d,0,13]: dec[c,0,14]: 2147483647 -dec[a,0,14]: -dec[s,0,14]: -dec[m,0,14]: * -dec[d,0,14]: +dec[a,0,14]: 7654321.0 +dec[s,0,14]: 7654321.0 +dec[m,0,14]: 7654321.0 +dec[d,0,14]: 7654321.0 dec[c,1,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,1,0]: @@ -297,10 +297,10 @@ dec[s,1,13]: -1234567890123456789012345680.91 dec[m,1,13]: -2469135780246913578024691357.82 dec[d,1,13]: -0.0000000000000000000000000016200000145800001 dec[c,1,14]: 2147483647 -dec[a,1,14]: 1234567890123456789012345676.91 -dec[s,1,14]: -1234567890123456789012345680.91 -dec[m,1,14]: -2469135780246913578024691357.82 -dec[d,1,14]: -0.0000000000000000000000000016200000145800001 +dec[a,1,14]: 7654321.0 +dec[s,1,14]: 7654321.0 +dec[m,1,14]: 7654321.0 +dec[d,1,14]: 7654321.0 dec[c,2,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,2,0]: @@ -372,10 +372,10 @@ dec[s,2,13]: dec[m,2,13]: dec[d,2,13]: 0.00000000000000000000000000064314000578826005 dec[c,2,14]: 2147483647 -dec[a,2,14]: -dec[s,2,14]: -dec[m,2,14]: -dec[d,2,14]: 0.00000000000000000000000000064314000578826005 +dec[a,2,14]: 7654321.0 +dec[s,2,14]: 7654321.0 +dec[m,2,14]: 7654321.0 +dec[d,2,14]: 7654321.0 dec[c,3,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,3,0]: @@ -447,10 +447,10 @@ dec[s,3,13]: -1234567890123456789012345675.47 dec[m,3,13]: dec[d,3,13]: 0.0000000000000000000000000027864000250776002 dec[c,3,14]: 2147483647 -dec[a,3,14]: 1234567890123456789012345682.35 -dec[s,3,14]: -1234567890123456789012345675.47 -dec[m,3,14]: -dec[d,3,14]: 0.0000000000000000000000000027864000250776002 +dec[a,3,14]: 7654321.0 +dec[s,3,14]: 7654321.0 +dec[m,3,14]: 7654321.0 +dec[d,3,14]: 7654321.0 dec[c,4,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,4,0]: @@ -522,10 +522,10 @@ dec[s,4,13]: -1233975400123456789012345678.91 dec[m,4,13]: dec[d,4,13]: 0.00047991690431925214 dec[c,4,14]: 2147483647 -dec[a,4,14]: 1235160380123456789012345678.91 -dec[s,4,14]: -1233975400123456789012345678.91 -dec[m,4,14]: -dec[d,4,14]: 0.00047991690431925214 +dec[a,4,14]: 7654321.0 +dec[s,4,14]: 7654321.0 +dec[m,4,14]: 7654321.0 +dec[d,4,14]: 7654321.0 dec[c,5,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,5,0]: @@ -597,10 +597,10 @@ dec[s,5,13]: -1234567890123456789012674078.91 dec[m,5,13]: dec[d,5,13]: -0.00000000000000000000026600400239403602 dec[c,5,14]: 2147483647 -dec[a,5,14]: 1234567890123456789012017278.91 -dec[s,5,14]: -1234567890123456789012674078.91 -dec[m,5,14]: -dec[d,5,14]: -0.00000000000000000000026600400239403602 +dec[a,5,14]: 7654321.0 +dec[s,5,14]: 7654321.0 +dec[m,5,14]: 7654321.0 +dec[d,5,14]: 7654321.0 dec[c,6,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,6,0]: @@ -672,10 +672,10 @@ dec[s,6,13]: dec[m,6,13]: * dec[d,6,13]: * dec[c,6,14]: 2147483647 -dec[a,6,14]: -dec[s,6,14]: -dec[m,6,14]: * -dec[d,6,14]: * +dec[a,6,14]: 7654321.0 +dec[s,6,14]: 7654321.0 +dec[m,6,14]: 7654321.0 +dec[d,6,14]: 7654321.0 dec[c,7,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,7,0]: @@ -747,10 +747,10 @@ dec[s,7,13]: dec[m,7,13]: 1234567890123456789012345.67891 dec[d,7,13]: 0.00000000000000000000000000000081000000729000007 dec[c,7,14]: 2147483647 -dec[a,7,14]: -dec[s,7,14]: -dec[m,7,14]: 1234567890123456789012345.67891 -dec[d,7,14]: 0.00000000000000000000000000000081000000729000007 +dec[a,7,14]: 7654321.0 +dec[s,7,14]: 7654321.0 +dec[m,7,14]: 7654321.0 +dec[d,7,14]: 7654321.0 dec[c,8,0]: -1 dec[a,8,0]: * dec[s,8,0]: * @@ -822,10 +822,10 @@ dec[s,8,13]: -1234567890123456789012345678.91 dec[m,8,13]: 0.000 dec[d,8,13]: 0 dec[c,8,14]: 2147483647 -dec[a,8,14]: 1234567890123456789012345678.91 -dec[s,8,14]: -1234567890123456789012345678.91 -dec[m,8,14]: 0.000 -dec[d,8,14]: 0 +dec[a,8,14]: 7654321.0 +dec[s,8,14]: 7654321.0 +dec[m,8,14]: 7654321.0 +dec[d,8,14]: 7654321.0 dec[c,9,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,9,0]: @@ -897,10 +897,10 @@ dec[s,9,13]: dec[m,9,13]: dec[d,9,13]: -0.000000000000000000000000000000047991690431925214 dec[c,9,14]: 2147483647 -dec[a,9,14]: -dec[s,9,14]: -dec[m,9,14]: -dec[d,9,14]: -0.000000000000000000000000000000047991690431925214 +dec[a,9,14]: 7654321.0 +dec[s,9,14]: 7654321.0 +dec[m,9,14]: 7654321.0 +dec[d,9,14]: 7654321.0 dec[c,10,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,10,0]: @@ -972,10 +972,10 @@ dec[s,10,13]: dec[m,10,13]: dec[d,10,13]: 0.0000000000000000000000000000026600400239403602 dec[c,10,14]: 2147483647 -dec[a,10,14]: -dec[s,10,14]: -dec[m,10,14]: -dec[d,10,14]: 0.0000000000000000000000000000026600400239403602 +dec[a,10,14]: 7654321.0 +dec[s,10,14]: 7654321.0 +dec[m,10,14]: 7654321.0 +dec[d,10,14]: 7654321.0 dec[c,11,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,11,0]: @@ -1047,10 +1047,10 @@ dec[s,11,13]: dec[m,11,13]: dec[d,11,13]: 0.00000000000000000000000000040500081364500732 dec[c,11,14]: 2147483647 -dec[a,11,14]: -dec[s,11,14]: -dec[m,11,14]: -dec[d,11,14]: 0.00000000000000000000000000040500081364500732 +dec[a,11,14]: 7654321.0 +dec[s,11,14]: 7654321.0 +dec[m,11,14]: 7654321.0 +dec[d,11,14]: 7654321.0 dec[c,12,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,12,0]: @@ -1122,10 +1122,10 @@ dec[s,12,13]: dec[m,12,13]: dec[d,12,13]: -0.00000000000000000000000000040500008464500076 dec[c,12,14]: 2147483647 -dec[a,12,14]: -dec[s,12,14]: -dec[m,12,14]: -dec[d,12,14]: -0.00000000000000000000000000040500008464500076 +dec[a,12,14]: 7654321.0 +dec[s,12,14]: 7654321.0 +dec[m,12,14]: 7654321.0 +dec[d,12,14]: 7654321.0 dec[c,13,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,13,0]: @@ -1197,85 +1197,85 @@ dec[s,13,13]: 0.00 dec[m,13,13]: dec[d,13,13]: 1.00000000000000000 dec[c,13,14]: 2147483647 -dec[a,13,14]: 2469135780246913578024691357.82 -dec[s,13,14]: 0.00 -dec[m,13,14]: -dec[d,13,14]: 1.00000000000000000 +dec[a,13,14]: 7654321.0 +dec[s,13,14]: 7654321.0 +dec[m,13,14]: 7654321.0 +dec[d,13,14]: 7654321.0 dec[c,14,0]: 2147483647 -dec[a,14,0]: 2469135780246913578024691357.82 -dec[s,14,0]: 0.00 -dec[m,14,0]: -dec[d,14,0]: 1.00000000000000000 +dec[a,14,0]: 7654321.0 +dec[s,14,0]: 7654321.0 +dec[m,14,0]: 7654321.0 +dec[d,14,0]: 7654321.0 dec[c,14,1]: 2147483647 -dec[a,14,1]: 2469135780246913578024691357.82 -dec[s,14,1]: 0.00 -dec[m,14,1]: -dec[d,14,1]: 1.00000000000000000 +dec[a,14,1]: 7654321.0 +dec[s,14,1]: 7654321.0 +dec[m,14,1]: 7654321.0 +dec[d,14,1]: 7654321.0 dec[c,14,2]: 2147483647 -dec[a,14,2]: 2469135780246913578024691357.82 -dec[s,14,2]: 0.00 -dec[m,14,2]: -dec[d,14,2]: 1.00000000000000000 +dec[a,14,2]: 7654321.0 +dec[s,14,2]: 7654321.0 +dec[m,14,2]: 7654321.0 +dec[d,14,2]: 7654321.0 dec[c,14,3]: 2147483647 -dec[a,14,3]: 2469135780246913578024691357.82 -dec[s,14,3]: 0.00 -dec[m,14,3]: -dec[d,14,3]: 1.00000000000000000 +dec[a,14,3]: 7654321.0 +dec[s,14,3]: 7654321.0 +dec[m,14,3]: 7654321.0 +dec[d,14,3]: 7654321.0 dec[c,14,4]: 2147483647 -dec[a,14,4]: 2469135780246913578024691357.82 -dec[s,14,4]: 0.00 -dec[m,14,4]: -dec[d,14,4]: 1.00000000000000000 +dec[a,14,4]: 7654321.0 +dec[s,14,4]: 7654321.0 +dec[m,14,4]: 7654321.0 +dec[d,14,4]: 7654321.0 dec[c,14,5]: 2147483647 -dec[a,14,5]: 2469135780246913578024691357.82 -dec[s,14,5]: 0.00 -dec[m,14,5]: -dec[d,14,5]: 1.00000000000000000 +dec[a,14,5]: 7654321.0 +dec[s,14,5]: 7654321.0 +dec[m,14,5]: 7654321.0 +dec[d,14,5]: 7654321.0 dec[c,14,6]: 2147483647 -dec[a,14,6]: 2469135780246913578024691357.82 -dec[s,14,6]: 0.00 -dec[m,14,6]: -dec[d,14,6]: 1.00000000000000000 +dec[a,14,6]: 7654321.0 +dec[s,14,6]: 7654321.0 +dec[m,14,6]: 7654321.0 +dec[d,14,6]: 7654321.0 dec[c,14,7]: 2147483647 -dec[a,14,7]: 2469135780246913578024691357.82 -dec[s,14,7]: 0.00 -dec[m,14,7]: -dec[d,14,7]: 1.00000000000000000 +dec[a,14,7]: 7654321.0 +dec[s,14,7]: 7654321.0 +dec[m,14,7]: 7654321.0 +dec[d,14,7]: 7654321.0 dec[c,14,8]: 2147483647 -dec[a,14,8]: 2469135780246913578024691357.82 -dec[s,14,8]: 0.00 -dec[m,14,8]: -dec[d,14,8]: 1.00000000000000000 +dec[a,14,8]: 7654321.0 +dec[s,14,8]: 7654321.0 +dec[m,14,8]: 7654321.0 +dec[d,14,8]: 7654321.0 dec[c,14,9]: 2147483647 -dec[a,14,9]: 2469135780246913578024691357.82 -dec[s,14,9]: 0.00 -dec[m,14,9]: -dec[d,14,9]: 1.00000000000000000 +dec[a,14,9]: 7654321.0 +dec[s,14,9]: 7654321.0 +dec[m,14,9]: 7654321.0 +dec[d,14,9]: 7654321.0 dec[c,14,10]: 2147483647 -dec[a,14,10]: 2469135780246913578024691357.82 -dec[s,14,10]: 0.00 -dec[m,14,10]: -dec[d,14,10]: 1.00000000000000000 +dec[a,14,10]: 7654321.0 +dec[s,14,10]: 7654321.0 +dec[m,14,10]: 7654321.0 +dec[d,14,10]: 7654321.0 dec[c,14,11]: 2147483647 -dec[a,14,11]: 2469135780246913578024691357.82 -dec[s,14,11]: 0.00 -dec[m,14,11]: -dec[d,14,11]: 1.00000000000000000 +dec[a,14,11]: 7654321.0 +dec[s,14,11]: 7654321.0 +dec[m,14,11]: 7654321.0 +dec[d,14,11]: 7654321.0 dec[c,14,12]: 2147483647 -dec[a,14,12]: 2469135780246913578024691357.82 -dec[s,14,12]: 0.00 -dec[m,14,12]: -dec[d,14,12]: 1.00000000000000000 +dec[a,14,12]: 7654321.0 +dec[s,14,12]: 7654321.0 +dec[m,14,12]: 7654321.0 +dec[d,14,12]: 7654321.0 dec[c,14,13]: 2147483647 -dec[a,14,13]: 2469135780246913578024691357.82 -dec[s,14,13]: 0.00 -dec[m,14,13]: -dec[d,14,13]: 1.00000000000000000 +dec[a,14,13]: 7654321.0 +dec[s,14,13]: 7654321.0 +dec[m,14,13]: 7654321.0 +dec[d,14,13]: 7654321.0 dec[c,14,14]: 2147483647 -dec[a,14,14]: 2469135780246913578024691357.82 -dec[s,14,14]: 0.00 -dec[m,14,14]: -dec[d,14,14]: 1.00000000000000000 +dec[a,14,14]: 7654321.0 +dec[s,14,14]: 7654321.0 +dec[m,14,14]: 7654321.0 +dec[d,14,14]: 7654321.0 0: * 1: -2 2: 0.794 --JvxchO/wJ+olBE97 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="deccall3-null-v1.patch" Author: Noah Misch Commit: Noah Misch Fix ECPG decadd(), decdiv(), decmul(), and decsub() for risnull() input. FIXME not for commit unless Informix testing confirms it Since commit 757fb0e5a9a61ac8d3a67e334faeea6dc0084b3f, these Informix-compat functions return 0 without changing the output parameter. Before that commit, they would rsetnull() the output parameter. Restore the rsetnull() behavior, which is also consistent with the SQL arithmetic operators. Today's behavior might be accidentally working for applications that use these functions to calculate x=x+null or x=x*null. In those calculations, the null coincidentally behaves like a 0 for addition and like a 1 for multiplication. Given that possibility and today's behavior having stood for 20 years, no back-patch. Reviewed by FIXME. Discussion: https://postgr.es/m/FIXME diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index 65a0b2e..32f8733 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -51,6 +51,11 @@ deccall2(decimal *arg1, decimal *arg2, int (*ptr) (numeric *, numeric *)) *a2; int i; + /* + * risnull() inputs: our only caller is deccmp(), and Informix documents + * deccmp() as returning DECUNKNOWN on null input. + */ + if ((a1 = PGTYPESnumeric_new()) == NULL) return ECPG_INFORMIX_OUT_OF_MEMORY; @@ -90,12 +95,12 @@ deccall3(decimal *arg1, decimal *arg2, decimal *result, int (*ptr) (numeric *, n *nres; int i; - /* - * we must NOT set the result to NULL here because it may be the same - * variable as one of the arguments - */ + /* like a STRICT function in SQL, null arg gives null result */ if (risnull(CDECIMALTYPE, (char *) arg1) || risnull(CDECIMALTYPE, (char *) arg2)) + { + rsetnull(CDECIMALTYPE, (char *) result); return 0; + } if ((a1 = PGTYPESnumeric_new()) == NULL) return ECPG_INFORMIX_OUT_OF_MEMORY; diff --git a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc index 830ab58..20538df 100644 --- a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc +++ b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc @@ -143,9 +143,8 @@ main(void) printf("dec[c,%d,%d]: %d\n", i, j, c); /* - * decarr[count-1] is risnull(), which makes these functions - * return 0 without changing the output parameter. Make that - * clear by initializing each output parameter. + * Initialize output parameters, so we get an unambiguous signal + * if any call doesn't change its output parameter. */ deccvint(7654321, &a); deccvint(7654321, &s); diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c index 3e68b2e..a9d9d21 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c +++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c @@ -196,9 +196,8 @@ main(void) printf("dec[c,%d,%d]: %d\n", i, j, c); /* - * decarr[count-1] is risnull(), which makes these functions - * return 0 without changing the output parameter. Make that - * clear by initializing each output parameter. + * Initialize output parameters, so we get an unambiguous signal + * if any call doesn't change its output parameter. */ deccvint(7654321, &a); deccvint(7654321, &s); diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout index 7e50493..9d38629 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout +++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout @@ -222,10 +222,10 @@ dec[s,0,13]: dec[m,0,13]: * dec[d,0,13]: dec[c,0,14]: 2147483647 -dec[a,0,14]: 7654321.0 -dec[s,0,14]: 7654321.0 -dec[m,0,14]: 7654321.0 -dec[d,0,14]: 7654321.0 +dec[a,0,14]: +dec[s,0,14]: +dec[m,0,14]: +dec[d,0,14]: dec[c,1,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,1,0]: @@ -297,10 +297,10 @@ dec[s,1,13]: -1234567890123456789012345680.91 dec[m,1,13]: -2469135780246913578024691357.82 dec[d,1,13]: -0.0000000000000000000000000016200000145800001 dec[c,1,14]: 2147483647 -dec[a,1,14]: 7654321.0 -dec[s,1,14]: 7654321.0 -dec[m,1,14]: 7654321.0 -dec[d,1,14]: 7654321.0 +dec[a,1,14]: +dec[s,1,14]: +dec[m,1,14]: +dec[d,1,14]: dec[c,2,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,2,0]: @@ -372,10 +372,10 @@ dec[s,2,13]: dec[m,2,13]: dec[d,2,13]: 0.00000000000000000000000000064314000578826005 dec[c,2,14]: 2147483647 -dec[a,2,14]: 7654321.0 -dec[s,2,14]: 7654321.0 -dec[m,2,14]: 7654321.0 -dec[d,2,14]: 7654321.0 +dec[a,2,14]: +dec[s,2,14]: +dec[m,2,14]: +dec[d,2,14]: dec[c,3,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,3,0]: @@ -447,10 +447,10 @@ dec[s,3,13]: -1234567890123456789012345675.47 dec[m,3,13]: dec[d,3,13]: 0.0000000000000000000000000027864000250776002 dec[c,3,14]: 2147483647 -dec[a,3,14]: 7654321.0 -dec[s,3,14]: 7654321.0 -dec[m,3,14]: 7654321.0 -dec[d,3,14]: 7654321.0 +dec[a,3,14]: +dec[s,3,14]: +dec[m,3,14]: +dec[d,3,14]: dec[c,4,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,4,0]: @@ -522,10 +522,10 @@ dec[s,4,13]: -1233975400123456789012345678.91 dec[m,4,13]: dec[d,4,13]: 0.00047991690431925214 dec[c,4,14]: 2147483647 -dec[a,4,14]: 7654321.0 -dec[s,4,14]: 7654321.0 -dec[m,4,14]: 7654321.0 -dec[d,4,14]: 7654321.0 +dec[a,4,14]: +dec[s,4,14]: +dec[m,4,14]: +dec[d,4,14]: dec[c,5,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,5,0]: @@ -597,10 +597,10 @@ dec[s,5,13]: -1234567890123456789012674078.91 dec[m,5,13]: dec[d,5,13]: -0.00000000000000000000026600400239403602 dec[c,5,14]: 2147483647 -dec[a,5,14]: 7654321.0 -dec[s,5,14]: 7654321.0 -dec[m,5,14]: 7654321.0 -dec[d,5,14]: 7654321.0 +dec[a,5,14]: +dec[s,5,14]: +dec[m,5,14]: +dec[d,5,14]: dec[c,6,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,6,0]: @@ -672,10 +672,10 @@ dec[s,6,13]: dec[m,6,13]: * dec[d,6,13]: * dec[c,6,14]: 2147483647 -dec[a,6,14]: 7654321.0 -dec[s,6,14]: 7654321.0 -dec[m,6,14]: 7654321.0 -dec[d,6,14]: 7654321.0 +dec[a,6,14]: +dec[s,6,14]: +dec[m,6,14]: +dec[d,6,14]: dec[c,7,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,7,0]: @@ -747,10 +747,10 @@ dec[s,7,13]: dec[m,7,13]: 1234567890123456789012345.67891 dec[d,7,13]: 0.00000000000000000000000000000081000000729000007 dec[c,7,14]: 2147483647 -dec[a,7,14]: 7654321.0 -dec[s,7,14]: 7654321.0 -dec[m,7,14]: 7654321.0 -dec[d,7,14]: 7654321.0 +dec[a,7,14]: +dec[s,7,14]: +dec[m,7,14]: +dec[d,7,14]: dec[c,8,0]: -1 dec[a,8,0]: * dec[s,8,0]: * @@ -822,10 +822,10 @@ dec[s,8,13]: -1234567890123456789012345678.91 dec[m,8,13]: 0.000 dec[d,8,13]: 0 dec[c,8,14]: 2147483647 -dec[a,8,14]: 7654321.0 -dec[s,8,14]: 7654321.0 -dec[m,8,14]: 7654321.0 -dec[d,8,14]: 7654321.0 +dec[a,8,14]: +dec[s,8,14]: +dec[m,8,14]: +dec[d,8,14]: dec[c,9,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,9,0]: @@ -897,10 +897,10 @@ dec[s,9,13]: dec[m,9,13]: dec[d,9,13]: -0.000000000000000000000000000000047991690431925214 dec[c,9,14]: 2147483647 -dec[a,9,14]: 7654321.0 -dec[s,9,14]: 7654321.0 -dec[m,9,14]: 7654321.0 -dec[d,9,14]: 7654321.0 +dec[a,9,14]: +dec[s,9,14]: +dec[m,9,14]: +dec[d,9,14]: dec[c,10,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,10,0]: @@ -972,10 +972,10 @@ dec[s,10,13]: dec[m,10,13]: dec[d,10,13]: 0.0000000000000000000000000000026600400239403602 dec[c,10,14]: 2147483647 -dec[a,10,14]: 7654321.0 -dec[s,10,14]: 7654321.0 -dec[m,10,14]: 7654321.0 -dec[d,10,14]: 7654321.0 +dec[a,10,14]: +dec[s,10,14]: +dec[m,10,14]: +dec[d,10,14]: dec[c,11,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,11,0]: @@ -1047,10 +1047,10 @@ dec[s,11,13]: dec[m,11,13]: dec[d,11,13]: 0.00000000000000000000000000040500081364500732 dec[c,11,14]: 2147483647 -dec[a,11,14]: 7654321.0 -dec[s,11,14]: 7654321.0 -dec[m,11,14]: 7654321.0 -dec[d,11,14]: 7654321.0 +dec[a,11,14]: +dec[s,11,14]: +dec[m,11,14]: +dec[d,11,14]: dec[c,12,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,12,0]: @@ -1122,10 +1122,10 @@ dec[s,12,13]: dec[m,12,13]: dec[d,12,13]: -0.00000000000000000000000000040500008464500076 dec[c,12,14]: 2147483647 -dec[a,12,14]: 7654321.0 -dec[s,12,14]: 7654321.0 -dec[m,12,14]: 7654321.0 -dec[d,12,14]: 7654321.0 +dec[a,12,14]: +dec[s,12,14]: +dec[m,12,14]: +dec[d,12,14]: dec[c,13,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,13,0]: @@ -1197,85 +1197,85 @@ dec[s,13,13]: 0.00 dec[m,13,13]: dec[d,13,13]: 1.00000000000000000 dec[c,13,14]: 2147483647 -dec[a,13,14]: 7654321.0 -dec[s,13,14]: 7654321.0 -dec[m,13,14]: 7654321.0 -dec[d,13,14]: 7654321.0 +dec[a,13,14]: +dec[s,13,14]: +dec[m,13,14]: +dec[d,13,14]: dec[c,14,0]: 2147483647 -dec[a,14,0]: 7654321.0 -dec[s,14,0]: 7654321.0 -dec[m,14,0]: 7654321.0 -dec[d,14,0]: 7654321.0 +dec[a,14,0]: +dec[s,14,0]: +dec[m,14,0]: +dec[d,14,0]: dec[c,14,1]: 2147483647 -dec[a,14,1]: 7654321.0 -dec[s,14,1]: 7654321.0 -dec[m,14,1]: 7654321.0 -dec[d,14,1]: 7654321.0 +dec[a,14,1]: +dec[s,14,1]: +dec[m,14,1]: +dec[d,14,1]: dec[c,14,2]: 2147483647 -dec[a,14,2]: 7654321.0 -dec[s,14,2]: 7654321.0 -dec[m,14,2]: 7654321.0 -dec[d,14,2]: 7654321.0 +dec[a,14,2]: +dec[s,14,2]: +dec[m,14,2]: +dec[d,14,2]: dec[c,14,3]: 2147483647 -dec[a,14,3]: 7654321.0 -dec[s,14,3]: 7654321.0 -dec[m,14,3]: 7654321.0 -dec[d,14,3]: 7654321.0 +dec[a,14,3]: +dec[s,14,3]: +dec[m,14,3]: +dec[d,14,3]: dec[c,14,4]: 2147483647 -dec[a,14,4]: 7654321.0 -dec[s,14,4]: 7654321.0 -dec[m,14,4]: 7654321.0 -dec[d,14,4]: 7654321.0 +dec[a,14,4]: +dec[s,14,4]: +dec[m,14,4]: +dec[d,14,4]: dec[c,14,5]: 2147483647 -dec[a,14,5]: 7654321.0 -dec[s,14,5]: 7654321.0 -dec[m,14,5]: 7654321.0 -dec[d,14,5]: 7654321.0 +dec[a,14,5]: +dec[s,14,5]: +dec[m,14,5]: +dec[d,14,5]: dec[c,14,6]: 2147483647 -dec[a,14,6]: 7654321.0 -dec[s,14,6]: 7654321.0 -dec[m,14,6]: 7654321.0 -dec[d,14,6]: 7654321.0 +dec[a,14,6]: +dec[s,14,6]: +dec[m,14,6]: +dec[d,14,6]: dec[c,14,7]: 2147483647 -dec[a,14,7]: 7654321.0 -dec[s,14,7]: 7654321.0 -dec[m,14,7]: 7654321.0 -dec[d,14,7]: 7654321.0 +dec[a,14,7]: +dec[s,14,7]: +dec[m,14,7]: +dec[d,14,7]: dec[c,14,8]: 2147483647 -dec[a,14,8]: 7654321.0 -dec[s,14,8]: 7654321.0 -dec[m,14,8]: 7654321.0 -dec[d,14,8]: 7654321.0 +dec[a,14,8]: +dec[s,14,8]: +dec[m,14,8]: +dec[d,14,8]: dec[c,14,9]: 2147483647 -dec[a,14,9]: 7654321.0 -dec[s,14,9]: 7654321.0 -dec[m,14,9]: 7654321.0 -dec[d,14,9]: 7654321.0 +dec[a,14,9]: +dec[s,14,9]: +dec[m,14,9]: +dec[d,14,9]: dec[c,14,10]: 2147483647 -dec[a,14,10]: 7654321.0 -dec[s,14,10]: 7654321.0 -dec[m,14,10]: 7654321.0 -dec[d,14,10]: 7654321.0 +dec[a,14,10]: +dec[s,14,10]: +dec[m,14,10]: +dec[d,14,10]: dec[c,14,11]: 2147483647 -dec[a,14,11]: 7654321.0 -dec[s,14,11]: 7654321.0 -dec[m,14,11]: 7654321.0 -dec[d,14,11]: 7654321.0 +dec[a,14,11]: +dec[s,14,11]: +dec[m,14,11]: +dec[d,14,11]: dec[c,14,12]: 2147483647 -dec[a,14,12]: 7654321.0 -dec[s,14,12]: 7654321.0 -dec[m,14,12]: 7654321.0 -dec[d,14,12]: 7654321.0 +dec[a,14,12]: +dec[s,14,12]: +dec[m,14,12]: +dec[d,14,12]: dec[c,14,13]: 2147483647 -dec[a,14,13]: 7654321.0 -dec[s,14,13]: 7654321.0 -dec[m,14,13]: 7654321.0 -dec[d,14,13]: 7654321.0 +dec[a,14,13]: +dec[s,14,13]: +dec[m,14,13]: +dec[d,14,13]: dec[c,14,14]: 2147483647 -dec[a,14,14]: 7654321.0 -dec[s,14,14]: 7654321.0 -dec[m,14,14]: 7654321.0 -dec[d,14,14]: 7654321.0 +dec[a,14,14]: +dec[s,14,14]: +dec[m,14,14]: +dec[d,14,14]: 0: * 1: -2 2: 0.794 --JvxchO/wJ+olBE97--