Thread: ResultSet.getClob() causing problems when used with JPA's @Lob

ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
Hi.

I have a varchar-column in a table which maps to a field (of type String) in a
JPA-entity. When marking that String-property with the JPA @Lob-annotation,
using Hibernate as my JPA-provider, it stops working as expected when using
PostgreSQL (works as expected on Oracle and SQL Server). The problem is that
Hibernate, correctly, calls ResultSet.getClob() but PG internally calls
getLong(), which obviously won't work with varchar-types, resulting in:

Caused by: org.postgresql.util.PSQLException: Bad value for type long : Hei
        at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2796)
        at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:2019)
        at org.postgresql.jdbc4.Jdbc4ResultSet.getClob(Jdbc4ResultSet.java:43)
        at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.java:384)
        at
org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4.doExtract(ClobTypeDescriptor.java:104)

After googling around I see this issue has come up before:
http://archives.postgresql.org/pgsql-jdbc/2010-02/msg00004.php

One is encurraged to use ResultSet.getString() instead. Hm, well - being at
Hibernate's mercy here, I don't really have that luxury. So, is PG's JDBC-
driver going to fix this flaw (IMNSHO it is a flaw) or is there consensus in the
PG-community that clobs are special and are not to be treated as
Strings/varchars?

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Radosław Smogura
Date:
Hi,
PGSQL doesn't have CLOB type, instead JDBC uses LOB, but PGSQL doesn't have
"clear" lob field type. It uses in table column with type OID, and supporting
table for storing large objects.

Look at bug submited by me
http://opensource.atlassian.com/projects/hibernate/browse/HHH-4617
Should be fixed in 3.6.1 release.

Kind regards,
Radosław Smogura
http://softperience.eu

Andreas Joseph Krogh <andreak@officenet.no> Monday 07 February 2011 00:01:21
> Hi.
>
> I have a varchar-column in a table which maps to a field (of type String)
> in a JPA-entity. When marking that String-property with the JPA
> @Lob-annotation, using Hibernate as my JPA-provider, it stops working as
> expected when using PostgreSQL (works as expected on Oracle and SQL
> Server). The problem is that Hibernate, correctly, calls
> ResultSet.getClob() but PG internally calls getLong(), which obviously
> won't work with varchar-types, resulting in:
>
> Caused by: org.postgresql.util.PSQLException: Bad value for type long : Hei
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.j
> ava:2796) at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.
> java:2019) at
> org.postgresql.jdbc4.Jdbc4ResultSet.getClob(Jdbc4ResultSet.java:43) at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.
> java:384) at
> org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4.doExtract(ClobTypeDe
> scriptor.java:104)
>
> After googling around I see this issue has come up before:
> http://archives.postgresql.org/pgsql-jdbc/2010-02/msg00004.php
>
> One is encurraged to use ResultSet.getString() instead. Hm, well - being at
> Hibernate's mercy here, I don't really have that luxury. So, is PG's JDBC-
> driver going to fix this flaw (IMNSHO it is a flaw) or is there consensus
> in the PG-community that clobs are special and are not to be treated as
> Strings/varchars?

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
On 02/07/2011 09:11 AM, Radosław Smogura wrote:
> Hi,
> PGSQL doesn't have CLOB type, instead JDBC uses LOB, but PGSQL doesn't
have
> "clear" lob field type. It uses in table column with type OID, and
supporting
> table for storing large objects.
>
> Look at bug submited by me
> http://opensource.atlassian.com/projects/hibernate/browse/HHH-4617
> Should be fixed in 3.6.1 release.

I'm experiencing this with 3.6.1 so whatever that issue fixes,
MaterializedClobType (which is the default type Hibernate uses when it
sees @Lob on String-types) still uses ClobTypeDescriptor, which again
has this code:

protected X doExtract(ResultSet rs, String name, WrapperOptions options)
throws SQLException {
    return javaTypeDescriptor.wrap( rs.getClob( name ), options );
}

And it should be able to call rs.getClob().

It's not clear to me why the JDBC-driver for PG shouldn't just use
rs.getString() internally for getClob() calls? Requiring
special-handling in Hibernate for dealing with Strings by setting an
obscure property just doesn't seem right. And I don't want to set a
property to handle CLOB which might affect how I use BLOBs.

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Radosław Smogura
Date:
PostgreSQL doesn't have field type CLOB, nor BLOB.

If eveny it would be possible for driver to read CLOB from varchar, driver
will be unable to set proper value when calling UPDATE or INSTERT. It is due
to internal way how PSQL deals with those values.

I know drivers supports custom casting, but casting from varchar to clob is
implicite prohibted in JDBC. If you look at B-6 table x indicates possible
casting. There is no x, nor X on varchar cross clob

Kind regards,
Radosław Smogura

Andreas Joseph Krogh <andreak@officenet.no> Monday 07 February 2011 21:50:10
> On 02/07/2011 09:11 AM, Radosław Smogura wrote:
> > Hi,
> > PGSQL doesn't have CLOB type, instead JDBC uses LOB, but PGSQL doesn't
>
> have
>
> > "clear" lob field type. It uses in table column with type OID, and
>
> supporting
>
> > table for storing large objects.
> >
> > Look at bug submited by me
> > http://opensource.atlassian.com/projects/hibernate/browse/HHH-4617
> > Should be fixed in 3.6.1 release.
>
> I'm experiencing this with 3.6.1 so whatever that issue fixes,
> MaterializedClobType (which is the default type Hibernate uses when it
> sees @Lob on String-types) still uses ClobTypeDescriptor, which again
> has this code:
>
> protected X doExtract(ResultSet rs, String name, WrapperOptions options)
> throws SQLException {
>     return javaTypeDescriptor.wrap( rs.getClob( name ), options );
> }
>
> And it should be able to call rs.getClob().
>
> It's not clear to me why the JDBC-driver for PG shouldn't just use
> rs.getString() internally for getClob() calls? Requiring
> special-handling in Hibernate for dealing with Strings by setting an
> obscure property just doesn't seem right. And I don't want to set a
> property to handle CLOB which might affect how I use BLOBs.

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
On 02/07/2011 10:38 PM, Radosław Smogura wrote:
> PostgreSQL doesn't have field type CLOB, nor BLOB.

I know that.

> If eveny it would be possible for driver to read CLOB from varchar, driver
> will be unable to set proper value when calling UPDATE or INSTERT. It is due
> to internal way how PSQL deals with those values.

Isn't the whole concept of CLOB just a bi-product of old proprietary
database-design where some RDBMS'es are unable to store arbitrary long
varchars? What properties do CLOBs have that varchars don't, except
being large? I don't understand why CLOBs can't be treated like text in
the PG-driver as PG handles large Strings just fine in
varchar/text-columns. If a DBA has for some reason defined a scale, say
VARCHAR(10), on a column and tries to store a CLOB in it, well - his
problem; He should get an Exception from PG.

> I know drivers supports custom casting, but casting from varchar to clob is
> implicite prohibted in JDBC. If you look at B-6 table x indicates possible
> casting. There is no x, nor X on varchar cross clob

Does it not make sense to you to be able to cast a *character large
object* to a *variable length character*-type and visa versa?

If the only argument is spec-complience I'm not getting it...

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Oliver Jowett
Date:
On 08/02/11 12:25, Andreas Joseph Krogh wrote:
> On 02/07/2011 10:38 PM, Radosław Smogura wrote:
>> PostgreSQL doesn't have field type CLOB, nor BLOB.
>
> I know that.
>
>> If eveny it would be possible for driver to read CLOB from varchar, driver
>> will be unable to set proper value when calling UPDATE or INSTERT. It is due
>> to internal way how PSQL deals with those values.
>
> Isn't the whole concept of CLOB just a bi-product of old proprietary
> database-design where some RDBMS'es are unable to store arbitrary long
> varchars? What properties do CLOBs have that varchars don't, except
> being large? I don't understand why CLOBs can't be treated like text in
> the PG-driver as PG handles large Strings just fine in
> varchar/text-columns. If a DBA has for some reason defined a scale, say
> VARCHAR(10), on a column and tries to store a CLOB in it, well - his
> problem; He should get an Exception from PG.

