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 rh...@apache.org on 2014/03/20 20:50:05 UTC
svn commit: r1579725 - in
/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql:
compile/MatchingClauseNode.java compile/MergeNode.java
execute/MatchingClauseConstantAction.java
Author: rhillegas
Date: Thu Mar 20 19:50:05 2014
New Revision: 1579725
URL: http://svn.apache.org/r1579725
Log:
DERBY-3155: Cleanup MERGE statement in order to make the code more readable; commit derby-3155-49-aa-cleanup1.diff.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MergeNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/MatchingClauseConstantAction.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java?rev=1579725&r1=1579724&r2=1579725&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MatchingClauseNode.java Thu Mar 20 19:50:05 2014
@@ -173,22 +173,19 @@ public class MatchingClauseNode extends
/** Return true if this is a WHEN MATCHED ... DELETE clause */
boolean isDeleteClause() { return !( isUpdateClause() || isInsertClause() ); }
- /** Return the bound DML statement--returns null if called before binding */
- DMLModStatementNode getDML() { return _dml; }
-
/**
* Return the list of columns which form the rows of the ResultSet which drive
* the INSERT/UPDATE/DELETE actions.
*/
- ResultColumnList getBufferedColumns() { return _thenColumns; }
+ ResultColumnList getThenColumns() { return _thenColumns; }
///////////////////////////////////////////////////////////////////////////////////
//
- // bind() BEHAVIOR
+ // bind() BEHAVIOR CALLED BY MergeNode
//
///////////////////////////////////////////////////////////////////////////////////
- /** Bind this WHEN [ NOT ] MATCHED clause against the parent JoinNode */
+ /** Bind this WHEN [ NOT ] MATCHED clause against the parent MergeNode */
void bind
(
DataDictionary dd,
@@ -280,7 +277,11 @@ public class MatchingClauseNode extends
}
}
- ////////////////////// UPDATE ///////////////////////////////
+ ////////////////
+ //
+ // BIND UPDATE
+ //
+ ////////////////
/** Bind a WHEN MATCHED ... THEN UPDATE clause */
private void bindUpdate
@@ -693,7 +694,11 @@ public class MatchingClauseNode extends
}
- ////////////////////// DELETE ///////////////////////////////
+ ////////////////
+ //
+ // BIND DELETE
+ //
+ ////////////////
/** Bind a WHEN MATCHED ... THEN DELETE clause */
private void bindDelete
@@ -772,7 +777,7 @@ public class MatchingClauseNode extends
/**
* <p>
- * Calculate the 1-based offsets which define the rows which will be buffered up
+ * Calculate the 1-based offsets which define the "then" rows which will be buffered up
* for a DELETE action at run-time. The rows are constructed
* from the columns in the SELECT list of the driving left joins. This method
* calculates an array of offsets into the SELECT list. The columns at those
@@ -783,21 +788,25 @@ public class MatchingClauseNode extends
private void bindDeleteThenColumns( ResultColumnList selectList )
throws StandardException
{
- int bufferedCount = _thenColumns.size();
+ int thenCount = _thenColumns.size();
int selectCount = selectList.size();
- _deleteColumnOffsets = new int[ bufferedCount ];
+ _deleteColumnOffsets = new int[ thenCount ];
- for ( int bidx = 0; bidx < bufferedCount; bidx++ )
+ for ( int bidx = 0; bidx < thenCount; bidx++ )
{
- ResultColumn bufferedRC = _thenColumns.elementAt( bidx );
- ValueNode bufferedExpression = bufferedRC.getExpression();
+ ResultColumn thenRC = _thenColumns.elementAt( bidx );
+ ValueNode thenExpression = thenRC.getExpression();
- _deleteColumnOffsets[ bidx ] = getSelectListOffset( selectList, bufferedExpression );
+ _deleteColumnOffsets[ bidx ] = getSelectListOffset( selectList, thenExpression );
}
}
- ////////////////////// INSERT ///////////////////////////////
+ ////////////////
+ //
+ // BIND INSERT
+ //
+ ////////////////
/** Bind a WHEN NOT MATCHED ... THEN INSERT clause */
private void bindInsert
@@ -1087,33 +1096,11 @@ public class MatchingClauseNode extends
}
- ////////////////////// bind() MINIONS ///////////////////////////////
-
- /** Boilerplate for binding a list of ResultColumns against a FromList */
- private void bindExpressions( ResultColumnList rcl, FromList fromList )
- throws StandardException
- {
- CompilerContext cc = getCompilerContext();
- final int previousReliability = cc.getReliability();
-
- boolean wasSkippingTypePrivileges = cc.skipTypePrivileges( true );
- cc.setReliability( previousReliability | CompilerContext.SQL_IN_ROUTINES_ILLEGAL );
-
- try {
- rcl.bindExpressions
- (
- fromList,
- new SubqueryList( getContextManager() ),
- new ArrayList<AggregateNode>()
- );
- }
- finally
- {
- // Restore previous compiler state
- cc.setReliability( previousReliability );
- cc.skipTypePrivileges( wasSkippingTypePrivileges );
- }
- }
+ ////////////////////////
+ //
+ // BIND THE THEN ROW
+ //
+ ////////////////////////
/**
* <p>
@@ -1133,16 +1120,16 @@ public class MatchingClauseNode extends
* can't be found.
* </p>
*/
- private int getSelectListOffset( ResultColumnList selectList, ValueNode bufferedExpression )
+ private int getSelectListOffset( ResultColumnList selectList, ValueNode thenExpression )
throws StandardException
{
int selectCount = selectList.size();
- if ( bufferedExpression instanceof ColumnReference )
+ if ( thenExpression instanceof ColumnReference )
{
- ColumnReference bufferedCR = (ColumnReference) bufferedExpression;
- String bufferedCRName = bufferedCR.getColumnName();
- int bufferedCRMergeTableID = getMergeTableID( bufferedCR );
+ ColumnReference thenCR = (ColumnReference) thenExpression;
+ String thenCRName = thenCR.getColumnName();
+ int thenCRMergeTableID = getMergeTableID( thenCR );
// loop through the SELECT list to find this column reference
for ( int sidx = 0; sidx < selectCount; sidx++ )
@@ -1155,8 +1142,8 @@ public class MatchingClauseNode extends
if ( selectCR != null )
{
if (
- ( getMergeTableID( selectCR ) == bufferedCRMergeTableID) &&
- bufferedCRName.equals( selectCR.getColumnName() )
+ ( getMergeTableID( selectCR ) == thenCRMergeTableID) &&
+ thenCRName.equals( selectCR.getColumnName() )
)
{
return sidx + 1;
@@ -1168,12 +1155,12 @@ public class MatchingClauseNode extends
{
SanityManager.THROWASSERT
(
- "Can't find select list column corresponding to " + bufferedCR.getSQLColumnName() +
- " with merge table id = " + bufferedCRMergeTableID
+ "Can't find select list column corresponding to " + thenCR.getSQLColumnName() +
+ " with merge table id = " + thenCRMergeTableID
);
}
}
- else if ( bufferedExpression instanceof CurrentRowLocationNode )
+ else if ( thenExpression instanceof CurrentRowLocationNode )
{
//
// There is only one RowLocation in the SELECT list, the row location for the
@@ -1203,6 +1190,38 @@ public class MatchingClauseNode extends
return mergeTableID;
}
+ /////////////////
+ //
+ // BIND MINIONS
+ //
+ /////////////////
+
+ /** Boilerplate for binding a list of ResultColumns against a FromList */
+ private void bindExpressions( ResultColumnList rcl, FromList fromList )
+ throws StandardException
+ {
+ CompilerContext cc = getCompilerContext();
+ final int previousReliability = cc.getReliability();
+
+ boolean wasSkippingTypePrivileges = cc.skipTypePrivileges( true );
+ cc.setReliability( previousReliability | CompilerContext.SQL_IN_ROUTINES_ILLEGAL );
+
+ try {
+ rcl.bindExpressions
+ (
+ fromList,
+ new SubqueryList( getContextManager() ),
+ new ArrayList<AggregateNode>()
+ );
+ }
+ finally
+ {
+ // Restore previous compiler state
+ cc.setReliability( previousReliability );
+ cc.skipTypePrivileges( wasSkippingTypePrivileges );
+ }
+ }
+
/**
* <p>
* Forbid subqueries in WHEN [ NOT ] MATCHED clauses.
@@ -1385,7 +1404,7 @@ public class MatchingClauseNode extends
/**
* <p>
- * Adds a field to the generated class to hold the ResultSet of buffered rows
+ * Adds a field to the generated class to hold the ResultSet of "then" rows
* which drive the INSERT/UPDATE/DELETE action. Generates code to push
* the contents of that field onto the stack.
* </p>
@@ -1525,17 +1544,6 @@ public class MatchingClauseNode extends
}
}
- /** Return true if the ResultColumn represents a RowLocation */
- private boolean isRowLocation( ResultColumn rc ) throws StandardException
- {
- if ( rc.getExpression() instanceof CurrentRowLocationNode ) { return true; }
-
- DataTypeDescriptor dtd = rc.getTypeServices();
- if ( (dtd != null) && (dtd.getTypeId().isRefTypeId()) ) { return true; }
-
- return false;
- }
-
///////////////////////////////////////////////////////////////////////////////////
//
// Visitable BEHAVIOR
@@ -1634,4 +1642,15 @@ public class MatchingClauseNode extends
return getCRs.getList();
}
+ /** Return true if the ResultColumn represents a RowLocation */
+ private boolean isRowLocation( ResultColumn rc ) throws StandardException
+ {
+ if ( rc.getExpression() instanceof CurrentRowLocationNode ) { return true; }
+
+ DataTypeDescriptor dtd = rc.getTypeServices();
+ if ( (dtd != null) && (dtd.getTypeId().isRefTypeId()) ) { return true; }
+
+ return false;
+ }
+
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MergeNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MergeNode.java?rev=1579725&r1=1579724&r2=1579725&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MergeNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MergeNode.java Thu Mar 20 19:50:05 2014
@@ -119,7 +119,7 @@ import org.apache.derby.shared.common.sa
* whether a given driving row matches. The row matches iff targetTable.RowLocation is not null.
* The driving row is then assigned to the
* first DELETE/UPDATE/INSERT action to which it applies. The relevant columns from
- * the driving row are extracted and buffered in a temporary table specific to that
+ * the driving row are extracted and buffered in a temporary table (the "then" rows) specific to that
* DELETE/UPDATE/INSERT action. After the driving left join has been processed,
* the DELETE/UPDATE/INSERT actions are run in order, each taking its corresponding
* temporary table as its source ResultSet.
@@ -193,6 +193,90 @@ public final class MergeNode extends DML
///////////////////////////////////////////////////////////////////////////////////
//
+ // BIND-TIME ENTRY POINTS CALLED BY MatchingClauseNode
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ /** Get the target table for the MERGE statement */
+ FromBaseTable getTargetTable() { return _targetTable; }
+
+ /** Associate a column with the SOURCE or TARGET table */
+ void associateColumn( FromList fromList, ColumnReference cr, int mergeTableID )
+ throws StandardException
+ {
+ if ( mergeTableID != ColumnReference.MERGE_UNKNOWN ) { cr.setMergeTableID( mergeTableID ); }
+ else
+ {
+ // we have to figure out which table the column is in
+ String columnsTableName = cr.getTableName();
+
+ if ( ((FromTable) fromList.elementAt( SOURCE_TABLE_INDEX )).getMatchingColumn( cr ) != null )
+ {
+ cr.setMergeTableID( ColumnReference.MERGE_SOURCE );
+ }
+ else if ( ((FromTable) fromList.elementAt( TARGET_TABLE_INDEX )).getMatchingColumn( cr ) != null )
+ {
+ cr.setMergeTableID( ColumnReference.MERGE_TARGET );
+ }
+ }
+
+ // Don't raise an error if a column in another table is referenced and we
+ // don't know how to handle it here. If the column is not in the SOURCE or TARGET
+ // table, then it will be caught by other bind-time logic. Columns which ought
+ // to be associated, but aren't, will be caught later on by MatchingClauseNode.getMergeTableID().
+ }
+
+ /** Boilerplate for binding an expression against a FromList */
+ void bindExpression( ValueNode value, FromList fromList )
+ throws StandardException
+ {
+ CompilerContext cc = getCompilerContext();
+ final int previousReliability = cc.getReliability();
+
+ cc.setReliability( previousReliability | CompilerContext.SQL_IN_ROUTINES_ILLEGAL );
+ cc.pushCurrentPrivType( Authorizer.SELECT_PRIV );
+
+ try {
+ // this adds SELECT priv on referenced columns and EXECUTE privs on referenced routines
+ value.bindExpression
+ (
+ fromList,
+ new SubqueryList( getContextManager() ),
+ new ArrayList<AggregateNode>()
+ );
+ }
+ finally
+ {
+ // Restore previous compiler state
+ cc.popCurrentPrivType();
+ cc.setReliability( previousReliability );
+ }
+ }
+
+ /** Add the columns in the matchingRefinement clause to the evolving map */
+ void getColumnsInExpression
+ ( HashMap<String,ColumnReference> map, ValueNode expression, int mergeTableID )
+ throws StandardException
+ {
+ if ( expression == null ) { return; }
+
+ List<ColumnReference> colRefs = getColumnReferences( expression );
+
+ getColumnsFromList( map, colRefs, mergeTableID );
+ }
+
+ /** Add a list of columns to the the evolving map */
+ void getColumnsFromList
+ ( HashMap<String,ColumnReference> map, ResultColumnList rcl, int mergeTableID )
+ throws StandardException
+ {
+ List<ColumnReference> colRefs = getColumnReferences( rcl );
+
+ getColumnsFromList( map, colRefs, mergeTableID );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
// bind() BEHAVIOR
//
///////////////////////////////////////////////////////////////////////////////////
@@ -252,40 +336,11 @@ public final class MergeNode extends DML
bindLeftJoin( dd );
}
- /** Create a FromList for binding a WHEN [ NOT ] MATCHED clause */
- private FromList cloneFromList( DataDictionary dd, FromBaseTable targetTable )
- throws StandardException
- {
- FromList dummyFromList = new FromList( getContextManager() );
- FromBaseTable dummyTargetTable = new FromBaseTable
- (
- targetTable.getTableNameField(),
- targetTable.correlationName,
- null,
- null,
- getContextManager()
- );
- FromTable dummySourceTable = cloneFromTable( _sourceTable );
-
- dummyTargetTable.setMergeTableID( ColumnReference.MERGE_TARGET );
- dummySourceTable.setMergeTableID ( ColumnReference.MERGE_SOURCE );
-
- dummyFromList.addFromTable( dummySourceTable );
- dummyFromList.addFromTable( dummyTargetTable );
-
- //
- // Don't add any privileges while binding the tables.
- //
- IgnoreFilter ignorePermissions = new IgnoreFilter();
- getCompilerContext().addPrivilegeFilter( ignorePermissions );
-
- dummyFromList.bindTables( dd, new FromList( getOptimizerFactory().doJoinOrderOptimization(), getContextManager() ) );
-
- // ready to add permissions
- getCompilerContext().removePrivilegeFilter( ignorePermissions );
-
- return dummyFromList;
- }
+ /////////////////////////////////////
+ //
+ // TABLE AND CORRELATION CHECKS
+ //
+ /////////////////////////////////////
/** Get the exposed name of a FromTable */
private String getExposedName( FromTable ft ) throws StandardException
@@ -337,6 +392,59 @@ public final class MergeNode extends DML
}
}
+ /** Throw a "not base table" exception */
+ private void notBaseTable() throws StandardException
+ {
+ throw StandardException.newException( SQLState.LANG_TARGET_NOT_BASE_TABLE );
+ }
+
+ /** Return true if the target table is a base table */
+ private boolean targetIsBaseTable( FromBaseTable targetTable ) throws StandardException
+ {
+ FromBaseTable fbt = targetTable;
+ TableDescriptor desc = fbt.getTableDescriptor();
+ if ( desc == null ) { return false; }
+
+ switch( desc.getTableType() )
+ {
+ case TableDescriptor.BASE_TABLE_TYPE:
+ case TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ /** Return true if the source table is a base table, view, or table function */
+ private boolean sourceIsBase_View_or_VTI() throws StandardException
+ {
+ if ( _sourceTable instanceof FromVTI ) { return true; }
+ if ( !( _sourceTable instanceof FromBaseTable) ) { return false; }
+
+ FromBaseTable fbt = (FromBaseTable) _sourceTable;
+ TableDescriptor desc = fbt.getTableDescriptor();
+ if ( desc == null ) { return false; }
+
+ switch( desc.getTableType() )
+ {
+ case TableDescriptor.BASE_TABLE_TYPE:
+ case TableDescriptor.SYSTEM_TABLE_TYPE:
+ case TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE:
+ case TableDescriptor.VIEW_TYPE:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ ///////////////////////////
+ //
+ // BINDING THE LEFT JOIN
+ //
+ ///////////////////////////
+
/**
* Bind the driving left join select.
* Stuffs the left join SelectNode into the resultSet variable.
@@ -453,109 +561,45 @@ public final class MergeNode extends DML
}
}
- /** Get the target table for the MERGE statement */
- FromBaseTable getTargetTable() { return _targetTable; }
-
- /** Throw a "not base table" exception */
- private void notBaseTable() throws StandardException
- {
- throw StandardException.newException( SQLState.LANG_TARGET_NOT_BASE_TABLE );
- }
+ ////////////////////////////
+ //
+ // CLONING THE FROM LIST
+ //
+ ////////////////////////////
- /** Build the select list for the left join */
- private ResultColumnList buildSelectList() throws StandardException
+ /** Create a FromList for binding a WHEN [ NOT ] MATCHED clause */
+ private FromList cloneFromList( DataDictionary dd, FromBaseTable targetTable )
+ throws StandardException
{
- HashMap<String,ColumnReference> drivingColumnMap = new HashMap<String,ColumnReference>();
- getColumnsInExpression( drivingColumnMap, _searchCondition, ColumnReference.MERGE_UNKNOWN );
-
- for ( MatchingClauseNode mcn : _matchingClauses )
- {
- mcn.getColumnsInExpressions( this, drivingColumnMap );
-
- int mergeTableID = mcn.isDeleteClause() ? ColumnReference.MERGE_TARGET : ColumnReference.MERGE_UNKNOWN;
- getColumnsFromList( drivingColumnMap, mcn.getBufferedColumns(), mergeTableID );
- }
-
- ResultColumnList selectList = new ResultColumnList( getContextManager() );
-
- // add all of the columns from the source table which are mentioned
- addColumns
- (
- (FromTable) _leftJoinFromList.elementAt( SOURCE_TABLE_INDEX ),
- drivingColumnMap,
- selectList,
- ColumnReference.MERGE_SOURCE
- );
- // add all of the columns from the target table which are mentioned
- addColumns
+ FromList dummyFromList = new FromList( getContextManager() );
+ FromBaseTable dummyTargetTable = new FromBaseTable
(
- (FromTable) _leftJoinFromList.elementAt( TARGET_TABLE_INDEX ),
- drivingColumnMap,
- selectList,
- ColumnReference.MERGE_TARGET
+ targetTable.getTableNameField(),
+ targetTable.correlationName,
+ null,
+ null,
+ getContextManager()
);
+ FromTable dummySourceTable = cloneFromTable( _sourceTable );
- addTargetRowLocation( selectList );
-
- return selectList;
- }
-
- /** Add the target table's row location to the left join's select list */
- private void addTargetRowLocation( ResultColumnList selectList )
- throws StandardException
- {
- // tell the target table to generate a row location column
- _targetTable.setRowLocationColumnName( TARGET_ROW_LOCATION_NAME );
-
- TableName fromTableName = _targetTable.getTableName();
- ColumnReference cr = new ColumnReference
- ( TARGET_ROW_LOCATION_NAME, fromTableName, getContextManager() );
- cr.setMergeTableID( ColumnReference.MERGE_TARGET );
- ResultColumn rowLocationColumn = new ResultColumn( (String) null, cr, getContextManager() );
- rowLocationColumn.markGenerated();
-
- selectList.addResultColumn( rowLocationColumn );
- }
-
- /** Return true if the target table is a base table */
- private boolean targetIsBaseTable( FromBaseTable targetTable ) throws StandardException
- {
- FromBaseTable fbt = targetTable;
- TableDescriptor desc = fbt.getTableDescriptor();
- if ( desc == null ) { return false; }
-
- switch( desc.getTableType() )
- {
- case TableDescriptor.BASE_TABLE_TYPE:
- case TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE:
- return true;
-
- default:
- return false;
- }
- }
-
- /** Return true if the source table is a base table, view, or table function */
- private boolean sourceIsBase_View_or_VTI() throws StandardException
- {
- if ( _sourceTable instanceof FromVTI ) { return true; }
- if ( !( _sourceTable instanceof FromBaseTable) ) { return false; }
-
- FromBaseTable fbt = (FromBaseTable) _sourceTable;
- TableDescriptor desc = fbt.getTableDescriptor();
- if ( desc == null ) { return false; }
-
- switch( desc.getTableType() )
- {
- case TableDescriptor.BASE_TABLE_TYPE:
- case TableDescriptor.SYSTEM_TABLE_TYPE:
- case TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE:
- case TableDescriptor.VIEW_TYPE:
- return true;
+ dummyTargetTable.setMergeTableID( ColumnReference.MERGE_TARGET );
+ dummySourceTable.setMergeTableID ( ColumnReference.MERGE_SOURCE );
+
+ dummyFromList.addFromTable( dummySourceTable );
+ dummyFromList.addFromTable( dummyTargetTable );
+
+ //
+ // Don't add any privileges while binding the tables.
+ //
+ IgnoreFilter ignorePermissions = new IgnoreFilter();
+ getCompilerContext().addPrivilegeFilter( ignorePermissions );
+
+ dummyFromList.bindTables( dd, new FromList( getOptimizerFactory().doJoinOrderOptimization(), getContextManager() ) );
- default:
- return false;
- }
+ // ready to add permissions
+ getCompilerContext().removePrivilegeFilter( ignorePermissions );
+
+ return dummyFromList;
}
/** Clone a FromTable to avoid binding the original */
@@ -593,6 +637,12 @@ public final class MergeNode extends DML
}
}
+ ///////////////////////////
+ //
+ // PRIVILEGE MANAGEMENT
+ //
+ ///////////////////////////
+
/**
* <p>
* Add the privileges required by the ON clause.
@@ -658,6 +708,92 @@ public final class MergeNode extends DML
cc.popCurrentPrivType();
}
+ /** Get a list of CastNodes in an expression */
+ private List<CastNode> getCastNodes( QueryTreeNode expression )
+ throws StandardException
+ {
+ CollectNodesVisitor<CastNode> getCNs =
+ new CollectNodesVisitor<CastNode>(CastNode.class);
+
+ expression.accept(getCNs);
+
+ return getCNs.getList();
+ }
+
+ /** Get a list of routines in an expression */
+ private List<StaticMethodCallNode> getRoutineReferences( QueryTreeNode expression )
+ throws StandardException
+ {
+ CollectNodesVisitor<StaticMethodCallNode> getSMCNs =
+ new CollectNodesVisitor<StaticMethodCallNode>(StaticMethodCallNode.class);
+
+ expression.accept(getSMCNs);
+
+ return getSMCNs.getList();
+ }
+
+ ///////////////////////////////
+ //
+ // BUILD THE SELECT LIST
+ // FOR THE DRIVING LEFT JOIN
+ //
+ ///////////////////////////////
+
+ /** Build the select list for the left join */
+ private ResultColumnList buildSelectList() throws StandardException
+ {
+ HashMap<String,ColumnReference> drivingColumnMap = new HashMap<String,ColumnReference>();
+ getColumnsInExpression( drivingColumnMap, _searchCondition, ColumnReference.MERGE_UNKNOWN );
+
+ for ( MatchingClauseNode mcn : _matchingClauses )
+ {
+ mcn.getColumnsInExpressions( this, drivingColumnMap );
+
+ int mergeTableID = mcn.isDeleteClause() ? ColumnReference.MERGE_TARGET : ColumnReference.MERGE_UNKNOWN;
+ getColumnsFromList( drivingColumnMap, mcn.getThenColumns(), mergeTableID );
+ }
+
+ ResultColumnList selectList = new ResultColumnList( getContextManager() );
+
+ // add all of the columns from the source table which are mentioned
+ addColumns
+ (
+ (FromTable) _leftJoinFromList.elementAt( SOURCE_TABLE_INDEX ),
+ drivingColumnMap,
+ selectList,
+ ColumnReference.MERGE_SOURCE
+ );
+ // add all of the columns from the target table which are mentioned
+ addColumns
+ (
+ (FromTable) _leftJoinFromList.elementAt( TARGET_TABLE_INDEX ),
+ drivingColumnMap,
+ selectList,
+ ColumnReference.MERGE_TARGET
+ );
+
+ addTargetRowLocation( selectList );
+
+ return selectList;
+ }
+
+ /** Add the target table's row location to the left join's select list */
+ private void addTargetRowLocation( ResultColumnList selectList )
+ throws StandardException
+ {
+ // tell the target table to generate a row location column
+ _targetTable.setRowLocationColumnName( TARGET_ROW_LOCATION_NAME );
+
+ TableName fromTableName = _targetTable.getTableName();
+ ColumnReference cr = new ColumnReference
+ ( TARGET_ROW_LOCATION_NAME, fromTableName, getContextManager() );
+ cr.setMergeTableID( ColumnReference.MERGE_TARGET );
+ ResultColumn rowLocationColumn = new ResultColumn( (String) null, cr, getContextManager() );
+ rowLocationColumn.markGenerated();
+
+ selectList.addResultColumn( rowLocationColumn );
+ }
+
/**
* <p>
* Add to an evolving select list the columns from the indicated table.
@@ -702,42 +838,6 @@ public final class MergeNode extends DML
return retval;
}
- /** Add the columns in the matchingRefinement clause to the evolving map */
- void getColumnsInExpression
- ( HashMap<String,ColumnReference> map, ValueNode expression, int mergeTableID )
- throws StandardException
- {
- if ( expression == null ) { return; }
-
- List<ColumnReference> colRefs = getColumnReferences( expression );
-
- getColumnsFromList( map, colRefs, mergeTableID );
- }
-
- /** Get a list of CastNodes in an expression */
- private List<CastNode> getCastNodes( QueryTreeNode expression )
- throws StandardException
- {
- CollectNodesVisitor<CastNode> getCNs =
- new CollectNodesVisitor<CastNode>(CastNode.class);
-
- expression.accept(getCNs);
-
- return getCNs.getList();
- }
-
- /** Get a list of routines in an expression */
- private List<StaticMethodCallNode> getRoutineReferences( QueryTreeNode expression )
- throws StandardException
- {
- CollectNodesVisitor<StaticMethodCallNode> getSMCNs =
- new CollectNodesVisitor<StaticMethodCallNode>(StaticMethodCallNode.class);
-
- expression.accept(getSMCNs);
-
- return getSMCNs.getList();
- }
-
/** Get a list of column references in an expression */
private List<ColumnReference> getColumnReferences( QueryTreeNode expression )
throws StandardException
@@ -751,16 +851,6 @@ public final class MergeNode extends DML
}
/** Add a list of columns to the the evolving map */
- void getColumnsFromList
- ( HashMap<String,ColumnReference> map, ResultColumnList rcl, int mergeTableID )
- throws StandardException
- {
- List<ColumnReference> colRefs = getColumnReferences( rcl );
-
- getColumnsFromList( map, colRefs, mergeTableID );
- }
-
- /** Add a list of columns to the the evolving map */
private void getColumnsFromList
( HashMap<String,ColumnReference> map, List<ColumnReference> colRefs, int mergeTableID )
throws StandardException
@@ -803,65 +893,12 @@ public final class MergeNode extends DML
}
}
- /** Associate a column with the SOURCE or TARGET table */
- void associateColumn( FromList fromList, ColumnReference cr, int mergeTableID )
- throws StandardException
- {
- if ( mergeTableID != ColumnReference.MERGE_UNKNOWN ) { cr.setMergeTableID( mergeTableID ); }
- else
- {
- // we have to figure out which table the column is in
- String columnsTableName = cr.getTableName();
-
- if ( ((FromTable) fromList.elementAt( SOURCE_TABLE_INDEX )).getMatchingColumn( cr ) != null )
- {
- cr.setMergeTableID( ColumnReference.MERGE_SOURCE );
- }
- else if ( ((FromTable) fromList.elementAt( TARGET_TABLE_INDEX )).getMatchingColumn( cr ) != null )
- {
- cr.setMergeTableID( ColumnReference.MERGE_TARGET );
- }
- }
-
- // Don't raise an error if a column in another table is referenced and we
- // don't know how to handle it here. If the column is not in the SOURCE or TARGET
- // table, then it will be caught by other bind-time logic. Columns which ought
- // to be associated, but aren't, will be caught later on by MatchingClauseNode.getMergeTableID().
- }
-
/** Make a HashMap key for a column in the driving column map of the LEFT JOIN */
private String makeDCMKey( String tableName, String columnName )
{
return IdUtil.mkQualifiedName( tableName, columnName );
}
- /** Boilerplate for binding an expression against a FromList */
- void bindExpression( ValueNode value, FromList fromList )
- throws StandardException
- {
- CompilerContext cc = getCompilerContext();
- final int previousReliability = cc.getReliability();
-
- cc.setReliability( previousReliability | CompilerContext.SQL_IN_ROUTINES_ILLEGAL );
- cc.pushCurrentPrivType( Authorizer.SELECT_PRIV );
-
- try {
- // this adds SELECT priv on referenced columns and EXECUTE privs on referenced routines
- value.bindExpression
- (
- fromList,
- new SubqueryList( getContextManager() ),
- new ArrayList<AggregateNode>()
- );
- }
- finally
- {
- // Restore previous compiler state
- cc.popCurrentPrivType();
- cc.setReliability( previousReliability );
- }
- }
-
///////////////////////////////////////////////////////////////////////////////////
//
// optimize() BEHAVIOR
@@ -894,6 +931,7 @@ public final class MergeNode extends DML
// ready to add permissions again
getCompilerContext().removePrivilegeFilter( ignorePermissions );
}
+
///////////////////////////////////////////////////////////////////////////////////
//
// generate() BEHAVIOR
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/MatchingClauseConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/MatchingClauseConstantAction.java?rev=1579725&r1=1579724&r2=1579725&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/MatchingClauseConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/MatchingClauseConstantAction.java Thu Mar 20 19:50:05 2014
@@ -193,7 +193,7 @@ public class MatchingClauseConstantActio
///////////////////////////////////////////////////////////////////////////////////
//
- // OTHER PUBLIC BEHAVIOR
+ // OTHER PACKAGE VISIBLE BEHAVIOR, CALLED BY MergeResultSet
//
///////////////////////////////////////////////////////////////////////////////////
@@ -268,13 +268,36 @@ public class MatchingClauseConstantActio
/**
* <p>
+ * Release resources at the end.
+ * </p>
+ */
+ void cleanUp() throws StandardException
+ {
+ if ( _actionRS != null )
+ {
+ _actionRS.close();
+ _actionRS = null;
+ }
+
+ _matchRefinementMethod = null;
+ _rowMakingMethod = null;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ //
+ // MINIONS
+ //
+ ///////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * <p>
* Construct and buffer a row for the DELETE
* action corresponding to this MATCHED clause. The buffered row
* is built from columns in the passed-in row. The passed-in row is the SELECT list
* of the MERGE statement's driving left join.
* </p>
*/
- ExecRow bufferThenRowForDelete
+ private ExecRow bufferThenRowForDelete
(
Activation activation,
ExecRow selectRow
@@ -297,7 +320,7 @@ public class MatchingClauseConstantActio
* action corresponding to this [ NOT ] MATCHED clause.
* </p>
*/
- ExecRow bufferThenRow
+ private ExecRow bufferThenRow
(
Activation activation
)
@@ -313,23 +336,6 @@ public class MatchingClauseConstantActio
/**
* <p>
- * Release resources at the end.
- * </p>
- */
- void cleanUp() throws StandardException
- {
- if ( _actionRS != null )
- {
- _actionRS.close();
- _actionRS = null;
- }
-
- _matchRefinementMethod = null;
- _rowMakingMethod = null;
- }
-
- /**
- * <p>
* Create the temporary table for holding the rows which are buffered up
* for bulk-processing after the driving left join completes.
* </p>