import mir.util.JDBCStringRoutines;
import mircoders.global.MirGlobal;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.*;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
+import org.apache.commons.dbcp.DelegatingConnection;
+import org.postgresql.PGConnection;
+import org.postgresql.largeobject.LargeObjectManager;
+import org.postgresql.largeobject.LargeObject;
+
/**
* Implements database access.
*
- * @version $Id: Database.java,v 1.44.2.25 2005/01/09 22:07:45 zapata Exp $
+ * @version $Id: Database.java,v 1.44.2.26 2005/01/23 15:36:03 zapata Exp $
* @author rk
*
*/
-public class Database implements StorageObject {
+public class Database {
private static Class GENERIC_ENTITY_CLASS = mir.entity.StorableObjectEntity.class;
protected static final ObjectStore o_store = ObjectStore.getInstance();
private static final int _millisPerHour = 60 * 60 * 1000;
protected List fieldNames;
protected int[] fieldTypes;
+ protected Map fieldNameToType;
protected Class entityClass;
private int defaultLimit;
}
}
- /**
- * Liefert die Entity-Klasse zur?ck, in der eine Datenbankzeile gewrappt
- * wird. Wird die Entity-Klasse durch die erbende Klasse nicht ?berschrieben,
- * wird eine mir.entity.GenericEntity erzeugt.
- *
- * @return Class-Objekt der Entity
- */
public java.lang.Class getEntityClass() {
return entityClass;
}
return defaultLimit;
}
- /**
- * Liefert den Namen des Primary-Keys zur?ck. Wird die Variable nicht von
- * der erbenden Klasse ?berschrieben, so ist der Wert <code>PKEY</code>
- * @return Name des Primary-Keys
- */
- public String getIdName() {
+ public String getIdFieldName() {
return primaryKeyField;
}
}
/**
- * {@inheritDoc}
+ * Returns a list of field names for this <code>Database</code>
*/
public List getFieldNames() throws StorageObjectFailure {
if (fieldNames == null) {
- retrieveMetaData();
+ acquireMetaData();
}
return fieldNames;
theReturnList.setStorage(this);
theReturnList.setLimit(aLimit);
- if (anOffset >= aLimit) {
- theReturnList.setPrevBatch(anOffset - aLimit);
- }
-
if (hasMore) {
theReturnList.setNextBatch(anOffset + aLimit);
}
/**
* Deletes entities based on a where clause
- *
- * @param aWhereClause
- * @return
- * @throws StorageObjectFailure
*/
public int deleteByWhereClause(String aWhereClause) throws StorageObjectFailure {
invalidateStore();
}
}
+ /**
+ * Executes 1 sql statement and returns the results as a <code>List</code> of
+ * <code>Map</code>s
+ */
public List executeFreeSql(String sql, int aLimit) throws StorageObjectFailure, StorageObjectExc {
Connection connection = null;
Statement statement = null;
}
};
+ /**
+ * Executes 1 sql statement and returns the first result row as a <code>Map</code>s
+ * (<code>null</code> if there wasn't any row)
+ */
public Map executeFreeSingleRowSql(String anSqlStatement) throws StorageObjectFailure, StorageObjectExc {
try {
List resultList = executeFreeSql(anSqlStatement, 1);
}
};
+ /**
+ * Executes 1 sql statement and returns the first column of the first result row as a <code>String</code>s
+ * (<code>null</code> if there wasn't any row)
+ */
public String executeFreeSingleValueSql(String sql) throws StorageObjectFailure, StorageObjectExc {
Map row = executeFreeSingleRowSql(sql);
*/
private void processMetaData(ResultSetMetaData aMetaData) throws StorageObjectFailure {
fieldNames = new ArrayList();
+ fieldNameToType = new HashMap();
try {
int numFields = aMetaData.getColumnCount();
for (int i = 1; i <= numFields; i++) {
fieldNames.add(aMetaData.getColumnName(i));
fieldTypes[i - 1] = aMetaData.getColumnType(i);
+ fieldNameToType.put(aMetaData.getColumnName(i), new Integer(aMetaData.getColumnType(i)));
}
}
catch (SQLException e) {
/**
* Retrieves metadata from the table this Database object represents
*/
- private void retrieveMetaData() throws StorageObjectFailure {
+ private void acquireMetaData() throws StorageObjectFailure {
Connection connection = null;
PreparedStatement statement = null;
String sql = "select * from " + mainTable + " where 0=1";
}
}
catch (SQLException e) {
- throwSQLException(e, "retrieveMetaData");
+ throwSQLException(e, "acquireMetaData");
}
finally {
freeConnection(connection, statement);
if(resultSet!=null) {
if (resultSet.next()) {
- inputStream = resultSet.getBlob(1).getBinaryStream();
- imageInputStream = new BinaryFieldInputStream(inputStream, connection, statement);
+ if (resultSet.getMetaData().getColumnType(1) == java.sql.Types.BINARY) {
+ byte[] data = resultSet.getBytes(1);
+ imageInputStream = new ByteArrayInputStream(data);
+ }
+ else {
+ inputStream = resultSet.getBlob(1).getBinaryStream();
+ imageInputStream = new BinaryFieldInputStream(inputStream, connection, statement);
+ }
}
resultSet.close();
}
}
/**
- * Sets a binary value. The query is supposed to contain 1 ? denoting where the
- * binary value should be inserted.
- *
- * e.g. <code>update images set image_data = ? where id= 22</code>
+ * Sets a binary value for a particular field in a record specified by its identifier
*/
- public void setBinaryField(String aQuery, byte aData[]) throws StorageObjectFailure, SQLException {
+ public void setBinaryField(String aFieldName, String anObjectId, byte aData[]) throws StorageObjectFailure, SQLException {
PreparedStatement statement = null;
Connection connection = obtainConnection();
+
try {
connection.setAutoCommit(false);
try {
- statement = connection.prepareStatement(aQuery);
- statement.setBinaryStream(1, new ByteArrayInputStream(aData), aData.length);
- statement.execute();
- connection.commit();
+ // are we using bytea ?
+ if (getFieldType(aFieldName) == java.sql.Types.BINARY) {
+ statement = connection.prepareStatement(
+ "update " + mainTable + " set " + aFieldName + " = ? where " + getIdFieldName() + "=" + Integer.parseInt(anObjectId));
+ statement.setBytes(1, aData);
+ statement.execute();
+ connection.commit();
+ }
+ // or the old oid's
+ else {
+ PGConnection postgresqlConnection = (org.postgresql.PGConnection) ((DelegatingConnection) connection).getDelegate();
+ LargeObjectManager lobManager = postgresqlConnection.getLargeObjectAPI();
+ int oid = lobManager.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
+ LargeObject obj = lobManager.open(oid, LargeObjectManager.WRITE); // Now open the file File file =
+ obj.write(aData);
+ obj.close();
+ statement = connection.prepareStatement(
+ "update " + mainTable + " set " + aFieldName + " = ? where " + getIdFieldName() + "=" + Integer.parseInt(anObjectId));
+ statement.setInt(1, oid);
+ statement.execute();
+ connection.commit();
+ }
}
finally {
connection.setAutoCommit(true);
logger.error("QUERY " + aQuery + " took " + aTime + "ms, but threw exception " + anException.toString());
}
+ private int getFieldType(String aFieldName) {
+ if (fieldNameToType == null) {
+ acquireMetaData();
+ }
+
+ return ((Integer) fieldNameToType.get(aFieldName)).intValue();
+ }
+
+
/**
* a small wrapper class that allows us to store the DB connection resources
* that the BlobInputStream is using and free them upon closing of the stream