The different property is that clobs are mapped to OIDs that reference
an externally-stored LOB. So at the most basic "what do I get from the
server?" level they're different to varchar - the column type is an OID,
not varchar, so you have to send/receive OID values not strings and
perform a separate step to manage the data referenced by the OID.

They're mostly superceded by bytea/text, but they do still have some
properties that mean they do not behave identically (e.g. they are
essentially pass-by-reference, not pass-by-value; and you can modify
parts of them in-place without passing around the whole value).

>> I know drivers supports custom casting, but casting from varchar to clob is
>> implicite prohibted in JDBC. If you look at B-6 table x indicates possible
>> casting. There is no x, nor X on varchar cross clob
>
> Does it not make sense to you to be able to cast a *character large
> object* to a *variable length character*-type and visa versa?
>
> If the only argument is spec-complience I'm not getting it...

Conceivably, the driver could notice that a column is a varchar and
expose it via a different implementation of the clob interface that
doesn't try to interpret the value as an OID identifying an underlying
LOB. But that's not currently done because it's not one of the required
JDBC conversions (so if you expect that behavior from an arbitrary
driver you're already on shaky ground) and there's been no requests for
it before this that I can remember offhand. Also, the reverse conversion
isn't going to work, as mentioned above, so I don't know how useful it'd
be to you (the driver knows it got a varchar in a resultset, but in
general it won't know that when you said PreparedStatement.setClob() you
actually meant "please turn this into a varchar and insert that, instead
of creating a LOB and inserting the OID as you usually would"). You
could make it a big connection-wide toggle that said whether to
interpret clobs as LOBs or varchars, I suppose, but that's rather a big
hammer to fix what is arguably a problem in your persistence layer. (For
example, why can't you tell Hibernate exactly the same thing - "please
interpret my character LOBs as varchars" - which would be presumably be
useful to more than just the postgresql driver?)

The fundamental question here is "why are you trying to map a varchar to
a Clob?" .. As you say, clobs are mostly redundant anyway. Given that
your schema uses varchar, why don't you just use the varchar-style
accessors? It's not unreasonable to expect your access method to match
the underlying schema, surely.

Oliver

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
På tirsdag 08. februar 2011 kl 01:53:23 skrev "Oliver Jowett" <oliver@opencloud.com>:
> On 08/02/11 12:25, Andreas Joseph Krogh wrote:
> > On 02/07/2011 10:38 PM, Radosław Smogura wrote:
> >> PostgreSQL doesn't have field type CLOB, nor BLOB.
> >
> > I know that.
> >
> >> If eveny it would be possible for driver to read CLOB from varchar, driver
> >> will be unable to set proper value when calling UPDATE or INSTERT. It is due
> >> to internal way how PSQL deals with those values.
> >
> > Isn't the whole concept of CLOB just a bi-product of old proprietary
> > database-design where some RDBMS'es are unable to store arbitrary long
> > varchars? What properties do CLOBs have that varchars don't, except
> > being large? I don't understand why CLOBs can't be treated like text in
> > the PG-driver as PG handles large Strings just fine in
> > varchar/text-columns. If a DBA has for some reason defined a scale, say
> > VARCHAR(10), on a column and tries to store a CLOB in it, well - his
> > problem; He should get an Exception from PG.
>
> The different property is that clobs are mapped to OIDs that reference
> an externally-stored LOB. So at the most basic "what do I get from the
> server?" level they're different to varchar - the column type is an OID,
> not varchar, so you have to send/receive OID values not strings and
> perform a separate step to manage the data referenced by the OID.
>
> They're mostly superceded by bytea/text, but they do still have some
> properties that mean they do not behave identically (e.g. they are
> essentially pass-by-reference, not pass-by-value; and you can modify
> parts of them in-place without passing around the whole value).

Firstly; My issue here only affects CLOBs, not BLOBs.
Secondly; I'm not trying to be anal here, just trying to understand the arguments.
Thirdly; Didn't we just agree on that PG doesn't have CLOBs? If PG doesn't have CLOBs, how can it map CLOBs to OIDs?
Underwhat circumstances would PG need an OID to map a *C*LOB? Are you suggesting to store CLOBs as bytea? Is anyone
doingthis? 

> >> I know drivers supports custom casting, but casting from varchar to clob is
> >> implicite prohibted in JDBC. If you look at B-6 table x indicates possible
> >> casting. There is no x, nor X on varchar cross clob
> >
> > Does it not make sense to you to be able to cast a *character large
> > object* to a *variable length character*-type and visa versa?
> >
> > If the only argument is spec-complience I'm not getting it...
>
> Conceivably, the driver could notice that a column is a varchar and
> expose it via a different implementation of the clob interface that
> doesn't try to interpret the value as an OID identifying an underlying
> LOB. But that's not currently done because it's not one of the required
> JDBC conversions (so if you expect that behavior from an arbitrary
> driver you're already on shaky ground) and there's been no requests for
> it before this that I can remember offhand. Also, the reverse conversion
> isn't going to work, as mentioned above, so I don't know how useful it'd
> be to you (the driver knows it got a varchar in a resultset, but in
> general it won't know that when you said PreparedStatement.setClob() you
> actually meant "please turn this into a varchar and insert that, instead
> of creating a LOB and inserting the OID as you usually would"). You
> could make it a big connection-wide toggle that said whether to
> interpret clobs as LOBs or varchars, I suppose, but that's rather a big
> hammer to fix what is arguably a problem in your persistence layer. (For
> example, why can't you tell Hibernate exactly the same thing - "please
> interpret my character LOBs as varchars" - which would be presumably be
> useful to more than just the postgresql driver?)

All this stuff sounds like an implementation detail to me. The programmer using JDBC should, IMO, be able to use
rs.setClob()to varchar/text-columns transparently as there's no reason to treat it differently than setString(). 

> The fundamental question here is "why are you trying to map a varchar to
> a Clob?" .. As you say, clobs are mostly redundant anyway. Given that
> your schema uses varchar, why don't you just use the varchar-style
> accessors? It's not unreasonable to expect your access method to match
> the underlying schema, surely.

The reason I map the String-property as @Lob (which, by default, makes Hibernate use setClob()) is for interoperability
withother DBs, like Oracle, which require this annotation in order to be able to store Strings which are over 4000
charslong. These properties are stored in Oracle as CLOB and in PG as VARCHAR. 

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Oliver Jowett
Date:
Andreas Joseph Krogh wrote:

> Firstly; My issue here only affects CLOBs, not BLOBs.

BLOB-vs-bytea is essentially the same issue as CLOB-vs-varchar, FWIW. If
you tried to use the BLOB interface on a bytea column or vice versa,
you'd see similar problems, because bytea is not a BLOB, regardless of
the fact that they're both ways of storing large binary data.

> Thirdly; Didn't we just agree on that PG doesn't have CLOBs? If PG doesn't have CLOBs, how can it map CLOBs to OIDs?
Underwhat circumstances would PG need an OID to map a *C*LOB? Are you suggesting to store CLOBs as bytea? Is anyone
doingthis? 

No, I don't think we agreed on that. The PG driver certainly does have
something that is a CLOB - it is a column that contains an OID
referencing a separate LO that contains character data. The server
itself doesn't know about that mapping, but when you're working at the
JDBC level, you do need to be aware of the mapping.

(One way to look at it is to pretend that "clob" is spelled "oid" in
your schema)

> All this stuff sounds like an implementation detail to me. The programmer using JDBC should, IMO, be able to use
rs.setClob()to varchar/text-columns transparently as there's no reason to treat it differently than setString(). 

Why do you assume this? JDBC's CLOB is not the same type as VARCHAR, and
JDBC doesn't require that they're interchangeable.

And, in fact, the postgresql driver's mapping of CLOB is not
interchangeable with VARCHAR, which is the root of your problem..

>> The fundamental question here is "why are you trying to map a varchar to
>> a Clob?" .. As you say, clobs are mostly redundant anyway. Given that
>> your schema uses varchar, why don't you just use the varchar-style
>> accessors? It's not unreasonable to expect your access method to match
>> the underlying schema, surely.
>
> The reason I map the String-property as @Lob (which, by default, makes Hibernate use setClob()) is for
interoperabilitywith other DBs, like Oracle, which require this annotation in order to be able to store Strings which
areover 4000 chars long. These properties are stored in Oracle as CLOB and in PG as VARCHAR. 

Your problem here is that by using the JDBC driver's set/getClob()
methods (indirectly via Hibernate), you are saying "I want to treat this
type as a CLOB"; and a CLOB is mapped by the postgresql driver to the
*oid* type, *not* the varchar type you are using in your schema.

So you have a mismatch between your schema and how you are trying to
access it. Is there some reason your schema can't use oid here, as the
driver requires?

When you're using something like Hibernate you have three layers involved:

1) your application layer, which is dealing in terms of Java objects
2) your persistence layer, which handles the mapping of the Java objects
to a SQL schema, perhaps in a database-specific or schema-specific way
(as customized by annotations etc)
3) the JDBC layer, which handles the database-specific parts of taking a
SQL query expressed via the JDBC API and giving it to the database.

The JDBC layer (3) really is quite a simple mapping. It does not have
any knowledge of how you want to handle the data up at layer (1) - it
just does specifically what is asked of it. When Hibernate calls, e.g.,
setClob() or getClob() it is explicitly asking the driver to interpret
that parameter/column as a JDBC CLOB, which in the postgresql world
means "a LO containing character data referenced by OID". If that
interpretation doesn't match your schema, that's not a problem with the
driver - it means that layer (2) doesn't have the right mapping set up.
Putting knowledge in layer (3) about how to map your particular schema
to the particular datatypes you want is really the wrong place for it -
the JDBC API just doesn't provide a place to put that information.

(TBH, I'd think the simplest solution would be to just teach Hibernate's
postgresql dialect to map String-with-@Lob to the text type - the clob
support in the driver is limited at best)

Oliver

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
På tirsdag 08. februar 2011 kl 11:35:37 skrev du:
> Andreas Joseph Krogh wrote:
>
> > Firstly; My issue here only affects CLOBs, not BLOBs.
>
> BLOB-vs-bytea is essentially the same issue as CLOB-vs-varchar, FWIW. If
> you tried to use the BLOB interface on a bytea column or vice versa,
> you'd see similar problems, because bytea is not a BLOB, regardless of
> the fact that they're both ways of storing large binary data.
>
> > Thirdly; Didn't we just agree on that PG doesn't have CLOBs? If PG doesn't have CLOBs, how can it map CLOBs to
OIDs?Under what circumstances would PG need an OID to map a *C*LOB? Are you suggesting to store CLOBs as bytea? Is
anyonedoing this? 
>
> No, I don't think we agreed on that.

I meant on the server-side.

> The PG driver certainly does have
> something that is a CLOB - it is a column that contains an OID
> referencing a separate LO that contains character data. The server
> itself doesn't know about that mapping, but when you're working at the
> JDBC level, you do need to be aware of the mapping.
>
> (One way to look at it is to pretend that "clob" is spelled "oid" in
> your schema)

And what benefits does having a LO referencing character-data gives you instead of just using varchar/text? I don't see
anymotivation for using a LO? 

> > All this stuff sounds like an implementation detail to me. The programmer using JDBC should, IMO, be able to use
rs.setClob()to varchar/text-columns transparently as there's no reason to treat it differently than setString(). 
>
> Why do you assume this? JDBC's CLOB is not the same type as VARCHAR, and
> JDBC doesn't require that they're interchangeable.
>
> And, in fact, the postgresql driver's mapping of CLOB is not
> interchangeable with VARCHAR, which is the root of your problem..
>
> >> The fundamental question here is "why are you trying to map a varchar to
> >> a Clob?" .. As you say, clobs are mostly redundant anyway. Given that
> >> your schema uses varchar, why don't you just use the varchar-style
> >> accessors? It's not unreasonable to expect your access method to match
> >> the underlying schema, surely.
> >
> > The reason I map the String-property as @Lob (which, by default, makes Hibernate use setClob()) is for
interoperabilitywith other DBs, like Oracle, which require this annotation in order to be able to store Strings which
areover 4000 chars long. These properties are stored in Oracle as CLOB and in PG as VARCHAR. 
>
> Your problem here is that by using the JDBC driver's set/getClob()
> methods (indirectly via Hibernate), you are saying "I want to treat this
> type as a CLOB"; and a CLOB is mapped by the postgresql driver to the
> *oid* type, *not* the varchar type you are using in your schema.
>
> So you have a mismatch between your schema and how you are trying to
> access it. Is there some reason your schema can't use oid here, as the
> driver requires?
>
> When you're using something like Hibernate you have three layers involved:
>
> 1) your application layer, which is dealing in terms of Java objects
> 2) your persistence layer, which handles the mapping of the Java objects
> to a SQL schema, perhaps in a database-specific or schema-specific way
> (as customized by annotations etc)
> 3) the JDBC layer, which handles the database-specific parts of taking a
> SQL query expressed via the JDBC API and giving it to the database.
>
> The JDBC layer (3) really is quite a simple mapping. It does not have
> any knowledge of how you want to handle the data up at layer (1) - it
> just does specifically what is asked of it. When Hibernate calls, e.g.,
> setClob() or getClob() it is explicitly asking the driver to interpret
> that parameter/column as a JDBC CLOB, which in the postgresql world
> means "a LO containing character data referenced by OID". If that
> interpretation doesn't match your schema, that's not a problem with the
> driver - it means that layer (2) doesn't have the right mapping set up.
> Putting knowledge in layer (3) about how to map your particular schema
> to the particular datatypes you want is really the wrong place for it -
> the JDBC API just doesn't provide a place to put that information.
>
> (TBH, I'd think the simplest solution would be to just teach Hibernate's
> postgresql dialect to map String-with-@Lob to the text type - the clob
> support in the driver is limited at best)

