/* * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden * Copyright (c) 2010, 2011 PostgreSQL Global Development Group * * Distributed under the terms shown in the file COPYRIGHT * found in the root folder of this project or at * http://wiki.tada.se/index.php?title=PLJava_License */ package org.postgresql.pljava.jdbc; import java.sql.SQLException; import java.util.ArrayList; import org.postgresql.pljava.internal.Tuple; import org.postgresql.pljava.internal.TupleDesc; /** * A single row, updateable ResultSet specially made for triggers. The * changes made to this ResultSet are remembered and converted to a * SPI_modify_tuple call prior to function return. * * @author Thomas Hallgren */ public class TriggerResultSet extends SingleRowResultSet { private ArrayList m_tupleChanges; private final TupleDesc m_tupleDesc; private final Tuple m_tuple; private final boolean m_readOnly; public TriggerResultSet(TupleDesc tupleDesc, Tuple tuple, boolean readOnly) throws SQLException { m_tupleDesc = tupleDesc; m_tuple = tuple; m_readOnly = readOnly; } /** * Cancel all changes made to the Tuple. */ public void cancelRowUpdates() throws SQLException { m_tupleChanges = null; } /** * Cancels all changes but doesn't really close the set. */ public void close() throws SQLException { m_tupleChanges = null; } /** * Returns the concurrency for this ResultSet. * @see java.sql.ResultSet#getConcurrency */ public int getConcurrency() throws SQLException { return m_readOnly ? CONCUR_READ_ONLY : CONCUR_UPDATABLE; } /** * Returns <code>true</code> if this row has been updated. */ public boolean rowUpdated() throws SQLException { return m_tupleChanges != null; } /** * Store this change for later use */ public void updateObject(int columnIndex, Object x) throws SQLException { if(m_readOnly) throw new UnsupportedFeatureException("ResultSet is read-only"); if(m_tupleChanges == null) m_tupleChanges = new ArrayList(); m_tupleChanges.add(new Integer(columnIndex)); m_tupleChanges.add(x); } /** * Return a 2 element array describing the changes that has been made to * the contained Tuple. The first element is an <code>int[]</code> containing * the index of each changed value. The second element is an <code>Object[] * </code> with containing the corresponding values. * * @return The 2 element array or <code>null</code> if no change has been made. */ public Object[] getChangeIndexesAndValues() { ArrayList changes = m_tupleChanges; if(changes == null) return null; int top = changes.size(); if(changes.size() == 0) return null; top /= 2; int[] indexes = new int[top]; Object[] values = new Object[top]; int vIdx = 0; for(int idx = 0; idx < top; ++idx) { indexes[idx] = ((Integer)changes.get(vIdx++)).intValue(); values[idx] = changes.get(vIdx++); } return new Object[] { m_tuple, indexes, values }; } protected Object getObjectValue(int columnIndex) throws SQLException { // Check if this value has been changed. // ArrayList changes = m_tupleChanges; if(changes != null) { int top = changes.size(); for(int idx = 0; idx < top; idx += 2) if(columnIndex == ((Integer)changes.get(idx)).intValue()) return changes.get(idx + 1); } return m_tuple.getObject(this.getTupleDesc(), columnIndex); } protected final TupleDesc getTupleDesc() { return m_tupleDesc; } // ************************************************************ // Implementation of JDBC 4 methods. // ************************************************************ public boolean isClosed() throws SQLException { return m_tupleChanges == null; } // ************************************************************ // End of implementation of JDBC 4 methods. // ************************************************************ }