[ 
https://issues.apache.org/jira/browse/DERBY-3155?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Rick Hillegas updated DERBY-3155:
---------------------------------

    Attachment: derby-3155-04-af-deleteAction.diff

Attaching derby-3155-04-af-deleteAction.diff. This patch enables the DELETE 
action of the MERGE statement, capitalizing on the row location work done by 
derby-3155-03-ah-backingStoreHashtableWithRowLocation.diff. I am running tests 
now.

With this patch, I am able to use the MERGE statement to DELETE rows. Various 
combinations of the following conditions have been tested:

1) MERGE statements with and without refined conditions in the WHEN MATCHED 
clause.

2) Search conditions which cause the optimizer to choose a nested-loop strategy.

3) Search conditions which cause the optimizer to choose a hash-join strategy.

4) Target tables with before and after per-row triggers.

5) Target tables with before and after per-statement triggers.


The basic operation of the MERGE statement is described by the header comment 
in MergeNode. The following additional execution behavior is worth mentioning:

The MergeResultSet loops through the rows coming from the driving left-join, 
assigning each row to a WHEN [ NOT ] MATCHED action. After all of the rows have 
been assigned, the MergeResultSet then calls logic in each matching clause 
action to process the buffered rows assigned to that action. The matching 
clause action does the following:

i) Pushes the corresponding INSERT/UPDATE/DELETE ConstantAction onto a stack of 
constant actions, introduced by this patch. This makes that 
INSERT/UPDATE/DELETE ConstantAction the current ConstantAction for the 
Activation. Introducing a stack of ConstantActions caused fewer code changes 
than wrenching around the constructors and code generators for the 
Insert/Update/DeleteResultSets so that they could handle fetching a 
ConstantAction out of a variable in the Activation. The 
Insert/Update/DeleteResultSets continue to take whatever ConstantAction is at 
the top of the stack.

ii) Pokes the temporary ResultSet of buffered rows into a variable which is 
pushed as an argument to the Insert/Update/DeleteResultSet.

iii) Invokes a method to instantiate the Insert/Update/DeleteResultSet.

iv) Opens the Insert/Update/DeleteResultSet in order to cause it to execute.


Touches the following files:

---------------

M       java/engine/org/apache/derby/impl/sql/compile/MergeNode.java
M       java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java
M       java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
M       java/engine/org/apache/derby/impl/sql/compile/DeleteNode.java
M       java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java
M       java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
M       java/engine/org/apache/derby/impl/sql/compile/DMLModStatementNode.java
M       java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
M       java/engine/org/apache/derby/impl/sql/compile/CurrentOfNode.java
M       java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj

Changes for binding and code-generating MERGE statements with DELETE actions. 
See the header comment in MergeNode for more details.

---------------

M       java/engine/org/apache/derby/iapi/sql/Activation.java
M       java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java
M       java/engine/org/apache/derby/impl/sql/GenericActivationHolder.java

Introduces a stack of ConstantActions.

---------------

M       java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
M       
java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
M       java/engine/org/apache/derby/impl/sql/execute/DMLWriteResultSet.java
A       java/engine/org/apache/derby/impl/sql/execute/MergeResultSet.java

Execution machinery to process the left-join, assign qualifying rows to the 
appropriate MatchingClauseConstantAction, and then invoke those ConstantActions 
in order after the left-join is drained.

---------------

M       java/engine/org/apache/derby/iapi/sql/execute/ConstantAction.java
M       java/engine/org/apache/derby/iapi/services/io/RegisteredFormatIds.java
M       java/engine/org/apache/derby/iapi/services/io/StoredFormatIds.java
A       java/engine/org/apache/derby/impl/sql/execute/MergeConstantAction.java
A       
java/engine/org/apache/derby/impl/sql/execute/MatchingClauseConstantAction.java
M       
java/engine/org/apache/derby/impl/sql/execute/GenericConstantActionFactory.java

New Formatable ConstantActions: one for the overall MERGE statement and another 
for its WHEN [ NOT ] MATCHED clauses.

---------------

M       java/engine/org/apache/derby/impl/sql/execute/ScanResultSet.java
M       java/engine/org/apache/derby/impl/sql/execute/HashScanResultSet.java
M       
java/engine/org/apache/derby/impl/sql/execute/BulkTableScanResultSet.java

Changes to retrieve the target table's RowLocation during the processing of the 
driving left-join.

---------------

M       java/engine/org/apache/derby/impl/sql/execute/DeleteResultSet.java
M       java/engine/org/apache/derby/impl/store/access/heap/HeapRowLocation.java

Change HeapRowLocation.getObject() to return itself rather than null. This is 
the economical way to retrieve a RowLocation from a bulk scan.

---------------

M       java/engine/org/apache/derby/loc/messages.xml

Re-worded an error message so it could be re-used for a MERGE-related error 
condition.

---------------

M       
java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.java
M       
java/testing/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java

Tests for the new functionality.


> Support for SQL:2003 MERGE statement
> ------------------------------------
>
>                 Key: DERBY-3155
>                 URL: https://issues.apache.org/jira/browse/DERBY-3155
>             Project: Derby
>          Issue Type: Improvement
>          Components: SQL
>            Reporter: Trejkaz
>            Assignee: Rick Hillegas
>              Labels: derby_triage10_10
>         Attachments: derby-3155-01-ac-grammar.diff, 
> derby-3155-02-ag-fixParserWarning.diff, 
> derby-3155-03-ae-backingStoreHashtableWithRowLocation.diff, 
> derby-3155-03-af-backingStoreHashtableWithRowLocation.diff, 
> derby-3155-03-ag-backingStoreHashtableWithRowLocation.diff, 
> derby-3155-03-ah-backingStoreHashtableWithRowLocation.diff, 
> derby-3155-04-ae-deleteAction.diff, derby-3155-04-af-deleteAction.diff, 
> MergeStatement.html, MergeStatement.html, MergeStatement.html
>
>
> A relatively common piece of logic in a database application is to check for 
> a row's existence and then either update or insert depending on its existence.
> SQL:2003 added a MERGE statement to perform this operation.  It looks like 
> this:
>     MERGE INTO table_name USING table_name ON (condition)
>     WHEN MATCHED THEN UPDATE SET column1 = value1 [, column2 = value2 ...]
>     WHEN NOT MATCHED THEN INSERT column1 [, column2 ...] VALUES (value1 [, 
> value2 ...]) 
> At the moment, the only workaround for this would be to write a stored 
> procedure to do the same operation, or to implement the logic client-side.



--
This message was sent by Atlassian JIRA
(v6.1#6144)

Reply via email to