I hear over and over that PGs JDBC-driver wants to map CLOBs to OIDs but there really doesn't seem to be any good
reasonsfor it (at least not that I can see). Why would I want to map my data as OID instead of varchar when the data is
aJAVA-String? Is anyone using LO and the LO-api for storing large character-data? I think not. The @Lob annotation
(whichstarted this thread) is just there to help other DBs map the String-property correctly, I would love to get rid
ofit but need it to have my app work with Oracle. I also want other properties of varchar to work (LIKE-operator f.ex.,
whichOracle also support on CLOBs), and I don't know what the PG-LO type supports. Honestly; I don't see any reason to
useLOs at all, neither for BLOB (where I use bytea) or CLOBs (where I use varchar). 

I get around this problem in Hibernate by using this combination:

    @Column(name="my_name")
    @Lob
    @Type(type="org.hibernate.type.StringClobType")

...but the StringClobType is deprecated.

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Oliver Jowett
Date:
Andreas Joseph Krogh wrote:

> I hear over and over that PGs JDBC-driver wants to map CLOBs to OIDs but there really doesn't seem to be any good
reasonsfor it 

It's mostly there for historical reasons - IIRC it dates back to the
early 7.x days when you *had* to use LOs to store large data, because
there was no such thing as the "text" or "bytea" type. There's really
not much reason to use it in new code these days, as I said. But there's
also not much reason to arbitrarily break compatibility with existing
code that assumes the current behavior, just for the sake of your
particular application.

I think that your efforts here might be more productively directed
towards improving the Hibernate postgresql implementation so that it
avoids using get/setClob() entirely.

Oliver

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Oliver Jowett
Date:
Andreas Joseph Krogh wrote:

> ...but the StringClobType is deprecated.

The obvious question here is "why?"

Oliver

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Radosław Smogura
Date:
Andreas Joseph Krogh <andreak@officenet.no> Tuesday 08 February 2011 12:34:19
> I hear over and over that PGs JDBC-driver wants to map CLOBs to OIDs but
> there really doesn't seem to be any good reasons for it (at least not that
> I can see). Why would I want to map my data as OID instead of varchar when
> the data is a JAVA-String? Is anyone using LO and the LO-api for storing
> large character-data? I think not. The @Lob annotation (which started this
> thread) is just there to help other DBs map the String-property correctly,
> I would love to get rid of it but need it to have my app work with Oracle.
> I also want other properties of varchar to work (LIKE-operator f.ex.,
> which Oracle also support on CLOBs), and I don't know what the PG-LO type
> supports. Honestly; I don't see any reason to use LOs at all, neither for
> BLOB (where I use bytea) or CLOBs (where I use varchar).

