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 1rmazN-008p7a-F8 for pgsql-jdbc@arkaria.postgresql.org; Tue, 19 Mar 2024 15:02:53 +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 1rmazL-00FeIL-Ea for pgsql-jdbc@arkaria.postgresql.org; Tue, 19 Mar 2024 15:02:51 +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 1rmazL-00FeID-0N for pgsql-jdbc@lists.postgresql.org; Tue, 19 Mar 2024 15:02:51 +0000 Received: from 008.lax.mailroute.net ([199.89.1.11]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rmazE-005Nwl-31 for pgsql-jdbc@lists.postgresql.org; Tue, 19 Mar 2024 15:02:50 +0000 Received: from localhost (localhost [127.0.0.1]) by 008.lax.mailroute.net (Postfix) with ESMTP id 4TzZhd2YPJz6Cnk8y; Tue, 19 Mar 2024 15:02:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=acm.org; h= content-transfer-encoding:content-type:content-type:in-reply-to :mime-version:user-agent:date:date:message-id:from:from :references:subject:subject:received:received; s=mr01; t= 1710860559; x=1713452560; bh=R2ddB1utp1jRm9fMLt0w90nL/3ZgF8HXTiL GGOV0sxI=; b=nurTlxs0LWOouOs1/OO0D3oAgeOAI/GIwO4FMoGa7JbhxWXLAMc UwANYHbMH7nvPeIOoDWcfUke8S+Trq0YtO7gz67thDxkTcBPVy1KkKtpZ+jpiOlW 2peDZ/pGLRQn4jD1rN7NfFRoXkbqTrXrzsK7dJjhhLRvb+I68zST/690AaPQsp/Z IAY59kePZeeXFC3ZfCJj0nvS+xHgr7McRk+NoPRyMzwcrcUbZCm5WG4Zm50a0/Ip fRKWiy+jt9APInEBHe+Ke3vRKW9q2NQASnYLtroVjts4nYZqY9GtKgjAR1fMs2/5 ALrdZL5OuPHOul7acKNmSt8PF9fEZXVN0aw== X-Virus-Scanned: by MailRoute Received: from 008.lax.mailroute.net ([127.0.0.1]) by localhost (008.lax [127.0.0.1]) (mroute_mailscanner, port 10029) with LMTP id 5HpC2zlmiElg; Tue, 19 Mar 2024 15:02:39 +0000 (UTC) Received: from [73.103.120.3] (c-73-103-120-3.hsd1.in.comcast.net [73.103.120.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: jcflack@acm.org) by 008.lax.mailroute.net (Postfix) with ESMTPSA id 4TzZhb3Gy8z6Cnk8t; Tue, 19 Mar 2024 15:02:39 +0000 (UTC) Subject: Re: Java : Postgres double precession issue with different data format text and binary To: Rahul Uniyal , pgsql-jdbc@lists.postgresql.org References: <7628237F-DEB2-414C-84D9-2E0C29FD9173@gmail.com> <510AA213-BEC4-458D-A3AB-38E43B67E482@gmail.com> From: Chapman Flack X-Enigmail-Draft-Status: N1110 Message-ID: <65F9A90E.5030508@acm.org> Date: Tue, 19 Mar 2024 11:02:38 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <510AA213-BEC4-458D-A3AB-38E43B67E482@gmail.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 03/18/24 23:05, Rahul Uniyal wrote: > This is the public method of PgResultSet class . > Apart from which format type it is , > getBigDecimal public method will get call That is interesting. That's why it's important to include the basics when making a report, including which public API method your code is calling. As you call getBigDecimal, you always will get a BigDecimal (or an exception). But, as you have shown, the implementation detail of the on-the-wire format influences how the BigDecimal is constructed. When the wire format is text, you get a BigDecimal constructed directly from the on-the-wire string value. When the wire format is binary (and the type is not NUMERIC or DECIMAL), there first is an object constructed by internalGetObject, and (if that is not an instance of Long, Integer, or Byte), it gets converted to a BigDecimal this way: return toBigDecimal(trimMoney(String.valueOf(obj)), scale); Assuming the object returned by internalGetObject is a Double, the reason for the divergent results is the String.valueOf in that conversion. BigDecimal and Double have different conventions for how they are rendered as a String; the representation of a Double will always have a decimal place: jshell> new BigDecimal("40") $1 ==> 40 jshell> Double.valueOf("40") $2 ==> 40.0 If you construct a BigDecimal directly from the Double, you get the one you expect: jshell> new BigDecimal($2) $3 ==> 40 But if you take the String value of the Double first, the extra decimal place shown in the Double's String value results in a BigDecimal with scale of 1 rather than 0: jshell> new BigDecimal(String.valueOf($2)) $4 ==> 40.0 jshell> $3.scale(); $4.scale() $5 ==> 0 $6 ==> 1 This is very probably worth reporting on pgsql-jdbc. I also wonder why the trimMoney() is there. The method seems to exist to deal with a string that could have $ in it, or parentheses instead of a negative sign, but I am unsure what kind of object could be obtained from internalGetObject that would require such treatment. Unrelated to your case, I wonder also about the handling of NUMERIC or DECIMAL when the value is NaN. The ByteConverter.numeric method is declared to return Number, and documented to return either a BigDecimal or Double.NaN. Likewise, PgResultSet.getNumeric can return Double.NaN in that case. But getBigDecimal contains an unconditional cast to BigDecimal, which seems like a ClassCastException waiting to happen for the NaN case. (getBigDecimal clearly can't return Double.NaN, but maybe a more-specific exception would be more helpful than "Double cannot be cast to BigInteger"?) I've added pgsql-jdbc to the To: for this message, but it will probably be delayed somewhat in moderation, as I am not subscribed to that list. Regards, -Chap