7

I cannot seem to set the proper type in a prepared statement. This code:

String sql = "delete from foo where ctid = ?";
PreparedStatement deleteStmt = conn.prepareStatement( sql );
deleteStmt.setString(1, "(0,43)");  // select ctid from foo shows (0,43) exists....
int a = deleteStmt.executeUpdate();

throws this exception:

org.postgresql.util.PSQLException: ERROR: operator does not exist: tid = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.   Position: 28

Note that from psql, the delete works using a string:

mydb=# DELETE FROM foo where ctid = '(0,43)';
DELETE 1

What is the proper type/encoding for a tid in a JDBC PreparedStatement? I have tried setRowId() (throws ava.sql.SQLFeatureNotSupportedException: Method org.postgresql.jdbc4.Jdbc4PreparedStatement.setRowId(int, RowId) is not yet implemented.) and setBytes() (throws ...operator does not exist: tid = byte)

6
  • 1
    What if you try with deleteStmt.setObject(1, "(0,43)");? What exception does it throw? Commented Sep 17, 2013 at 14:42
  • 1
    Another possible solution: setString(1, "(0,43)::ctid") or don't use a PreparedStatement and use a dynamic SQL. Commented Sep 17, 2013 at 14:46
  • Both setObject(1, "(0,43)") and setString(1, "(0,43)::ctid") throw org.postgresql.util.PSQLException: ERROR: operator does not exist: tid = character varying. Dynamic SQL with no substitutions on a PreparedStatement (e.g. sql = "delete from foo where ctid = '(0,50)'"; deleteStmt = conn.prepareStatement( sql ); ) DOES work. Commented Sep 17, 2013 at 15:01
  • else - if possible - change your datatype to varchar Commented Sep 18, 2013 at 5:19
  • ctid is an internal column of type tid and cannot be changed. Commented Sep 18, 2013 at 15:55

2 Answers 2

3

Solved! You have to manually create a PGO object and set the type and value and pass it to JDBC as a object. This now works:

sql = "delete from foo where ctid = ?";
deleteStmt = conn.prepareStatement( sql );
org.postgresql.util.PGobject pgo = new org.postgresql.util.PGobject();
pgo.setType("tid");
pgo.setValue("(0,54)");  // value is a string as might be returned in select ctid from foo and then resultSet.getString(1);
deleteStmt.setObject(1, pgo);

int a = deleteStmt.executeUpdate();
System.out.println("delete returns " + a);
Sign up to request clarification or add additional context in comments.

Comments

1

Old topic, but I would like to add that writing

where ctid = ?::tid";

instead of

where ctid = ?::ctid";

did the trick. It is then possible to use PreparedStatement.setString(x, "(10,3)")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.