Actually there is good reason LOB are streamed. As it stands it's "large
object", and need special treatment. This LO can be 1,2 or 16GB. If you will
use bytea (it's impossible for such large objects) PGSQL sends all data in one
message so, select * my_table_with_los will end with OutOfMemory. 2nd reason
is that different communication is performed with LOBs, this is streaming
mode, which is faster so you will not OOM your JVM. You need to understand
that LO wasn't made to be something more then "fiele systems" in database for
realy big files.

CLOBS are more historical, in days of XMLs, but historical applications still
exists and sitll many systemes use plain flat files to exchange data.

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Kris Jurka
Date:

On Mon, 7 Feb 2011, Andreas Joseph Krogh wrote:

> It's not clear to me why the JDBC-driver for PG shouldn't just use
> rs.getString() internally for getClob() calls? Requiring
> special-handling in Hibernate for dealing with Strings by setting an
> obscure property just doesn't seem right. And I don't want to set a
> property to handle CLOB which might affect how I use BLOBs.
>

The problem is that we have no idea what someone might want to do with a
CLOB after they've fetched it.  You're coming from the idea that all they
want to do is read it and copy the data out to a String.  From that
perspective it's not hard to have a Clob wrapper around a String, but what
happens when they say clob.setString(13, "data")?  Are we going to try and
figure out what row of what table that varchar column is coming from and
do a partial update on it?

Kris Jurka

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Lew
Date:
Andreas Joseph Krogh wrote:
> I get around this problem in Hibernate by using this combination:
>
>      @Column(name="my_name")
>      @Lob
>      @Type(type="org.hibernate.type.StringClobType")
>
> ...but the StringClobType is deprecated.
>

It really makes it so much easier to have a TEXT column mapped to a 'String'.

  @Entity public class Foo
  {
    @Id
    private String ident;
    private String somethingBackedByTEXT;
   ...
  }

FWIW, in a database like Oracle that does have CLOBs it's still a lot easier
with Hibernate to map CLOBs to 'String' than to 'Clob', as I learned from
experience.  Even the Hibernate documentation recommends against mapping to
'Clob'.

--
Lew
Ceci n'est pas une fenêtre.
.___________.
|###] | [###|
|##/  | *\##|
|#/ * |   \#|
|#----|----#|
||    |  * ||
|o *  |    o|
|_____|_____|
|===========|

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
On 02/09/2011 01:20 AM, Kris Jurka wrote:
>
>
> On Mon, 7 Feb 2011, Andreas Joseph Krogh wrote:
>
>> It's not clear to me why the JDBC-driver for PG shouldn't just use
>> rs.getString() internally for getClob() calls? Requiring
>> special-handling in Hibernate for dealing with Strings by setting an
>> obscure property just doesn't seem right. And I don't want to set a
>> property to handle CLOB which might affect how I use BLOBs.
>>
>
> The problem is that we have no idea what someone might want to do with a
> CLOB after they've fetched it.  You're coming from the idea that all
> they want to do is read it and copy the data out to a String.  From that
> perspective it's not hard to have a Clob wrapper around a String, but
> what happens when they say clob.setString(13, "data")?  Are we going to
> try and figure out what row of what table that varchar column is coming
> from and do a partial update on it?

The javadoc for clob.setString(index, data) says:
----------------------------------------
Writes the given Java String to the CLOB value that this Clob object
designates at the position pos. The string will overwrite the existing
characters in the Clob object starting at the position pos. If the end
of the Clob value is reached while writing the given string, then the
length of the Clob value will be increased to accomodate the extra
characters.

Note: If the value specified for pos is greater then the length+1 of the
CLOB value then the behavior is undefined. Some JDBC drivers may throw a
SQLException while other drivers may support this operation.

Parameters:
pos - the position at which to start writing to the CLOB value that this
Clob object represents; The first position is 1
str - the string to be written to the CLOB value that this Clob designates
----------------------------------------

So, I think clob.setString(index, data) should behave just like
StringBuilder.insert(int offset, String str) except overwrite existing
data instead of moving the characters above the position.

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Oliver Jowett
Date:
Andreas Joseph Krogh wrote:
> On 02/09/2011 01:20 AM, Kris Jurka wrote:

>> The problem is that we have no idea what someone might want to do with a
>> CLOB after they've fetched it.  You're coming from the idea that all
>> they want to do is read it and copy the data out to a String.  From that
>> perspective it's not hard to have a Clob wrapper around a String, but
>> what happens when they say clob.setString(13, "data")?  Are we going to
>> try and figure out what row of what table that varchar column is coming
>> from and do a partial update on it?

> So, I think clob.setString(index, data) should behave just like
> StringBuilder.insert(int offset, String str) except overwrite existing
> data instead of moving the characters above the position.

You really missed Kris' point here - the question is not "how should we
modify the data?" but "how do we locate the data to modify in the first
place?". Consider:

  SELECT somedatacolumn FROM sometable WHERE complex condition

Now you have a resultset with one column. It's a varchar. The caller
calls ResultSet.getClob().setString(). What does the driver do?
Synthesize an UPDATE statement? How? With what parameters?

Oliver

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Andreas Joseph Krogh
Date:
On 02/09/2011 04:23 AM, Lew wrote:
> Andreas Joseph Krogh wrote:
>> I get around this problem in Hibernate by using this combination:
>>
>>      @Column(name="my_name")
>>      @Lob
>>      @Type(type="org.hibernate.type.StringClobType")
>>
>> ...but the StringClobType is deprecated.
>>
>
> It really makes it so much easier to have a TEXT column mapped to a
> 'String'.
>
>  @Entity public class Foo
>  {
>    @Id
>    private String ident;
>    private String somethingBackedByTEXT;
>   ...
>  }
>
> FWIW, in a database like Oracle that does have CLOBs it's still a lot
> easier with Hibernate to map CLOBs to 'String' than to 'Clob', as I
> learned from experience.  Even the Hibernate documentation recommends
> against mapping to 'Clob'.

Seems you missed the point

My mapping was like this, to a String-property

    @Column(name="my_name")
    @Lob
    @Type(type="org.hibernate.type.StringClobType")
    private String someLongDescription;

But I have to use @Lob in order to be able to persist this long String
in Oracle. With PG it works without the @Lob but then it's not portable.
The problem is that Hibernate uses ResultSet.setClob() regardless of the
DB-dialect when it sees @Lob on a String-type. This shouldn't be a
problem is the PG JDBC-driver implemented setClob as setString, but some
think that's not correct.

--
Andreas Joseph Krogh <andreak@officenet.no>
Senior Software Developer / CTO
Public key: http://home.officenet.no/~andreak/public_key.asc
------------------------+---------------------------------------------+
OfficeNet AS            | The most difficult thing in the world is to |
Rosenholmveien 25       | know how to do a thing and to watch         |
1414 Trollåsen          | somebody else doing it wrong, without       |
NORWAY                  | comment.                                    |
Org.nr: NO 981 479 076  |                                             |
                        |                                             |
Tlf:    +47 24 15 38 90 |                                             |
Fax:    +47 24 15 38 91 |                                             |
Mobile: +47 909  56 963 |                                             |
------------------------+---------------------------------------------+

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Radosław Smogura
Date:
After think, It is good idea to have CLOBS for VARCHARS, but to have any
chance:
How do You create this CLOB? If your column will be null you are in trouble,
as it will be impossible to call setClob(...) to set VARCHAR value. I mean
everyting will work until you will set/change values only by retrivied Clob
methods. You will be unable to set VARCHAR value with connection.createBlob,
too

You will need to ensure your VARCHAR will not be NULL, and your JPA will use
Clob.getter/Setter.

Andreas Joseph Krogh <andreak@officenet.no> Wednesday 09 February 2011
09:04:05
> On 02/09/2011 01:20 AM, Kris Jurka wrote:
> > On Mon, 7 Feb 2011, Andreas Joseph Krogh wrote:
> >> It's not clear to me why the JDBC-driver for PG shouldn't just use
> >> rs.getString() internally for getClob() calls? Requiring
> >> special-handling in Hibernate for dealing with Strings by setting an
> >> obscure property just doesn't seem right. And I don't want to set a
> >> property to handle CLOB which might affect how I use BLOBs.
> >
> > The problem is that we have no idea what someone might want to do with a
> > CLOB after they've fetched it.  You're coming from the idea that all
> > they want to do is read it and copy the data out to a String.  From that
> > perspective it's not hard to have a Clob wrapper around a String, but
> > what happens when they say clob.setString(13, "data")?  Are we going to
> > try and figure out what row of what table that varchar column is coming
> > from and do a partial update on it?
>
> The javadoc for clob.setString(index, data) says:
> ----------------------------------------
> Writes the given Java String to the CLOB value that this Clob object
> designates at the position pos. The string will overwrite the existing
> characters in the Clob object starting at the position pos. If the end
> of the Clob value is reached while writing the given string, then the
> length of the Clob value will be increased to accomodate the extra
> characters.
>
> Note: If the value specified for pos is greater then the length+1 of the
> CLOB value then the behavior is undefined. Some JDBC drivers may throw a
> SQLException while other drivers may support this operation.
>
> Parameters:
> pos - the position at which to start writing to the CLOB value that this
> Clob object represents; The first position is 1
> str - the string to be written to the CLOB value that this Clob designates
> ----------------------------------------
>
> So, I think clob.setString(index, data) should behave just like
> StringBuilder.insert(int offset, String str) except overwrite existing
> data instead of moving the characters above the position.

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Andreas Joseph Krogh schrieb am 07.02.2011 um 00:01:
> I have a varchar-column in a table which maps to a field (of type String) in a
> JPA-entity. When marking that String-property with the JPA @Lob-annotation,
> using Hibernate as my JPA-provider, it stops working as expected when using
> PostgreSQL (works as expected on Oracle and SQL Server). The problem is that
> Hibernate, correctly, calls ResultSet.getClob() but PG internally calls
> getLong(), which obviously won't work with varchar-types, resulting in:
>
> Caused by: org.postgresql.util.PSQLException: Bad value for type long : Hei
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2796)
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:2019)
>         at org.postgresql.jdbc4.Jdbc4ResultSet.getClob(Jdbc4ResultSet.java:43)
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.java:384)
>         at
> org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4.doExtract(ClobTypeDescriptor.java:104)
>
> After googling around I see this issue has come up before:
> http://archives.postgresql.org/pgsql-jdbc/2010-02/msg00004.php
>
> One is encurraged to use ResultSet.getString() instead. Hm, well - being at
> Hibernate's mercy here, I don't really have that luxury. So, is PG's JDBC-
> driver going to fix this flaw (IMNSHO it is a flaw) or is there consensus in the
> PG-community that clobs are special and are not to be treated as
> Strings/varchars?


