/*
* 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.
// ************************************************************
}