View Javadoc
1   package org.dbunit.ext.postgresql;
2   
3   import org.dbunit.dataset.datatype.BytesDataType;
4   import org.dbunit.dataset.datatype.TypeCastException;
5   import org.postgresql.largeobject.LargeObject;
6   import org.postgresql.largeobject.LargeObjectManager;
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import java.io.ByteArrayInputStream;
11  import java.sql.*;
12  
13  public class PostgreSQLOidDataType
14          extends BytesDataType {
15  
16      /**
17       * Logger for this class
18       */
19      private static final Logger logger = LoggerFactory.getLogger(PostgreSQLOidDataType.class);
20  
21      public PostgreSQLOidDataType() {
22          super("OID", Types.BIGINT);
23      }
24  
25      @Override
26      public Object getSqlValue(final int column, final ResultSet resultSet)
27              throws SQLException,
28              TypeCastException
29      {
30          if (logger.isDebugEnabled()) {
31              logger.debug("getSqlValue(column={}, resultSet={}) - start", new Integer(column), resultSet);
32          }
33  
34          Statement statement = resultSet.getStatement();
35          Connection connection = statement.getConnection();
36          boolean autoCommit = connection.getAutoCommit();
37          // kinda ugly
38          connection.setAutoCommit(false);
39  
40          try {
41              LargeObjectManager lobj =
42                      ((org.postgresql.PGConnection) resultSet.getStatement().getConnection()).getLargeObjectAPI();
43  
44              long oid = resultSet.getLong(column);
45              if (oid == 0) {
46                  logger.debug("'oid' is zero, the data is NULL.");
47                  return null;
48              }
49              LargeObject obj = lobj.open(oid, LargeObjectManager.READ);
50              // If lobj.open() throws an exception, it means something wrong with the OID / table.
51              // So to be accurate, we don't catch this exception but let it propagate.
52              // Swallowing the exception silently indeed hides the problem, which is the wrong behavior
53  //            try {
54  //                obj = lobj.open(oid, LargeObjectManager.READ);
55  //            } catch (SQLException ex) {
56  //                logger.error("Failed to open oid {} for Large Object reading.", oid);
57  //                logger.error("Exception: {}", ex.getMessage());
58  //                logger.error("Returning null instead of bailing out");
59  //                return null;
60  //            }
61  
62              // Read the data
63              byte buf[] = new byte[obj.size()];
64              obj.read(buf, 0, obj.size());
65              // Close the object
66              obj.close();
67  
68              return buf;
69          } finally {
70              connection.setAutoCommit(autoCommit);
71          }
72      }
73  
74      @Override
75      public void setSqlValue(final Object value, final int column, final PreparedStatement statement)
76              throws SQLException,
77              TypeCastException
78      {
79          if (logger.isDebugEnabled())
80          {
81              logger.debug("setSqlValue(value={}, column={}, statement={}) - start",
82                      new Object[] { value, new Integer(column), statement });
83          }
84  
85          Connection connection = statement.getConnection();
86          boolean autoCommit = connection.getAutoCommit();
87          // kinda ugly
88          connection.setAutoCommit(false);
89  
90          try {
91              // Get the Large Object Manager to perform operations with
92              LargeObjectManager lobj = ((org.postgresql.PGConnection) statement.getConnection()).getLargeObjectAPI();
93  
94              // Create a new large object
95              long oid = lobj.createLO(LargeObjectManager.READ | LargeObjectManager.WRITE);
96  
97              // Open the large object for writing
98              LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);
99  
100             // Now open the file
101             ByteArrayInputStream bis = new ByteArrayInputStream((byte[]) super.typeCast(value));
102 
103             // Copy the data from the file to the large object
104             byte buf[] = new byte[2048];
105             int s = 0;
106             while ((s = bis.read(buf, 0, 2048)) > 0) {
107                 obj.write(buf, 0, s);
108             }
109 
110             // Close the large object
111             obj.close();
112 
113             statement.setLong(column, oid);
114         } finally {
115             connection.setAutoCommit(autoCommit);
116         }
117     }
118 }