Is there anything new here?
This still doesn't work with 9.4.1208

We are using Hibernate with an application that has to support Oracle and Postgres.

For Oracle we have to use CLOB to store Strings longer then 4000 characters - which means we *have* to use CLOB.
The Hibernate Entity is therefore annotated with @Lob and thus the whole thing fails with Postgres

So we are caught between a rock and a hard place: change to String and lose the ability to work with Oracle (which we
can't)or stick with @Lob and lose the possibility to also support Postgres. 

I think a connection parameter treatClobAsString=true would solve this problem - at least for us (and I think for most
othersthat have this problem as well).  

Are there any plans for this?

If not, is this something that would be accepted as a patch?


Thomas



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
>Is there anything new here?
>This still doesn't work with 9.4.1208

Nothing new here yet.

>So we are caught between a rock and a hard place

I feel your pain.

Technically the problem is pgjdbc does not have "String -> Clob" conversion yet.

>Are there any plans for this?

I've not heard of those.

>If not, is this something that would be accepted as a patch?

I think so.
It should be possible to check the result column type and create java.sql.Clob instance that would just work off the resulting string.

Special thank would go for a patch that would add JPA -> pgjdbc kind of integration test to the regression suite.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 20.07.2016 um 14:37:
>>Is there anything new here?
>>This still doesn't work with 9.4.1208
>
> Nothing new here yet.
>
>>So we are caught between a rock and a hard place
>
> I feel your pain.
>
> Technically the problem is pgjdbc does not have "String -> Clob" conversion yet.
>
>>Are there any plans for this?
>
> I've not heard of those.
>
>>If not, is this something that would be accepted as a patch?
>
> I think so.
> It should be possible to check the result column type and create java.sql.Clob instance that would just work off the
resultingstring. 

I don't think checking the column type is necessary (at least not for me).
If this option is enabled, then all calls to getClob() are simply "re-routed" to getString().



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
1) AFAIK, Oracle allows to use getString/setString for clob columns when using Oracle JDBC driver 10.2 or higher. Basically you set SetBigStringTryClob=true connection option and that is it.

2)
Thomas>I don't think checking the column type is necessary (at least not for me).
Thomas>If this option is enabled, then all calls to getClob() are simply "re-routed" to getString().

I'm afraid you miss the point.

In postgresql world, there's "large object API": https://www.postgresql.org/docs/current/static/lo-interfaces.html
pgjdbc wraps that, so if you have a column of "oid" type, then you can access the value via getClob and pgjdbc would reroute the calls to large object API.

So getLong is not a mistake in getClob. getLong is here to retrieve the value of "large object oid" (i.e. pointer). That is why column type is crucial to tell if getClob is dealing with "large object API" or "just a string".

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Andreas Joseph Krogh schrieb am 07.02.2011 um 00:01:
> I have a varchar-column in a table which maps to a field (of type String) in a
> JPA-entity. When marking that String-property with the JPA @Lob-annotation,
> using Hibernate as my JPA-provider, it stops working as expected when using
> PostgreSQL (works as expected on Oracle and SQL Server). The problem is that
> Hibernate, correctly, calls ResultSet.getClob() but PG internally calls
> getLong(), which obviously won't work with varchar-types, resulting in:
>
> Caused by: org.postgresql.util.PSQLException: Bad value for type long : Hei
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2796)
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:2019)
>         at org.postgresql.jdbc4.Jdbc4ResultSet.getClob(Jdbc4ResultSet.java:43)
>         at
> org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.java:384)
>         at
> org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4.doExtract(ClobTypeDescriptor.java:104)
>
> After googling around I see this issue has come up before:
> http://archives.postgresql.org/pgsql-jdbc/2010-02/msg00004.php
>
> One is encurraged to use ResultSet.getString() instead. Hm, well - being at
> Hibernate's mercy here, I don't really have that luxury. So, is PG's JDBC-
> driver going to fix this flaw (IMNSHO it is a flaw) or is there consensus in the
> PG-community that clobs are special and are not to be treated as
> Strings/varchars?


Is there anything new here?
This still doesn't work with 9.4.1208

We are using Hibernate with an application that has to support Oracle and Postgres.

For Oracle we have to use CLOB to store Strings longer then 4000 characters - which means we *have* to use CLOB.
The Hibernate Entity is therefore annotated with @Lob and thus the whole thing fails with Postgres

So we are caught between a rock and a hard place: change to String and lose the ability to work with Oracle (which we
can't)or stick with @Lob and lose the possibility to also support Postgres. 

I think a connection parameter treatClobAsString=true would solve this problem - at least for us (and I think for most
othersthat have this problem as well).  

Are there any plans for this?

If not, is this something that would be accepted as a patch?


Thomas



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 20.07.2016 um 15:52:
> 2)
> Thomas>I don't think checking the column type is necessary (at least not for me).
> Thomas>If this option is enabled, then all calls to getClob() are simply "re-routed" to getString().
>
> I'm afraid you miss the point.
>
> In postgresql world, there's "large object API": https://www.postgresql.org/docs/current/static/lo-interfaces.html
> pgjdbc wraps that, so if you have a column of "oid" type, then you can access the value via getClob and pgjdbc would
reroutethe calls to large object API. 

I am aware of the large object API but for the intended use case of "treatClobAsString=true" this would simply not
supportstoring string values through large objects - and I doubt that any project that would actually use
"treatClobAsString=true"would mix CLOBs as "large objects" and CLOBs as "text". 

> So getLong is not a mistake in getClob. getLong is here to retrieve the value of "large object oid" (i.e. pointer).
> That is why column type is crucial to tell if getClob is dealing with "large object API" or "just a string".

