[
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-01-ac-grammar.diff
Attaching derby-3155-01-ac-grammar.diff. This is the first increment of work
for implementing the MERGE statement. This patch covers the grammar and bind()
logic. I will run tests.
Although permissions descriptors are attached at bind() time, I did not tackle
any of the permissions logic. The GRANT/REVOKE behavior of the MERGE statement
will have to be verified and debugged when the execution logic is written. This
may cascade changes back into the bind() logic.
It is also possible that I have modelled the bind() structures in a way which
will be frustrating for code-generation or execution. When I tackle
code-generation and execution, I may need to adjust the bind() logic further.
However, at this point I think that this increment is big enough for
submission. This is a convenient checkpoint of work on the MERGE statement.
Here is the basic model I have adopted:
1) The WHEN MATCHED ... THEN UPDATE clause is modelled by an internally
generated UpdateNode.
2) The WHEN MATCHED ... THEN DELETE clause is modelled by an internally
generated DeleteNode.
3) The WHEN NOT MATCHED ... THEN INSERT clause is modelled by an internally
generated InsertNode.
4) The WHEN [ NOT ] MATCHED clauses are driven by an internally generated
HalfOuterJoinNode which represents the following query:
sourceTable LEFT OUTER JOIN targetTable ON searchCondition
Along the way, I had to tweak other compile-time classes. However, I believe
that these tweaks are minor. So far, the MERGE statement has not caused a lot
of disruption.
A valid MERGE statement currently raises the following error at the end of the
bind phase:
ERROR 0A000: Feature not implemented: MERGE.
Touches the following files:
-------------------
M java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
Grammar changes, including the introduction of two new non-reserved keywords:
MERGE and MATCHED.
-------------------
A java/engine/org/apache/derby/impl/sql/compile/MergeNode.java
A java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java
Adds two new query nodes. MergeNode is a new DMLModStatementNode parallel to
InsertNode, UpdateNode, and DeleteNode. MatchingClauseNode is a single class
which can represent all three variants of the WHEN [ NOT ] MATCHED clause.
-------------------
M java/engine/org/apache/derby/impl/sql/compile/DeleteNode.java
M java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java
When we internally generate an UpdateNode for a WHEN MATCHED ... THEN UPDATE
clause, we have to allow references to the source table on the right side of
the SET operator. For example, in the following statement...
merge into t1
using t2
on t1.c1 = t2.c1
when matched and t1.c2 != t2.c2 then update set c2 = t2.c2;
...we allow "set c2 = t2.c2" even though the table being updated is t1, not t2.
This means that for this case we must disable a little piece of logic which was
deliberately nulling out the tablename in expressions on the right side of the
SET operator.
In addition, I disabled a Sanity check which prevented us from having more than
one table in the query which drives an UPDATE statement. This was necessary in
order to use a left join to drive the WHEN MATCHED ... THEN UPDATE clause.
-------------------
M java/engine/org/apache/derby/impl/sql/compile/UnionNode.java
M java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
M java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
Some extra book-keeping was added in order to support DEFAULT values for
generated columns in WHEN NOT MATCHED ... THEN INSERT clauses. The handling of
generated columns (including identity columns) is already a set of brittle
special cases. This makes the handling more brittle and flags an area which may
need extra testing.
-------------------
M java/engine/org/apache/derby/impl/sql/compile/JoinNode.java
Two new methods were created in order to abstract out some bind() logic. That
logic is now used both by ordinary left joins and by the internally generated
left join which drives the MERGE statement.
-------------------
M java/engine/org/apache/derby/loc/messages.xml
M java/shared/org/apache/derby/shared/common/reference/SQLState.java
Adds 3 new messages for errors discovered at bind() time.
-------------------
M
java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.java
M
java/testing/org/apache/derbyTesting/functionTests/tests/lang/_Suite.java
A
java/testing/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java
Adds a battery of tests for the MERGE statement's bind() logic. Mostly these
are negative tests, stressing error conditions.
> 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
> Labels: derby_triage10_10
> Attachments: derby-3155-01-ac-grammar.diff, 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 is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira