Re: Change of format of returned flat value after prepareThreshold - Mailing list pgsql-jdbc

From Michał Niklas
Subject Re: Change of format of returned flat value after prepareThreshold
Date
Msg-id 56208B5C.9090803@heuthes.pl
Whole thread Raw
In response to Re: Change of format of returned flat value after prepareThreshold  (Vladimir Sitnikov <sitnikov.vladimir@gmail.com>)
Responses Re: Change of format of returned flat value after prepareThreshold
List pgsql-jdbc
W dniu 15.10.2015 o 17:34, Vladimir Sitnikov pisze:
>> but I think that those numbers can be returned as large integers
>> just like it was with 9.3 drivers or just like it is
>
> I'm afraid it is not possible at jdbc driver level. You need to
> change application code.

I have changed that query. One of programmer didn't know
Java well and used such query to get number of milliseconds
since epoch start (1970-01-01). I changed those codes
to use System.currentTimeMillis(). Problem disappeared.


> As far as I can see from your output, backend reports float8. That
> means, we have just a "double" at the client side, and we have no
> idea what string representation is "expected".

Of course I understand it.

The only thing I do not understand is:
why JDBC or database backend changes format of returned value
after my use count reaches prepareThreshold parameter.

If I set prepareThreshold=0 then I always get float in normal
notation.

If I set prepareThreshold=5 then I get float in normal
notation up to 5th try, and then from 6th try I get this
value in scientific notation.

If I set prepareThreshold=10 then I get float in normal
notation ut to 10th try, and then from 11th try I get this
value in scientific notation.

Why such change?

ResultSetMetaData do not changes and report that value
to be of float8 type (SQL_TYPE=8).

So what changed?

I do not observe this with JDBC drivers in version 9.3,
so I think something changed in driver code, but maybe
it is change in the database?

I use:
PostgreSQL 9.4.5 on x86_64-unknown-linux-gnu, compiled by gcc (GCC)
4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit



> If you want a "epoch time", I would recommend using
> resultSet.getLong(). Additionally, you might want to cast the
> selected expression to int8, so you do not mess with floating point
> numerics.

At first I casted it to bigint, then I simplified code that now
is even more portable (as we work with other databases)
and now I use System.currentTimeMillis() :-)


> Is there a specific reason why you expect non-scientific output of
> a _floating_ value out of .getString()?

This code is part of our reporting engine where all results are read
by rs.getString(). I know that I could use ResultSetMetaData,
but getString() simply works.

I was looking for similar queries that behaves the same way,
i.e. changes format of returned value after use count reaches
prepareThreshold, but I was not able to find such query.

In my previous mail there was attachment with Java code
that shows that behaviour and shell script that tests
it with various JDBC drivers.

There is Jython code that does the same thing:

<code>

#!/usr/bin/env jython
# -*- coding: utf8 -*-

__version__ = '$Id: jdbc_pg_float_time.py 2521 2015-10-16 05:24:43Z mn $'

import sys
import time
import traceback

from java.sql import DriverManager
from java.lang import Class

Class.forName("org.postgresql.Driver")


def test(db_url, user, passwd):
    try:
        print("\n\n%s\n--------------" % (db_url))
        db = DriverManager.getConnection(db_url, user, passwd)
        try:
            pstmt = db.prepareStatement("SELECT version()")
            rs = pstmt.executeQuery()
            while rs.next():
                s = rs.getString(1)
                print(s)
            rs.close()
            pstmt.close()

            dbmi = db.getMetaData()
            print("JDBC driver version is '%s'; major: %s; minor: %s" %
(dbmi.getDriverVersion(), dbmi.getDriverMajorVersion(),
dbmi.getDriverMinorVersion()))

            last_s = ''
            i = 0
            t0 = time.time()
            while 1:
                i += 1
                pstmt = db.prepareStatement("SELECT (EXTRACT(EPOCH FROM
timeofday()::timestamp(3))*1000) AS timestamp")
                rs = pstmt.executeQuery()
                try:
                    if i == 1:
                        rsmd = rs.getMetaData()
                        type_id = rsmd.getColumnType(1)
                        type_name = rsmd.getColumnTypeName(1)
                        print('column type: %s (%d)' % (type_name, type_id))
                    while rs.next():
                        s = rs.getString('timestamp')
                        if s != last_s:
                            t2 = time.time()
                            if t2 - t0 > 2:
                                print('epoch: %s; tries: %d' % (s, i))
                                t0 = t2
                            if '.' in s:
                                print('last value: %s; try: %d' % (last_s, i))
                                print('%s !!!' % (s))
                                return
                            last_s = s
                finally:
                    rs.close()
                    pstmt.close()
        finally:
            db.close()
    except:
        print("there were errors!")
        s = traceback.format_exc()
        sys.stderr.write("%s\n" % (s))


test('jdbc:postgresql://test-baza.heuthesd:5494/isof_test?stringtype=unspecified&prepareThreshold=10',
'postgres', 'postgres')


</code>

And results on my machine:

jdbc:postgresql://test-baza.heuthesd:5494/isof_test?stringtype=unspecified&prepareThreshold=10
--------------
PostgreSQL 9.4.5 on x86_64-unknown-linux-gnu, compiled by gcc (GCC)
4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit
JDBC driver version is 'PostgreSQL 9.4 JDBC4.2 (build 1204)'; major:
9; minor: 4
column type: float8 (8)
last value: 1444980175621; try: 11
1.444980175621E12 !!!


When you change prepareThreshold=10 to something else you will
get scientific format earlier or later.


--
Regards,
Michał Niklas


pgsql-jdbc by date:

Previous
From: Dave Cramer
Date:
Subject: Re: Release 1204 released
Next
From: Thomas Kellerer
Date:
Subject: Re: Release 1204 released