If we look at the use-case for this "override", I'm pretty sure there are (a lot) more people that could benefit from
anunconditional getClob() == getString() then people that actually need the distinction because they store large text
dataas "large objects" (oid columns): 

Thomas

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
>Is there anything new here?
>This still doesn't work with 9.4.1208

Nothing new here yet.

>So we are caught between a rock and a hard place

I feel your pain.

Technically the problem is pgjdbc does not have "String -> Clob" conversion yet.

>Are there any plans for this?

I've not heard of those.

>If not, is this something that would be accepted as a patch?

I think so.
It should be possible to check the result column type and create java.sql.Clob instance that would just work off the resulting string.

Special thank would go for a patch that would add JPA -> pgjdbc kind of integration test to the regression suite.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
Thomas> treatClobAsString

I do not find adding such a property is justified.
Adding random properties complicates behavior, it makes support harder and it makes bugs more obscure.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 20.07.2016 um 14:37:
>>Is there anything new here?
>>This still doesn't work with 9.4.1208
>
> Nothing new here yet.
>
>>So we are caught between a rock and a hard place
>
> I feel your pain.
>
> Technically the problem is pgjdbc does not have "String -> Clob" conversion yet.
>
>>Are there any plans for this?
>
> I've not heard of those.
>
>>If not, is this something that would be accepted as a patch?
>
> I think so.
> It should be possible to check the result column type and create java.sql.Clob instance that would just work off the
resultingstring. 

I don't think checking the column type is necessary (at least not for me).
If this option is enabled, then all calls to getClob() are simply "re-routed" to getString().



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
1) AFAIK, Oracle allows to use getString/setString for clob columns when using Oracle JDBC driver 10.2 or higher. Basically you set SetBigStringTryClob=true connection option and that is it.

2)
Thomas>I don't think checking the column type is necessary (at least not for me).
Thomas>If this option is enabled, then all calls to getClob() are simply "re-routed" to getString().

I'm afraid you miss the point.

In postgresql world, there's "large object API": https://www.postgresql.org/docs/current/static/lo-interfaces.html
pgjdbc wraps that, so if you have a column of "oid" type, then you can access the value via getClob and pgjdbc would reroute the calls to large object API.

So getLong is not a mistake in getClob. getLong is here to retrieve the value of "large object oid" (i.e. pointer). That is why column type is crucial to tell if getClob is dealing with "large object API" or "just a string".

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 20.07.2016 um 15:52:
> 2)
> Thomas>I don't think checking the column type is necessary (at least not for me).
> Thomas>If this option is enabled, then all calls to getClob() are simply "re-routed" to getString().
>
> I'm afraid you miss the point.
>
> In postgresql world, there's "large object API": https://www.postgresql.org/docs/current/static/lo-interfaces.html
> pgjdbc wraps that, so if you have a column of "oid" type, then you can access the value via getClob and pgjdbc would
reroutethe calls to large object API. 

I am aware of the large object API but for the intended use case of "treatClobAsString=true" this would simply not
supportstoring string values through large objects - and I doubt that any project that would actually use
"treatClobAsString=true"would mix CLOBs as "large objects" and CLOBs as "text". 

> So getLong is not a mistake in getClob. getLong is here to retrieve the value of "large object oid" (i.e. pointer).
> That is why column type is crucial to tell if getClob is dealing with "large object API" or "just a string".

If we look at the use-case for this "override", I'm pretty sure there are (a lot) more people that could benefit from
anunconditional getClob() == getString() then people that actually need the distinction because they store large text
dataas "large objects" (oid columns): 

Thomas

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
Thomas> treatClobAsString

