You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by be...@apache.org on 2006/02/07 17:09:18 UTC
svn commit: r375635 [1/6] - in /db/derby/code/trunk/java:
client/org/apache/derby/client/am/ engine/org/apache/derby/impl/jdbc/
engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/
testing/org/apache/derbyTesting/functionTests/...
Author: bernt
Date: Tue Feb 7 08:09:10 2006
New Revision: 375635
URL: http://svn.apache.org/viewcvs?rev=375635&view=rev
Log:
DERBY-100 Add support for insert functionality using BC 2.0 updatable resultset apis. Submitted by Fernanda Pizzorno
Modified:
db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_pt_BR.properties
db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/jdk14/updatableResultSet.out
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/updatableResultSet.out
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/jdk14/updatableResultSet.out
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/updatableResultSet.out
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/updatableResultSet.java
Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java?rev=375635&r1=375634&r2=375635&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java Tue Feb 7 08:09:10 2006
@@ -178,6 +178,7 @@
public PreparedStatement preparedStatementForUpdate_;
public PreparedStatement preparedStatementForDelete_;
+ public PreparedStatement preparedStatementForInsert_;
// Nesting level of the result set in a stored procedure
public int nestingLevel_ = -1;
@@ -274,6 +275,11 @@
checkForClosedResultSet();
clearWarningsX();
+ if (isOnInsertRow_) {
+ isOnInsertRow_ = false;
+ isOnCurrentRow_ = true;
+ }
+
wasNull_ = ResultSet.WAS_NULL_UNSET;
// discard all previous updates when moving the cursor
@@ -541,15 +547,17 @@
}
checkGetterPreconditions(column);
boolean result = false;
- if (wasNonNullSensitiveUpdate(column)) {
- result = agent_.crossConverters_.setBooleanFromObject(updatedColumns_[column - 1],
- resultSetMetaData_.types_[column - 1]);
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if (isOnInsertRow_ && updatedColumns_[column - 1] == null) {
+ result = false;
+ } else {
+ result = agent_.crossConverters_.setBooleanFromObject(
+ updatedColumns_[column - 1],
+ resultSetMetaData_.types_[column - 1]);
+ }
} else {
result = isNull(column) ? false : cursor_.getBoolean(column);
}
- if (agent_.loggingEnabled()) {
- agent_.logWriter_.traceExit(this, "getBoolean", result);
- }
setWasNull(column); // Placed close to the return to minimize risk of thread interference
return result;
}
@@ -570,9 +578,14 @@
}
checkGetterPreconditions(column);
byte result = 0;
- if (wasNonNullSensitiveUpdate(column)) {
- result = agent_.crossConverters_.setByteFromObject(updatedColumns_[column - 1],
- resultSetMetaData_.types_[column - 1]);
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if ((isOnInsertRow_) && (updatedColumns_[column - 1] == null)) {
+ result = 0;
+ } else {
+ result = agent_.crossConverters_.setByteFromObject(
+ updatedColumns_[column - 1],
+ resultSetMetaData_.types_[column - 1]);
+ }
} else {
result = isNull(column) ? 0 : cursor_.getByte(column);
}
@@ -599,9 +612,14 @@
}
checkGetterPreconditions(column);
short result = 0;
- if (wasNonNullSensitiveUpdate(column)) {
- result = ((Short) agent_.crossConverters_.setObject(java.sql.Types.SMALLINT,
- updatedColumns_[column - 1])).shortValue();
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if (isOnInsertRow_ && updatedColumns_[column - 1] == null) {
+ result = 0;
+ } else {
+ result = ((Short) agent_.crossConverters_.setObject(
+ java.sql.Types.SMALLINT,
+ updatedColumns_[column - 1])).shortValue();
+ }
} else {
result = isNull(column) ? 0 : cursor_.getShort(column);
}
@@ -628,9 +646,14 @@
}
checkGetterPreconditions(column);
int result = 0;
- if (wasNonNullSensitiveUpdate(column)) {
- result = ((Integer) agent_.crossConverters_.setObject(java.sql.Types.INTEGER,
- updatedColumns_[column - 1])).intValue();
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if (isOnInsertRow_ && updatedColumns_[column - 1] == null) {
+ result = 0;
+ } else {
+ result = ((Integer) agent_.crossConverters_.setObject(
+ java.sql.Types.INTEGER,
+ updatedColumns_[column - 1])).intValue();
+ }
} else {
result = isNull(column) ? 0 : cursor_.getInt(column);
}
@@ -657,9 +680,14 @@
}
checkGetterPreconditions(column);
long result = 0;
- if (wasNonNullSensitiveUpdate(column)) {
- result = ((Long) agent_.crossConverters_.setObject(java.sql.Types.BIGINT,
- updatedColumns_[column - 1])).longValue();
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if (isOnInsertRow_ && updatedColumns_[column - 1] == null) {
+ result = 0;
+ } else {
+ result = ((Long) agent_.crossConverters_.setObject(
+ java.sql.Types.BIGINT,
+ updatedColumns_[column - 1])).longValue();
+ }
} else {
result = isNull(column) ? 0 : cursor_.getLong(column);
}
@@ -686,9 +714,14 @@
}
checkGetterPreconditions(column);
float result = 0;
- if (wasNonNullSensitiveUpdate(column)) {
- result = ((Float) agent_.crossConverters_.setObject(java.sql.Types.REAL,
- updatedColumns_[column - 1])).floatValue();
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if ((isOnInsertRow_ && updatedColumns_[column - 1] == null)) {
+ result = 0;
+ } else {
+ result = ((Float) agent_.crossConverters_.setObject(
+ java.sql.Types.REAL,
+ updatedColumns_[column - 1])).floatValue();
+ }
} else {
result = isNull(column) ? 0 : cursor_.getFloat(column);
}
@@ -715,9 +748,14 @@
}
checkGetterPreconditions(column);
double result = 0;
- if (wasNonNullSensitiveUpdate(column)) {
- result = ((Double) agent_.crossConverters_.setObject(java.sql.Types.DOUBLE,
- updatedColumns_[column - 1])).doubleValue();
+ if (wasNonNullSensitiveUpdate(column) || isOnInsertRow_) {
+ if (isOnInsertRow_ && updatedColumns_[column - 1] == null) {
+ result = 0;
+ } else {
+ result = ((Double) agent_.crossConverters_.setObject(
+ java.sql.Types.DOUBLE,
+ updatedColumns_[column - 1])).doubleValue();
+ }
} else {
result = isNull(column) ? 0 : cursor_.getDouble(column);
}
@@ -1378,7 +1416,7 @@
}
private void setWasNull(int column) {
- if (wasNullSensitiveUpdate(column)) {
+ if (wasNullSensitiveUpdate(column) || (isOnInsertRow_ && updatedColumns_[column - 1] == null)) {
wasNull_ = WAS_NULL;
} else {
wasNull_ = (cursor_.isNull_ == null || cursor_.isNull_[column - 1]) ? WAS_NULL : WAS_NOT_NULL;
@@ -2643,14 +2681,8 @@
public boolean rowInserted() throws SQLException {
try
{
- if (agent_.loggingEnabled()) {
- agent_.logWriter_.traceEntry(this, "rowInserted");
- }
- checkForClosedResultSet();
- if (true) {
- throw new SqlException(agent_.logWriter_, "under construction");
- }
boolean rowInserted = false;
+ checkForClosedResultSet();
if (agent_.loggingEnabled()) {
agent_.logWriter_.traceExit(this, "rowInserted", rowInserted);
}
@@ -3297,8 +3329,7 @@
if (agent_.loggingEnabled()) {
agent_.logWriter_.traceEntry(this, "insertRow");
}
- checkForClosedResultSet();
- throw new SqlException(agent_.logWriter_, "Driver not capable: insertRow");
+ insertRowX();
}
}
catch ( SqlException se )
@@ -3307,6 +3338,53 @@
}
}
+ private void insertRowX() throws SqlException {
+ checkForClosedResultSet();
+ if (isOnCurrentRow_ || resultSetConcurrency_ == java.sql.ResultSet.CONCUR_READ_ONLY) {
+ throw new SqlException(agent_.logWriter_, "This method cannot be invoked while the cursor is not on the insert " +
+ "row or if the concurrency of this ResultSet object is CONCUR_READ_ONLY.");
+ }
+
+ // if not on a valid row, then do not accept updateXXX calls
+ if (!isValidCursorPosition_) {
+ throw new SqlException(agent_.logWriter_, "Invalid operation to " +
+ "insert at current cursor position");
+ }
+
+ // User might not be updating all the updatable columns selected in the
+ // select sql and hence every insertRow on the same ResultSet can be
+ // potentially different than the previous one. Because of that, we
+ // should get a new prepared statement to do inserts every time
+ getPreparedStatementForInsert();
+
+ // build the inputs array for the prepared statement for insert
+ int paramNumber = 0;
+ for (int i = 0; i < updatedColumns_.length; i++) {
+ if (resultSetMetaData_.sqlxUpdatable_[i] == 1) {
+ // Since user may choose not to update all the columns in the
+ // select list, check first if the column has been updated
+ if (columnUpdated_[i] == true) {
+ paramNumber++;
+
+ // column is updated either if the updatedColumns_ entry is not null,
+ // or if the updatedColumns_ entry is null, but columnUpdated is
+ // set to true, which means columns is updated to a null.
+ if (updatedColumns_[i] != null ||
+ (updatedColumns_[i] == null && columnUpdated_[i])) {
+ preparedStatementForInsert_.setInput(
+ paramNumber,
+ updatedColumns_[i]);
+ }
+ }
+ }
+ }
+ try {
+ insert();
+ } catch (SqlException e) {
+ throw e;
+ }
+ }
+
public void updateRow() throws java.sql.SQLException {
try
{
@@ -3550,7 +3628,13 @@
agent_.logWriter_.traceEntry(this, "moveToInsertRow");
}
checkForClosedResultSet();
- throw new SqlException(agent_.logWriter_, "Driver not capable");
+ checkUpdatableCursor();
+
+ resetUpdatedColumnsForInsert();
+
+ isOnInsertRow_ = true;
+ isOnCurrentRow_ = false;
+ isValidCursorPosition_ = true;
}
}
catch ( SqlException se )
@@ -3567,15 +3651,18 @@
agent_.logWriter_.traceEntry(this, "moveToCurrentRow");
}
checkForClosedResultSet();
- if (resultSetConcurrency_ == java.sql.ResultSet.CONCUR_READ_ONLY) {
- throw new SqlException(agent_.logWriter_, "This method should only be called on ResultSet objects that are " +
- "updatable(concurrency type CONCUR_UPDATABLE).");
- }
+ checkUpdatableCursor();
if (!isOnInsertRow_) {
// no affect
} else {
- throw new SqlException(agent_.logWriter_, "Driver no capable");
+ resetUpdatedColumns();
+ isOnInsertRow_ = false;
+ isOnCurrentRow_ = true;
+ if (currentRowInRowset_ > 0) {
+ updateColumnInfoFromCache();
+ }
+ isValidCursorPosition_ = true;
}
}
}
@@ -3724,6 +3811,35 @@
agent_.endReadChain();
}
+ protected void insert() throws SqlException {
+ agent_.beginWriteChain(statement_);
+
+ // re-prepare the insert statement if repreparing is needed after a commit.
+ if (!preparedStatementForInsert_.openOnServer_) {
+ preparedStatementForInsert_.materialPreparedStatement_.writePrepare_(
+ preparedStatementForInsert_.sql_,
+ preparedStatementForInsert_.section_);
+ }
+
+ try {
+ writeInsertRow(false);
+ } catch (SQLException se ) {
+ throw new SqlException(se);
+ }
+
+ agent_.flow(statement_);
+
+ // read prepare replies if the update statement is re-prepared after a commit.
+ if (!preparedStatementForInsert_.openOnServer_) {
+ preparedStatementForInsert_.materialPreparedStatement_.readPrepare_();
+ }
+
+ readInsertRow();
+
+ agent_.endReadChain();
+ }
+
+
protected void update() throws SqlException {
agent_.beginWriteChain(statement_);
@@ -3915,6 +4031,24 @@
agent_.endReadChain();
}
+ public void writeInsertRow(boolean chainedWritesFollowingSetLob) throws SQLException {
+ try
+ {
+ preparedStatementForInsert_.materialPreparedStatement_.writeExecute_(
+ preparedStatementForInsert_.section_,
+ preparedStatementForInsert_.parameterMetaData_,
+ preparedStatementForInsert_.parameters_,
+ (preparedStatementForInsert_.parameterMetaData_ == null ? 0 :
+ preparedStatementForInsert_.parameterMetaData_.getColumnCount()),
+ false, // false means we're not expecting output
+ chainedWritesFollowingSetLob); // chaining after the execute
+ }
+ catch ( SqlException se )
+ {
+ throw se.getSQLException();
+ }
+ }
+
public void writeUpdateRow(boolean chainedWritesFollowingSetLob) throws SQLException {
try
{
@@ -3956,6 +4090,10 @@
}
}
+ public void readInsertRow() throws DisconnectException, SqlException {
+ preparedStatementForInsert_.materialPreparedStatement_.readExecute_();
+ }
+
public void readUpdateRow() throws DisconnectException, SqlException {
preparedStatementForUpdate_.materialPreparedStatement_.readExecute_();
}
@@ -4128,7 +4266,51 @@
updatedColumns_[column - 1] = value;
columnUpdated_[column - 1] = true;
}
+
+ /*
+ * Builds the insert statement that will be used well calling insertRow
+ *
+ * If no values have been supplied for a column, it will be set
+ * to the column's default value, if any.
+ * If no default value had been defined, the default value of a
+ * nullable column is set to NULL.
+ */
+ private String buildInsertString() throws SqlException {
+ int column;
+ boolean foundOneUpdatedColumnAlready = false;
+
+ StringBuffer insertSQL = new StringBuffer("INSERT INTO ");
+ StringBuffer valuesSQL = new StringBuffer("VALUES (");
+ insertSQL.append(getTableName());
+ insertSQL.append(" (");
+
+ for (column = 1; column <= resultSetMetaData_.columns_; column++) {
+ if (foundOneUpdatedColumnAlready) {
+ insertSQL.append(",");
+ valuesSQL.append(",");
+ }
+ //using quotes around the column name to preserve case sensitivity
+ try {
+ insertSQL.append("\"" + resultSetMetaData_.getColumnName(column) + "\"");
+ } catch ( SQLException sqle ) {
+ throw new SqlException(sqle);
+ }
+ if (columnUpdated_[column - 1]) {
+ valuesSQL.append("?");
+ } else {
+ valuesSQL.append("DEFAULT");
+ }
+ foundOneUpdatedColumnAlready = true;
+ }
+
+ insertSQL.append(") ");
+ valuesSQL.append(") ");
+ insertSQL.append(valuesSQL.toString());
+
+ return(insertSQL.toString());
+ }
+
private String buildUpdateString() throws SqlException {
int column;
int numColumns = 0;
@@ -4219,6 +4401,18 @@
return statement_.section_.getServerCursorName();
}
+ private void getPreparedStatementForInsert() throws SqlException {
+ // each column is associated with a tableName in the extended describe info.
+ String insertString = buildInsertString();
+
+ try {
+ preparedStatementForInsert_ = (PreparedStatement)statement_.connection_.
+ prepareStatement(insertString);
+ } catch ( SQLException sqle ) {
+ throw new SqlException(sqle);
+ }
+ }
+
private void getPreparedStatementForUpdate() throws SqlException {
// each column is associated with a tableName in the extended describe info.
String updateString = buildUpdateString();
@@ -4241,6 +4435,22 @@
statement_.section_.getPositionedUpdateSection()); // update section
}
+ private final void resetUpdatedColumnsForInsert() {
+ // initialize updateColumns with nulls for all columns
+ if (updatedColumns_ == null) {
+ updatedColumns_ = new Object[resultSetMetaData_.columns_];
+ }
+ if (columnUpdated_ != null) {
+ columnUpdated_ = new boolean[resultSetMetaData_.columns_];
+ }
+ for (int i = 0; i < updatedColumns_.length; i++) {
+ updateColumn(i+1, null);
+ }
+ for (int i = 0; i < columnUpdated_.length; i++) {
+ columnUpdated_[i] = false;
+ }
+ }
+
private final void resetUpdatedColumns() {
if (updatedColumns_ != null) {
for (int i = 0; i < updatedColumns_.length; i++) {
@@ -4290,6 +4500,14 @@
if (column < 1 || column > resultSetMetaData_.columns_) {
throw new SqlException(agent_.logWriter_, "Invalid argument: parameter index " +
column + " is out of range.");
+ }
+ }
+
+ private void checkUpdatableCursor() throws SqlException {
+ if (resultSetConcurrency_ == java.sql.ResultSet.CONCUR_READ_ONLY) {
+ throw new SqlException(agent_.logWriter_,
+ "This method should only be called on ResultSet objects " +
+ "that are updatable(concurrency type CONCUR_UPDATABLE).");
}
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?rev=375635&r1=375634&r2=375635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Tue Feb 7 08:09:10 2006
@@ -103,6 +103,9 @@
private DataValueDescriptor[] rowData;
protected boolean wasNull;
protected boolean isClosed;
+ private boolean isOnInsertRow;
+ private ExecRow currentRowBeforeInsert;
+ private ExecRow insertRow = null;
private Object currentStream;
// immutable state
@@ -249,6 +252,12 @@
}
}
+ private void checkNotOnInsertRow() throws SQLException {
+ if (isOnInsertRow) {
+ throw newSQLException(SQLState.NO_CURRENT_ROW);
+ }
+ }
+
// onRow protects us from making requests of
// resultSet that would fail with NullPointerExceptions
// or milder problems due to not having a row.
@@ -337,6 +346,10 @@
// on the underlying connection. Do this
// outside of the connection synchronization.
+ if (isOnInsertRow) {
+ moveToCurrentRow();
+ }
+
synchronized (getConnectionSynchronization()) {
@@ -2044,7 +2057,7 @@
* @see EmbedDatabaseMetaData#insertsAreDetected
*/
public boolean rowInserted() throws SQLException {
- throw Util.notImplemented();
+ return false;
}
/**
@@ -2087,7 +2100,7 @@
getCursorName());
}
- //do following few checks before accepting updatable resultset api
+ //do following few checks before accepting updateRow or deleteRow
//1)Make sure this is an updatable ResultSet
//2)Make sure JDBC ResultSet is not closed
//3)Make sure JDBC ResultSet is positioned on a row
@@ -2095,8 +2108,7 @@
protected void checksBeforeUpdateOrDelete(String methodName, int columnIndex) throws SQLException {
//1)Make sure this is an updatable ResultSet
- if (getConcurrency() != JDBC20Translation.CONCUR_UPDATABLE)//if not updatable resultset, then throw exception
- throw Util.generateCsSQLException(SQLState.UPDATABLE_RESULTSET_API_DISALLOWED, methodName);
+ checkUpdatableCursor(methodName);
//2)Make sure JDBC ResultSet is not closed
checkIfClosed(methodName);
@@ -2125,7 +2137,33 @@
return currentRow.getColumn(columnIndex);
}
- /**
+ /* do following few checks before accepting insertRow
+ * 1) Make sure this is an updatable ResultSet
+ * 2) Make sure JDBC ResultSet is not closed
+ * 3) Make sure JDBC ResultSet is positioned on insertRow
+ * 4) Make sure underneath language resultset is not closed
+ */
+ protected void checksBeforeInsert() throws SQLException {
+ // 1)Make sure this is an updatable ResultSet
+ // if not updatable resultset, then throw exception
+ checkUpdatableCursor("insertRow");
+
+ // 2)Make sure JDBC ResultSet is not closed
+ checkIfClosed("insertRow");
+
+ // 3)Make sure JDBC ResultSet is positioned on insertRow
+ if (!isOnInsertRow) {
+ throw newSQLException(SQLState.NOT_POSITIONED_ON_INSERT_ROW);
+ }
+
+ // 4)Make sure underneath language resultset is not closed
+ if (theResults.isClosed()) {
+ throw Util.generateCsSQLException(SQLState.LANG_RESULT_SET_NOT_OPEN, "insertRow");
+ }
+ }
+
+
+ /**
* JDBC 2.0
*
* Give a nullable column a null value.
@@ -3208,7 +3246,94 @@
* insert row have not been given a value
*/
public void insertRow() throws SQLException {
- throw Util.notImplemented();
+ synchronized (getConnectionSynchronization()) {
+ checksBeforeInsert();
+ setupContextStack();
+ LanguageConnectionContext lcc = null;
+ StatementContext statementContext = null;
+ try {
+ /*
+ * construct the insert statement
+ *
+ * If no values have been supplied for a column, it will be set
+ * to the column's default value, if any.
+ * If no default value had been defined, the default value of a
+ * nullable column is set to NULL.
+ */
+
+ boolean foundOneColumnAlready = false;
+ StringBuffer insertSQL = new StringBuffer("INSERT INTO ");
+ StringBuffer valuesSQL = new StringBuffer("VALUES (");
+ CursorActivation activation = getEmbedConnection().
+ getLanguageConnection().lookupCursorActivation(getCursorName());
+
+ ExecCursorTableReference targetTable =
+ activation.getPreparedStatement().getTargetTable();
+ // got the underlying (schema.)table name
+ insertSQL.append(getFullBaseTableName(targetTable));
+ ResultDescription rd = theResults.getResultDescription();
+
+ insertSQL.append(" (");
+ // in this for loop we are constructing list of column-names
+ // and values (?) ,... part of the insert sql
+ for (int i=1; i<=rd.getColumnCount(); i++) {
+ if (foundOneColumnAlready) {
+ insertSQL.append(",");
+ valuesSQL.append(",");
+ }
+ // using quotes around the column name
+ // to preserve case sensitivity
+ insertSQL.append("\"" +
+ rd.getColumnDescriptor(i).getName() + "\"");
+ if (columnGotUpdated[i-1]) {
+ valuesSQL.append("?");
+ } else {
+ valuesSQL.append("DEFAULT");
+ }
+ foundOneColumnAlready = true;
+ }
+ insertSQL.append(") ");
+ valuesSQL.append(") ");
+ insertSQL.append(valuesSQL);
+
+ lcc = getEmbedConnection().getLanguageConnection();
+
+ // Context used for preparing, don't set any timeout (use 0)
+ statementContext = lcc.pushStatementContext(
+ isAtomic,
+ false,
+ insertSQL.toString(),
+ null,
+ false,
+ 0L);
+ org.apache.derby.iapi.sql.PreparedStatement ps =
+ lcc.prepareInternalStatement(insertSQL.toString());
+ Activation act = ps.getActivation(lcc, false);
+
+ // in this for loop we are assigning values for parameters
+ //in sql constructed earlier VALUES (?, ..)
+ for (int i=1, paramPosition=0; i<=rd.getColumnCount(); i++) {
+ // if the column got updated, do following
+ if (columnGotUpdated[i-1]) {
+ act.getParameterValueSet().
+ getParameterForSet(paramPosition++).
+ setValue(currentRow.getColumn(i));
+ }
+ }
+ // Don't see any timeout when inserting rows (use 0)
+ //execute the insert
+ org.apache.derby.iapi.sql.ResultSet rs =
+ ps.execute(act, false, true, true, 0L);
+ rs.close();
+ rs.finish();
+
+ lcc.popStatementContext(statementContext, null);
+ } catch (StandardException t) {
+ throw closeOnTransactionError(t);
+ } finally {
+ restoreContextStack();
+ }
+ }
}
/**
@@ -3223,6 +3348,10 @@
public void updateRow() throws SQLException {
synchronized (getConnectionSynchronization()) {
checksBeforeUpdateOrDelete("updateRow", -1);
+
+ // Check that the cursor is not positioned on insertRow
+ checkNotOnInsertRow();
+
setupContextStack();
LanguageConnectionContext lcc = null;
StatementContext statementContext = null;
@@ -3294,6 +3423,9 @@
public void deleteRow() throws SQLException {
synchronized (getConnectionSynchronization()) {
checksBeforeUpdateOrDelete("deleteRow", -1);
+
+ // Check that the cursor is not positioned on insertRow
+ checkNotOnInsertRow();
setupContextStack();
//now construct the delete where current of sql
@@ -3375,6 +3507,9 @@
*/
public void cancelRowUpdates () throws SQLException {
checksBeforeUpdateOrDelete("cancelRowUpdates", -1);
+
+ checkNotOnInsertRow();
+
if (currentRowHasBeenUpdated == false) return; //nothing got updated on this row so cancelRowUpdates is a no-op in this case.
for (int i=0; i < columnGotUpdated.length; i++){
@@ -3406,7 +3541,42 @@
* not updatable
*/
public void moveToInsertRow() throws SQLException {
- throw Util.notImplemented();
+ // if not updatable resultset, then throw exception
+ checkUpdatableCursor("moveToInsertRow");
+
+ checkExecIfClosed("moveToInsertRow");
+
+ synchronized (getConnectionSynchronization()) {
+ try {
+ // initialize state corresponding to insertRow/updateRow impl.
+ for (int i=0; i < columnGotUpdated.length; i++) {
+ columnGotUpdated[i] = false;
+ }
+ currentRowHasBeenUpdated = false;
+
+ // Remember position
+ if (!isOnInsertRow) {
+ currentRowBeforeInsert = currentRow;
+ }
+
+ isOnInsertRow = true;
+
+ // If insertRow has not been allocated yet, get new insertRow
+ if (insertRow == null) {
+ insertRow = stmt.lcc.getExecutionContext().
+ getExecutionFactory().getValueRow(columnGotUpdated.length);
+ }
+ for (int i=1; i <= columnGotUpdated.length; i++) {
+ insertRow.setColumn(i,
+ resultDescription.getColumnDescriptor(i).getType().getNull());
+ }
+ // Set currentRow to insertRow
+ currentRow = insertRow;
+ rowData = currentRow.getRowArray();
+ } catch (Throwable ex) {
+ handleException(ex);
+ }
+ }
}
/**
@@ -3420,7 +3590,36 @@
* not updatable
*/
public void moveToCurrentRow() throws SQLException {
- throw Util.notImplemented();
+ // if not updatable resultset, then throw exception
+ checkUpdatableCursor("moveToCurrentRow");
+
+ checkExecIfClosed("moveToCurrentRow");
+
+ synchronized (getConnectionSynchronization()) {
+ try {
+
+ if (isOnInsertRow) {
+ // Get position previous to moveToInsertRow
+ currentRow = currentRowBeforeInsert;
+ currentRowBeforeInsert = null;
+
+ // initialize state corresponding to insertRow/updateRow impl.
+ for (int i=0; i < columnGotUpdated.length; i++) {
+ columnGotUpdated[i] = false;
+ }
+ currentRowHasBeenUpdated = false;
+
+ // Get rowData
+ if (currentRow != null) {
+ rowData = currentRow.getRowArray();
+ }
+
+ isOnInsertRow = false;
+ }
+ } catch (Throwable ex) {
+ handleException(ex);
+ }
+ }
}
/**
@@ -3770,7 +3969,7 @@
if ((appConn == null) || appConn.isClosed())
throw Util.noCurrentConnection();
}
-
+
/**
* Try to see if we can fish the SQL Statement out of the local statement.
* @return null if we cannot figure out what SQL Statement is currently
@@ -3915,6 +4114,16 @@
StandardException
.getSeverityFromIdentifier(SQLState.NOT_ON_FORWARD_ONLY_CURSOR));
}
+
+ private void checkUpdatableCursor(String operation) throws SQLException {
+ if (getConcurrency() != JDBC20Translation.CONCUR_UPDATABLE) {
+ throw Util.generateCsSQLException(
+ SQLState.UPDATABLE_RESULTSET_API_DISALLOWED,
+ operation);
+ }
+ }
+
+
private boolean checkRowPosition(int position, String positionText)
throws SQLException {
// beforeFirst is only allowed on scroll cursors
Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties?rev=375635&r1=375634&r2=375635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties Tue Feb 7 08:09:10 2006
@@ -1122,6 +1122,7 @@
XJ083.U=''{0}'' not allowed because the ResultSet is not an updatable ResultSet.
XJ084.U=Column does not correspond to a column in the base table. Cannot issue ''{0}'' on this column.
XJ085.S=Stream has already been read and end-of-file reached and cannot be re-used.
+XJ086.S=This method cannot be invoked unless the cursor is positioned on the insert row.
0A000.S=Feature not implemented: {0}.
XJ004.C=Database ''{0}'' not found.
@@ -1279,5 +1280,6 @@
#
#
# ----------------------------------------------------------------------------------------------------------
+
Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_pt_BR.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_pt_BR.properties?rev=375635&r1=375634&r2=375635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_pt_BR.properties (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_pt_BR.properties Tue Feb 7 08:09:10 2006
@@ -1102,7 +1102,7 @@
XJ082.U=Valores de BLOB/CLOB n\u00e3o s\u00e3o permitidos como par\u00e2metros ou receptores de m\u00e9todos.
XJ083.U=''{0}'' n\u00e3o permitido porque o ResultSet n\u00e3o \u00e9 um ResultSet poss\u00edvel de atualizar.
XJ084.U=A coluna n\u00e3o corresponde \u00e0 coluna na tabela base. N\u00e3o \u00e9 poss\u00edvel emitir {0} nessa coluna.
-
+XJ086.S=Este m\u00E9todo n\u00E3o pode ser chamado a n\u00E3o ser que o cursor esteja posicionado na linha de inser\u00E7\u00E3o.
0A000.S=Recurso n\u00e3o implementado: {0}.
XJ004.C=Banco de dados ''{0}'' n\u00e3o localizado.
Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=375635&r1=375634&r2=375635&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Tue Feb 7 08:09:10 2006
@@ -1445,6 +1445,7 @@
//updatable resultset related
String UPDATABLE_RESULTSET_API_DISALLOWED = "XJ083.U";
String COLUMN_NOT_FROM_BASE_TABLE = "XJ084.U";
+ String NOT_POSITIONED_ON_INSERT_ROW = "XJ086.S";
//following are session severity.
String DATABASE_NOT_FOUND = "XJ004.C";