[
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-30-ab-moreCorrelationNames.diff
Attaching derby-3155-30-ab-moreCorrelationNames.diff. This patch fixes more
column resolution problems. I am running tests now.
Working on this patch has helped me understand a defect (or at least a
brittleness) in my approach to implementing the UPDATE action of the MERGE
statement. The dummy UPDATE statement I create is one which can not arise via
the supported Derby grammar. That is because this UPDATE statement is driven by
a SELECT having more than one table. An ordinary Derby UPDATE can be driven by
a multi-table SELECT but only if the SELECT is hidden behind a WHERE CURRENT OF
clause.
The existing logic takes advantage of an assumption that the driving SELECT
only has columns from the table being UPDATEd. In particular, there is some
UpdateNode logic (around line 1530) which clears out table identifiers from the
UPDATE statement's column list. It appears that that logic was added as part of
the work on DERBY-1043. But without those table identifiers, I can't
distinguish between columns coming from the source vs. the target table of a
MERGE statement.
My original solution to this problem was to skip the logic which clears out
table identifiers when I am binding a MERGE statement. That worked for a long
time until I started trying to compile UPDATE actions which supplement their
column lists with extra columns needed to evaluate constraints, triggers, and
generation expressions. I re-instated id-clearing logic in order to make those
statements compile.
This revived the ambiguity when the source and target tables had columns with
the same name. My solution is to double-down on associating all columns with
the source vs. target tables before binding the INSERT/UPDATE/DELETE actions.
It's possible that I will continue to be buried under a pile of column
resolution problems. I may need to fall back and re-implement the UPDATE action
so that it uses some dummy column list which could be concocted via SQL and
then add some substitution logic to map between the dummy column list and the
expressions in the SET clauses.
However, for the moment I'm doubling down on the current implementation.
Touches the following files:
----------------
M java/engine/org/apache/derby/iapi/sql/compile/TagFilter.java
M java/engine/org/apache/derby/impl/sql/compile/UpdateNode.java
Columns added to satisfy constraints, triggers, and generation clauses are
assocated with the TARGET table. The table-id-clearing logic is re-instated.
----------------
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/DMLModStatementNode.java
M java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
M java/engine/org/apache/derby/impl/sql/compile/FromTable.java
More logic to associate columns with the source or target table.
----------------
M java/engine/org/apache/derby/impl/sql/compile/FromList.java
Use the pre-computed association of columns with source/target tables to
resolve column references.
----------------
M java/engine/org/apache/derby/impl/sql/compile/ColumnReference.java
Minor tweak to improve encapsulation and tracing of this class.
----------------
M
java/testing/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java
Additional tests.
> 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: MergeStatement.html, MergeStatement.html,
> MergeStatement.html, MergeStatement.html, 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,
> derby-3155-05-aa-triggerTransitionTableAsTarget.diff,
> derby-3155-06-aa-triggerTransitionTableAsSource.diff,
> derby-3155-07-ad-insertAction.diff, derby-3155-08-ah-updateAction.diff,
> derby-3155-09-aa-correlationNames.diff,
> derby-3155-10-aa-correlationNames.diff,
> derby-3155-11-ab-beforeTriggersCantFireMerge.diff,
> derby-3155-12-aa-canOmitInsertColumnList.diff,
> derby-3155-13-aa-allowSystemAndTempTables.diff,
> derby-3155-14-aa-replaceCorrelationNamesOnLeftSideOfSETclauses.diff,
> derby-3155-15-aa-replumbMergeResultSetCleanup.diff,
> derby-3155-16-aa-treatCurrentRowLocationNodeLikeBaseColumnNode.diff,
> derby-3155-17-aa-serializingRowLocations.diff,
> derby-3155-18-aa-basicView.diff,
> derby-3155-19-aa-forbidSubqueriesInMatchedClauses.diff,
> derby-3155-20-aa-reworkColumnMatching.diff,
> derby-3155-21-ac-cleanupAndForbidSynonyms.diff,
> derby-3155-22-ad-testIdentifiersOnLeftSideOfSetClauses.diff,
> derby-3155-23-aa-forbidDerivedColumnLists.diff,
> derby-3155-24-aa-supportParameters.diff,
> derby-3155-25-aa-parametersAsInsertValues.diff,
> derby-3155-26-aa-copyRowLocationForIndexScans.diff,
> derby-3155-27-aa-adjustMatchingRefinements.diff,
> derby-3155-28-aa-cardinalityViolations.diff,
> derby-3155-29-aa-missingSchema.diff,
> derby-3155-30-ab-moreCorrelationNames.diff
>
>
> 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.5#6160)