I do not find adding such a property is justified.
Adding random properties complicates behavior, it makes support harder and it makes bugs more obscure.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Thomas Kellerer schrieb am 20.07.2016 um 13:51:
>> I have a varchar-column in a table which maps to a field (of type String) in a
>> JPA-entity. When marking that String-property with the JPA @Lob-annotation,
>> using Hibernate as my JPA-provider, it stops working as expected when using
>> PostgreSQL (works as expected on Oracle and SQL Server). The problem is that
>> Hibernate, correctly, calls ResultSet.getClob() but PG internally calls
>> getLong(), which obviously won't work with varchar-types, resulting in:
>>
>>
>> After googling around I see this issue has come up before:
>> http://archives.postgresql.org/pgsql-jdbc/2010-02/msg00004.php
>>
>> One is encurraged to use ResultSet.getString() instead. Hm, well - being at
>> Hibernate's mercy here, I don't really have that luxury. So, is PG's JDBC-
>> driver going to fix this flaw (IMNSHO it is a flaw) or is there consensus in the
>> PG-community that clobs are special and are not to be treated as
>> Strings/varchars?
>
>
> Is there anything new here?
> This still doesn't work with 9.4.1208
>
> We are using Hibernate with an application that has to support Oracle and Postgres.
>
> For Oracle we have to use CLOB to store Strings longer then 4000 characters - which means we *have* to use CLOB.
> The Hibernate Entity is therefore annotated with @Lob and thus the whole thing fails with Postgres
>
> So we are caught between a rock and a hard place: change to String and lose the ability to work with Oracle (which we
can't)
>or stick with @Lob and lose the possibility to also support Postgres.
>

Please find attached a patch that does the following:

* An implementation of the java.sql.Clob interface based on a String
* An implementation of the java.sql.Blob interface based on a byte[]
*A modified PgResultSet that checks the column type in getClob() and getBlob() and
returns the approriate Lob implementation if the column is a varchar/text or bytea
column.

The methods to set a stream are not implemented yet though.

I did not extend AbstractBlobClob as that makes too many assumption that the
underlying Lob is a "large object" in the database and I would wind up overwriting
nearly all methods in there.

I did however create an AbstractBasicLob to re-use the check for the correct position. The assertPosition()
methods in there are a copy from AbstractBlobClob. If this is something that gets accepted, it might
make sense to derive AbstractBlobClob from AbstractBasicLob and keep the assertions in a single place.

I don't know if we also need support for creating empty Clobs based on Strings that can be filled later

I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
would provide that information, but I don't know how to use that. If someone points me in the right
direction I can add that as well.


Regards
Thomas



Attachment

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
Thomas,

Thanks for looking into this, however could you please file a github PR so the system tests the change against different PostgreSQL / Java versions?

Could you add a test case that explores ResultSet.getClob as well?


I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
would provide that information, but I don't know how to use that. If someone points me in the right
direction I can add that as well.

I'm not yet ready to answer that.

Vladimir 

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Thomas Kellerer schrieb am 20.07.2016 um 13:51:
>> I have a varchar-column in a table which maps to a field (of type String) in a
>> JPA-entity. When marking that String-property with the JPA @Lob-annotation,
>> using Hibernate as my JPA-provider, it stops working as expected when using
>> PostgreSQL (works as expected on Oracle and SQL Server). The problem is that
>> Hibernate, correctly, calls ResultSet.getClob() but PG internally calls
>> getLong(), which obviously won't work with varchar-types, resulting in:
>>
>>
>> After googling around I see this issue has come up before:
>> http://archives.postgresql.org/pgsql-jdbc/2010-02/msg00004.php
>>
>> One is encurraged to use ResultSet.getString() instead. Hm, well - being at
>> Hibernate's mercy here, I don't really have that luxury. So, is PG's JDBC-
>> driver going to fix this flaw (IMNSHO it is a flaw) or is there consensus in the
>> PG-community that clobs are special and are not to be treated as
>> Strings/varchars?
>
>
> Is there anything new here?
> This still doesn't work with 9.4.1208
>
> We are using Hibernate with an application that has to support Oracle and Postgres.
>
> For Oracle we have to use CLOB to store Strings longer then 4000 characters - which means we *have* to use CLOB.
> The Hibernate Entity is therefore annotated with @Lob and thus the whole thing fails with Postgres
>
> So we are caught between a rock and a hard place: change to String and lose the ability to work with Oracle (which we
can't)
>or stick with @Lob and lose the possibility to also support Postgres.
>

Please find attached a patch that does the following:

* An implementation of the java.sql.Clob interface based on a String
* An implementation of the java.sql.Blob interface based on a byte[]
*A modified PgResultSet that checks the column type in getClob() and getBlob() and
returns the approriate Lob implementation if the column is a varchar/text or bytea
column.

The methods to set a stream are not implemented yet though.

I did not extend AbstractBlobClob as that makes too many assumption that the
underlying Lob is a "large object" in the database and I would wind up overwriting
nearly all methods in there.

I did however create an AbstractBasicLob to re-use the check for the correct position. The assertPosition()
methods in there are a copy from AbstractBlobClob. If this is something that gets accepted, it might
make sense to derive AbstractBlobClob from AbstractBasicLob and keep the assertions in a single place.

I don't know if we also need support for creating empty Clobs based on Strings that can be filled later

I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
would provide that information, but I don't know how to use that. If someone points me in the right
direction I can add that as well.


Regards
Thomas



Attachment

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
Thomas,

Thanks for looking into this, however could you please file a github PR so the system tests the change against different PostgreSQL / Java versions?

Could you add a test case that explores ResultSet.getClob as well?


I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
would provide that information, but I don't know how to use that. If someone points me in the right
direction I can add that as well.

I'm not yet ready to answer that.

Vladimir 

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 27.07.2016 um 21:58:
> Thomas,
>
> Thanks for looking into this, however could you please file a github PR so the system tests the change against
differentPostgreSQL / Java versions? 


Sorry, I don't have a github account, so I can't do that.


> Could you add a test case that explores ResultSet.getClob as well?

Yes, of course.

Thomas

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 27.07.2016 um 21:58:
> Thomas,
>
> Thanks for looking into this, however could you please file a github PR so the system tests the change against
differentPostgreSQL / Java versions? 


Sorry, I don't have a github account, so I can't do that.


> Could you add a test case that explores ResultSet.getClob as well?

Yes, of course.

Thomas

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
> Thanks for looking into this, however could you please file a github PR so the system tests the change against different PostgreSQL / Java versions?


Sorry, I don't have a github account, so I can't do that.

I've created a PR with your changes. Tests work ok, however code style is not in line with the project.

Can you fix checkstyle errors as well?
FYI: you can run `mvn checkstyle:check` to check the style locally.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
> Thanks for looking into this, however could you please file a github PR so the system tests the change against different PostgreSQL / Java versions?


Sorry, I don't have a github account, so I can't do that.

I've created a PR with your changes. Tests work ok, however code style is not in line with the project.

Can you fix checkstyle errors as well?
FYI: you can run `mvn checkstyle:check` to check the style locally.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 28.07.2016 um 15:57:
>      > Thanks for looking into this, however could you please file a github PR so the system tests the change against
differentPostgreSQL / Java versions? 
>
>
>     Sorry, I don't have a github account, so I can't do that.
>
> I've created a PR with your changes. Tests work ok, however code style is not in line with the project.
> Here's the test report: https://travis-ci.org/pgjdbc/pgjdbc/builds/147963868
>
> Can you fix checkstyle errors as well?
> FYI: you can run `mvn checkstyle:check` to check the style locally.
>
> Vladimir

Thanks.

Here is a new patch with formatting fixed and a test for PgResultSet

Thomas


Attachment

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 27.07.2016 um 21:58:
>
>     I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
>     the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
>     would provide that information, but I don't know how to use that. If someone points me in the right
>     direction I can add that as well.
>
>
> I'm not yet ready to answer that.
>

It would be nice if someone else could point me in the right direction, because I think
that only a change to PreparedStatement would make that complete.




Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Thomas Kellerer schrieb am 28.07.2016 um 22:24:
> Vladimir Sitnikov schrieb am 27.07.2016 um 21:58:
>>
>>     I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
>>     the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
>>     would provide that information, but I don't know how to use that. If someone points me in the right
>>     direction I can add that as well.
>>
>>
>> I'm not yet ready to answer that.
>>
>
> It would be nice if someone else could point me in the right direction, because I think
> that only a change to PreparedStatement would make that complete.
>

I wonder if something like this would be correct to detect the column type in PgPreparedStatement:

   private boolean isBytea(int i) throws SQLException {
     TypeInfo info = connection.getTypeInfo();
     int columnOID = preparedParameters.getTypeOIDs()[i];
     String pgType = info.getPGType(columnOID);
     return "bytea".equals(pgType);
   }

   private boolean isVarchar(int i) throws SQLException {
     TypeInfo info = connection.getTypeInfo();
     int columnOID = preparedParameters.getTypeOIDs()[i];
     String pgType = info.getPGType(columnOID);
     return "text".equals(pgType) ||
            "varchar".equals(pgType) ||
            "character varying".equals(pgType) ||
            "char".equals(pgType);
   }

I chose to compare the Postgres Names rather than the java.sql.Type constants because it seems
that TypeInfoCache will send a SQL query to the backend (at least once) to get that mapping.

I am not sure if "character varying" will ever be needed. TypeInfoCache does not have that in its internal array
where oids are mapped to type names.


and then in the setClob() method:

     if (isVarchar(i)) {
       setString(i, x.getSubString(1, (int)x.length()));
       return;
     }

and for setBlob() the similar thing:

     if (isBytea(i)) {
       setBytes(i, x.getBytes(1, (int)x.length()));
       return;
     }



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
>It would be nice if someone else could point me in the right direction, because I think
that only a change to PreparedStatement would make that complete.

Am I right your problem is "find a way to identify database type at PreparedStatement#setClob time"?

I'm afraid, there's no solution for that.

Technically speaking, java types are used to parse the SQL properly.
Suppose there's a function process(int4) and function process(text). When using prepareStatement("process(?)") at java side you can refer to both of those and the exact overload depends on the setXXX method.
For instance, if you call setString, then process(text) variation will be called.

Well, let's revert to our clob/text stuff.

I'm not quite sure we can easily figure out what is the proper data type for the bind.

I do not like the idea "having additional round trip to the database just to resolve desired bind types".
I do not like the idea of having a switch that binds setClob to text or lob database types either.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 28.07.2016 um 22:47:
>> It would be nice if someone else could point me in the right direction, because I think
>> that only a change to PreparedStatement would make that complete.
>
> Am I right your problem is "find a way to identify database type at PreparedStatement#setClob time"?
>
> I'm afraid, there's no solution for that.
>
> I'm not quite sure we can easily figure out what is the proper data type for the bind.

That's really a pity, because the (very unusual) handling of "large objects" makes the Clob/Blob handling quite
incompatiable with other JDBC implementations.


> I do not like the idea "having additional round trip to the database just to resolve desired bind types".

Me neither, that would be horrible.

> I do not like the idea of having a switch that binds setClob to text or lob database types either.

Well, in certain environments it would certainly make it easier to switch to Postgres.


Thomas



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
>other JDBC implementations.

I've just looked into PgConnection.createClob, and it turns out the method is not implemented.
This means no one ever used that to pass strings into large objects or whatever thing.

Large object API works with bytes, not characters, so I think we can safely assume that PgPreparedStatement.setClob results into string datatype (that is it should be just redirected to setString).

This (plus the patch that enables to getClob for textual results) should solve the problem for the majority of pgjdbc users. 

Thomas is that enough so you can give it a try?


That's really a pity, because the (very unusual) handling of "large objects" makes the Clob/Blob handling quite
incompatiable with other JDBC implementations.

The problem with Blob remains (I'm not sure if you have one): postgresql cannot automatically create a large object when it receives "bytea" bind.

For instance, we have pretty much similar problem with timestamp kind of types: setTimestamp() does not say much if "with time zone" or "without time zone" type should be used, so pgjdbc just sends a sting with "oid.UNKNOWN" in a hope that backend will figure out the proper timestamp type (luckily it can ignore time zone part when without time zone is required).

The same "unknown" approach does not work here since "large objects" are stored aside and a colum contains just a "oid" (64bit id).


Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 28.07.2016 um 15:57:
>      > Thanks for looking into this, however could you please file a github PR so the system tests the change against
differentPostgreSQL / Java versions? 
>
>
>     Sorry, I don't have a github account, so I can't do that.
>
> I've created a PR with your changes. Tests work ok, however code style is not in line with the project.
> Here's the test report: https://travis-ci.org/pgjdbc/pgjdbc/builds/147963868
>
> Can you fix checkstyle errors as well?
> FYI: you can run `mvn checkstyle:check` to check the style locally.
>
> Vladimir

Thanks.

Here is a new patch with formatting fixed and a test for PgResultSet

Thomas


Attachment

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 27.07.2016 um 21:58:
>
>     I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
>     the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
>     would provide that information, but I don't know how to use that. If someone points me in the right
>     direction I can add that as well.
>
>
> I'm not yet ready to answer that.
>

It would be nice if someone else could point me in the right direction, because I think
that only a change to PreparedStatement would make that complete.




Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Thomas Kellerer schrieb am 28.07.2016 um 22:24:
> Vladimir Sitnikov schrieb am 27.07.2016 um 21:58:
>>
>>     I think something similar is needed for PgPreparedStatement as well, but I did not find a way to check
>>     the type of a column the way it's done in PgResultSet. It seems that ParameterList.getTypeOIDs()
>>     would provide that information, but I don't know how to use that. If someone points me in the right
>>     direction I can add that as well.
>>
>>
>> I'm not yet ready to answer that.
>>
>
> It would be nice if someone else could point me in the right direction, because I think
> that only a change to PreparedStatement would make that complete.
>

I wonder if something like this would be correct to detect the column type in PgPreparedStatement:

   private boolean isBytea(int i) throws SQLException {
     TypeInfo info = connection.getTypeInfo();
     int columnOID = preparedParameters.getTypeOIDs()[i];
     String pgType = info.getPGType(columnOID);
     return "bytea".equals(pgType);
   }

   private boolean isVarchar(int i) throws SQLException {
     TypeInfo info = connection.getTypeInfo();
     int columnOID = preparedParameters.getTypeOIDs()[i];
     String pgType = info.getPGType(columnOID);
     return "text".equals(pgType) ||
            "varchar".equals(pgType) ||
            "character varying".equals(pgType) ||
            "char".equals(pgType);
   }

I chose to compare the Postgres Names rather than the java.sql.Type constants because it seems
that TypeInfoCache will send a SQL query to the backend (at least once) to get that mapping.

I am not sure if "character varying" will ever be needed. TypeInfoCache does not have that in its internal array
where oids are mapped to type names.


and then in the setClob() method:

     if (isVarchar(i)) {
       setString(i, x.getSubString(1, (int)x.length()));
       return;
     }

and for setBlob() the similar thing:

     if (isBytea(i)) {
       setBytes(i, x.getBytes(1, (int)x.length()));
       return;
     }



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
>It would be nice if someone else could point me in the right direction, because I think
that only a change to PreparedStatement would make that complete.

Am I right your problem is "find a way to identify database type at PreparedStatement#setClob time"?

I'm afraid, there's no solution for that.

Technically speaking, java types are used to parse the SQL properly.
Suppose there's a function process(int4) and function process(text). When using prepareStatement("process(?)") at java side you can refer to both of those and the exact overload depends on the setXXX method.
For instance, if you call setString, then process(text) variation will be called.

Well, let's revert to our clob/text stuff.

I'm not quite sure we can easily figure out what is the proper data type for the bind.

I do not like the idea "having additional round trip to the database just to resolve desired bind types".
I do not like the idea of having a switch that binds setClob to text or lob database types either.

Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 28.07.2016 um 22:47:
>> It would be nice if someone else could point me in the right direction, because I think
>> that only a change to PreparedStatement would make that complete.
>
> Am I right your problem is "find a way to identify database type at PreparedStatement#setClob time"?
>
> I'm afraid, there's no solution for that.
>
> I'm not quite sure we can easily figure out what is the proper data type for the bind.

That's really a pity, because the (very unusual) handling of "large objects" makes the Clob/Blob handling quite
incompatiable with other JDBC implementations.


> I do not like the idea "having additional round trip to the database just to resolve desired bind types".

Me neither, that would be horrible.

> I do not like the idea of having a switch that binds setClob to text or lob database types either.

Well, in certain environments it would certainly make it easier to switch to Postgres.


Thomas



Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Vladimir Sitnikov
Date:
>other JDBC implementations.

I've just looked into PgConnection.createClob, and it turns out the method is not implemented.
This means no one ever used that to pass strings into large objects or whatever thing.

Large object API works with bytes, not characters, so I think we can safely assume that PgPreparedStatement.setClob results into string datatype (that is it should be just redirected to setString).

This (plus the patch that enables to getClob for textual results) should solve the problem for the majority of pgjdbc users. 

Thomas is that enough so you can give it a try?


That's really a pity, because the (very unusual) handling of "large objects" makes the Clob/Blob handling quite
incompatiable with other JDBC implementations.

The problem with Blob remains (I'm not sure if you have one): postgresql cannot automatically create a large object when it receives "bytea" bind.

For instance, we have pretty much similar problem with timestamp kind of types: setTimestamp() does not say much if "with time zone" or "without time zone" type should be used, so pgjdbc just sends a sting with "oid.UNKNOWN" in a hope that backend will figure out the proper timestamp type (luckily it can ignore time zone part when without time zone is required).

The same "unknown" approach does not work here since "large objects" are stored aside and a colum contains just a "oid" (64bit id).


Vladimir

Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 29.07.2016 um 00:20:
>>other JDBC implementations.
>
> I've just looked into PgConnection.createClob, and it turns out the method is not implemented.
> This means no one ever used that to pass strings into large objects or whatever thing.

I noticed that as well. I wonder if we could use the PgStringClob and PgStringBlob I included with my patch for that
purpose? 

I think the missing methods in those two classes shouldn't be that hard to implement.


> Large object API works with bytes, not characters, so I think we can
> safely assume that PgPreparedStatement.setClob results into string
> datatype (that is it should be just redirected to setString).
>
> This (plus the patch that enables to getClob for textual results) should solve the problem for the majority of pgjdbc
users. 
>
> Thomas is that enough so you can give it a try?

Redirecting setClob() to setString() unconditionally would help us in the current migration, yes.

I can submit a patch for that, sounds easy enough.

>     That's really a pity, because the (very unusual) handling of "large objects" makes the Clob/Blob handling quite
>     incompatiable with other JDBC implementations.
>
> The problem with Blob remains (I'm not sure if you have one):
> postgresql cannot automatically create a large object when it receives "bytea" bind.
>
> The same "unknown" approach does not work here since "large objects" are stored aside and a colum contains just a
"oid"(64bit id). 
>
> That adds yet another case "bytea vs large object" to
>
https://github.com/pgjdbc/pgjdbc/blob/master/backend_protocol_v4_wanted_features.md#binary-transfer-vs-exact-data-type

I still think that having a connection property that switches between large objects and bytea for BLOBs makes sense.

Thomas





Re: ResultSet.getClob() causing problems when used with JPA's @Lob

From
Thomas Kellerer
Date:
Vladimir Sitnikov schrieb am 29.07.2016 um 00:20:
>>other JDBC implementations.
>
> I've just looked into PgConnection.createClob, and it turns out the method is not implemented.
> This means no one ever used that to pass strings into large objects or whatever thing.

I noticed that as well. I wonder if we could use the PgStringClob and PgStringBlob I included with my patch for that
purpose? 

I think the missing methods in those two classes shouldn't be that hard to implement.


> Large object API works with bytes, not characters, so I think we can
> safely assume that PgPreparedStatement.setClob results into string
> datatype (that is it should be just redirected to setString).
>
> This (plus the patch that enables to getClob for textual results) should solve the problem for the majority of pgjdbc
users. 
>
> Thomas is that enough so you can give it a try?

Redirecting setClob() to setString() unconditionally would help us in the current migration, yes.

I can submit a patch for that, sounds easy enough.

>     That's really a pity, because the (very unusual) handling of "large objects" makes the Clob/Blob handling quite
>     incompatiable with other JDBC implementations.
>
> The problem with Blob remains (I'm not sure if you have one):
> postgresql cannot automatically create a large object when it receives "bytea" bind.
>
> The same "unknown" approach does not work here since "large objects" are stored aside and a colum contains just a
"oid"(64bit id). 
>
> That adds yet another case "bytea vs large object" to
>
https://github.com/pgjdbc/pgjdbc/blob/master/backend_protocol_v4_wanted_features.md#binary-transfer-vs-exact-data-type

I still think that having a connection property that switches between large objects and bytea for BLOBs makes sense.

Thomas