⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joinnode.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
					SanityManager.THROWASSERT(						"allTableName (" + allTableName + 						") expected to be null");				}			}			// Return a spliced copy of the 2 lists			ResultColumnList tempList =								(ResultColumnList) getNodeFactory().getNode(												C_NodeTypes.RESULT_COLUMN_LIST,												getContextManager());			tempList.nondestructiveAppend(leftRCL);			tempList.nondestructiveAppend(rightRCL);			return tempList;		}	}	/**	 * Try to find a ResultColumn in the table represented by this FromTable	 * that matches the name in the given ColumnReference.	 *	 * @param columnReference	The columnReference whose name we're looking	 *				for in the given table.	 *	 * @return	A ResultColumn whose expression is the ColumnNode	 *			that matches the ColumnReference.	 *		Returns null if there is no match.	 *	 * @exception StandardException		Thrown on error	 */	public ResultColumn getMatchingColumn(ColumnReference columnReference) throws StandardException	{		/* Get the logical left and right sides of the join.		 * (For RIGHT OUTER JOIN, the left is the right		 * and the right is the left and the JOIN is the NIOJ).		 */		ResultSetNode	logicalLeftRS = getLogicalLeftResultSet();		ResultSetNode	logicalRightRS = getLogicalRightResultSet();		ResultColumn	leftRC = null;		ResultColumn	resultColumn = null;		ResultColumn	rightRC = null;		ResultColumn	usingRC = null;		leftRC = logicalLeftRS.getMatchingColumn(columnReference);		if (leftRC != null)		{			resultColumn = leftRC;			/* Find out if the column is in the using clause */			if (usingClause != null)			{				usingRC = usingClause.getResultColumn(leftRC.getName());			}		}		/* We only search on the right if the column isn't in the		 * USING clause.		 */		if (usingRC == null)		{			rightRC = logicalRightRS.getMatchingColumn(columnReference);		}		if (rightRC != null)		{			/* We must catch ambiguous column references for joins here,			 * since FromList only checks for ambiguous references between			 * nodes, not within a node.			 */			if (leftRC != null)			{				throw StandardException.newException(SQLState.LANG_AMBIGUOUS_COLUMN_NAME, 						 columnReference.getSQLColumnName());			}			resultColumn = rightRC;		}		/* Insert will bind the underlying result sets which have		 * tables twice. On the 2nd bind, resultColumns != null,		 * we must return the RC from the JoinNode's RCL which is above		 * the RC that we just found above.  (Otherwise, the source		 * for the ColumnReference will be from the wrong ResultSet		 * at generate().)		 */		if (resultColumns != null)		{			int rclSize = resultColumns.size();			for (int index = 0; index < rclSize; index++)			{				ResultColumn rc = (ResultColumn) resultColumns.elementAt(index);				VirtualColumnNode vcn = (VirtualColumnNode) rc.getExpression();				if (resultColumn == vcn.getSourceColumn())				{					resultColumn = rc;					break;				}			}		}		return resultColumn;	}	/**	 * Bind the result columns of this ResultSetNode when there is no	 * base table to bind them to.  This is useful for SELECT statements,	 * where the result columns get their types from the expressions that	 * live under them.	 *	 * @param fromListParam		FromList to use/append to.	 *	 * @return	Nothing	 *	 * @exception StandardException		Thrown on error	 */	public void bindResultColumns(FromList fromListParam)					throws StandardException	{		super.bindResultColumns(fromListParam);		/* Now we build our RCL */		buildRCL();		/* We cannot bind the join clause until after we've bound our		 * result columns. This is because the resultColumns from the		 * children are propagated and merged to create our resultColumns		 * in super.bindRCs().  If we bind the join clause prior to that		 * call, then the ColumnReferences in the join clause will point		 * to the children's RCLs at the time that they are bound, but		 * will end up pointing above themselves, to our resultColumns,		 * after the call to super.bindRCS().		 */		deferredBindExpressions(fromListParam);	}	/**	 * Bind the result columns for this ResultSetNode to a base table.	 * This is useful for INSERT and UPDATE statements, where the	 * result columns get their types from the table being updated or	 * inserted into.	 * If a result column list is specified, then the verification that the 	 * result column list does not contain any duplicates will be done when	 * binding them by name.	 *	 * @param targetTableDescriptor	The TableDescriptor for the table being	 *				updated or inserted into	 * @param targetColumnList	For INSERT statements, the user	 *					does not have to supply column	 *					names (for example, "insert into t	 *					values (1,2,3)".  When this	 *					parameter is null, it means that	 *					the user did not supply column	 *					names, and so the binding should	 *					be done based on order.  When it	 *					is not null, it means do the binding	 *					by name, not position.	 * @param statement			Calling DMLStatementNode (Insert or Update)	 * @param fromListParam		FromList to use/append to.	 *	 * @return	Nothing	 *	 * @exception StandardException		Thrown on error	 */	public void bindResultColumns(TableDescriptor targetTableDescriptor,					FromVTI targetVTI,					ResultColumnList targetColumnList,					DMLStatementNode statement,					FromList fromListParam)				throws StandardException	{		super.bindResultColumns(targetTableDescriptor,								targetVTI,								targetColumnList, statement, 								fromListParam);		/* Now we build our RCL */		buildRCL();		/* We cannot bind the join clause until after we've bound our		 * result columns. This is because the resultColumns from the		 * children are propagated and merged to create our resultColumns		 * in super.bindRCs().  If we bind the join clause prior to that		 * call, then the ColumnReferences in the join clause will point		 * to the children's RCLs at the time that they are bound, but		 * will end up pointing above themselves, to our resultColumns,		 * after the call to super.bindRCS().		 */		deferredBindExpressions(fromListParam);	}	/**	 * Build the RCL for this node.  We propagate the RCLs up from the	 * children and splice them to form this node's RCL.	 *	 * @return	Nothing	 *	 * @exception StandardException		Thrown on error	 */	private void buildRCL() throws StandardException	{		/* NOTE - we only need to build this list if it does not already 		 * exist.  This can happen in the degenerate case of an insert		 * select with a join expression in a derived table within the select.		 */		if (resultColumns != null)		{			return;		}		ResultColumnList leftRCL;		ResultColumnList rightRCL;		ResultColumnList tmpRCL;		/* We get a shallow copy of the left's ResultColumnList and its 		 * ResultColumns.  (Copy maintains ResultColumn.expression for now.)		 */		resultColumns = leftResultSet.getResultColumns();		leftRCL = resultColumns.copyListAndObjects();		leftResultSet.setResultColumns(leftRCL);		/* Replace ResultColumn.expression with new VirtualColumnNodes		 * in the ProjectRestrictNode's ResultColumnList.  (VirtualColumnNodes include		 * pointers to source ResultSetNode, this, and source ResultColumn.)		 */		resultColumns.genVirtualColumnNodes(leftResultSet, leftRCL, false);		/*		** If this is a right outer join, we can get nulls on the left side,		** so change the types of the left result set to be nullable.		*/		if (this instanceof HalfOuterJoinNode && ((HalfOuterJoinNode)this).isRightOuterJoin())		{			resultColumns.setNullability(true);		}		/* Now, repeat the process with the right's RCL */		tmpRCL = rightResultSet.getResultColumns();		rightRCL = tmpRCL.copyListAndObjects();		rightResultSet.setResultColumns(rightRCL);		/* Replace ResultColumn.expression with new VirtualColumnNodes		 * in the ProjectRestrictNode's ResultColumnList.  (VirtualColumnNodes include		 * pointers to source ResultSetNode, this, and source ResultColumn.)		 */		tmpRCL.genVirtualColumnNodes(rightResultSet, rightRCL, false);		tmpRCL.adjustVirtualColumnIds(resultColumns.size());		/*		** If this is a left outer join, we can get nulls on the right side,		** so change the types of the right result set to be nullable.		*/		if (this instanceof HalfOuterJoinNode && !((HalfOuterJoinNode)this).isRightOuterJoin())		{			tmpRCL.setNullability(true);		}				/* Now we append the propagated RCL from the right to the one from		 * the left and call it our own.		 */		resultColumns.nondestructiveAppend(tmpRCL);	}	private void deferredBindExpressions(FromList fromListParam)				throws StandardException	{		/* Bind the expressions in the join clause */		subqueryList = (SubqueryList) getNodeFactory().getNode(											C_NodeTypes.SUBQUERY_LIST,											getContextManager());		aggregateVector = new Vector();		/* ON clause */		if (joinClause != null)		{			/* Create a new fromList with only left and right children before			 * binding the join clause. Valid column references in the join clause			 * are limited to columns from the 2 tables being joined. This			 * algorithm enforces that.			 */			FromList	fromList = (FromList) getNodeFactory().getNode(									C_NodeTypes.FROM_LIST,									getNodeFactory().doJoinOrderOptimization(),									getContextManager());			fromList.addElement((FromTable) leftResultSet);			fromList.addElement((FromTable) rightResultSet);			/* First bind with all tables in the from clause, to detect ambiguous			 * references. Push the left and right children to the front of the			 * fromListParam before binding the join clause.  (We will			 * remove it before returning.)  Valid column references in			 * the join clause are limited to columns from the 2 tables being			 * joined			 */			fromListParam.insertElementAt(rightResultSet, 0);			fromListParam.insertElementAt(leftResultSet, 0);			joinClause = joinClause.bindExpression(									  fromListParam, subqueryList,									  aggregateVector);			/* Now bind with two tables being joined. If this raises column not found exception,			 * then we have a reference to other tables in the from clause. Raise invalid			 * ON clause error to match DB2.			 */			try {				joinClause = joinClause.bindExpression(									  fromList, subqueryList,									  aggregateVector);			} catch (StandardException se) {				if (se.getSQLState().equals(SQLState.LANG_COLUMN_NOT_FOUND))					throw StandardException.newException(SQLState.LANG_DB2_ON_CLAUSE_INVALID); 				throw se;			}			/* DB2 doesn't allow subquerries in the ON clause */			if (subqueryList.size() > 0)				throw StandardException.newException(SQLState.LANG_DB2_ON_CLAUSE_INVALID); 			/*			** We cannot have aggregates in the ON clause.			** In the future, if we relax this, we'll need			** to be able to pass the aggregateVector up			** the tree.			*/			if (aggregateVector.size() > 0)			{				throw StandardException.newException(SQLState.LANG_NO_AGGREGATES_IN_ON_CLAUSE);			}			fromListParam.removeElementAt(0);			fromListParam.removeElementAt(0);		}		/* USING clause */		else if (usingClause != null)		{			/* Build a join clause from the usingClause, using the			 * exposed names in the left and right RSNs.			 * For each column in the list, we generate 2 ColumnReferences,			 * 1 for the left and 1 for the right.  We bind each of these			 * to the appropriate side and build an equality predicate			 * between the 2.  We bind the = and AND nodes by hand because			 * we have to bind the ColumnReferences a side at a time.			 * We need to bind the CRs a side at a time to ensure that			 * we don't find an bogus ambiguous column reference. (Bug 377)			 */			joinClause = (AndNode) getNodeFactory().getNode(												C_NodeTypes.AND_NODE,												null,												null,												getContextManager());			AndNode	currAnd = (AndNode) joinClause;			ValueNode trueNode = (ValueNode) getNodeFactory().getNode(											C_NodeTypes.BOOLEAN_CONSTANT_NODE,											Boolean.TRUE,											getContextManager());			int usingSize = usingClause.size();			for (int index = 0; index < usingSize; index++)			{				BinaryComparisonOperatorNode equalsNode;				ColumnReference leftCR;				ColumnReference rightCR;				ResultColumn	rc = (ResultColumn) usingClause.elementAt(index);				/* currAnd starts as first point of insertion (leftOperand == null)				 * and becomes last point of insertion.				 */				if (currAnd.getLeftOperand() != null)				{					currAnd.setRightOperand(						(AndNode) getNodeFactory().getNode(												C_NodeTypes.AND_NODE,												null,												null,												getContextManager()));					currAnd = (AndNode) currAnd.getRightOperand();				}				/* Create and bind the left CR */				fromListParam.insertElementAt(leftResultSet, 0);				leftCR = (ColumnReference) getNodeFactory().getNode(							C_NodeTypes.COLUMN_REFERENCE,							rc.getName(),							((FromTable) leftResultSet).getTableName(),							getContextManager()); 				leftCR = (ColumnReference) leftCR.bindExpression(									  fromListParam, subqueryList,									  aggregateVector);				fromListParam.removeElementAt(0);				/* Create and bind the right CR */				fromListParam.insertElementAt(rightResultSet, 0);				rightCR = (ColumnReference) getNodeFactory().getNode(							C_NodeTypes.COLUMN_REFERENCE,							rc.getName(),							((FromTable) rightResultSet).getTableName(),							getContextManager()); 				rightCR = (ColumnReference) rightCR.bindExpression(									  fromListParam, subqueryList,									  aggregateVector);				fromListParam.removeElementAt(0);				/* Create and insert the new = condition */				equalsNode = (BinaryComparisonOperatorNode)								getNodeFactory().getNode(										C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,										leftCR,										rightCR,										getContextManager());				equalsNode.bindComparisonOperator();				currAnd.setLeftOperand(equalsNode);				/* The right deep chain of AndNodes ends in a BinaryTrueNode.				 * NOTE: We set it for every AndNode, even though we will				 * overwrite it if this is not the last column in the list,				 * because postBindFixup() expects both the AndNode to have				 * both the left and right operands.				 */				currAnd.setRightOperand(trueNode);				currAnd.postBindFixup();			 }		}		if (joinClause != null)		{			/* If joinClause is a parameter, (where ?), then we assume			 * it will be a nullable boolean.			 */			if (joinClause.isParameterNode())			{				joinClause.setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, true));			}						/*			** Is the datatype of the JOIN clause BOOLEAN?			**			** NOTE: This test is not necessary in SQL92 entry level, because			** it is syntactically impossible to have a non-Boolean JOIN clause			** in that level of the standard.  But we intend to extend the			** language to allow Boolean user functions in the JOIN clause,			** so we need to test for the error condition.			*/			TypeId joinTypeId = joinClause.getTypeId();			/* If the where clause is not a built-in type, then generate a bound 			 * conversion tree to a built-in type.			 */			if (! joinTypeId.systemBuiltIn())			{				joinClause = joinClause.genSQLJavaSQLTree();			}			if (! joinClause.getTypeServices().getTypeId().equals(					TypeId.BOOLEAN_ID))			{				throw StandardException.newException(SQLState.LANG_NON_BOOLEAN_JOIN_CLAUSE, 						joinClause.getTypeServices().getTypeId().getSQLTypeName()						);			}		}	}	/** 	 * Put a ProjectRestrictNode on top of each FromTable in the FromList.	 * ColumnReferences must continue to point to the same ResultColumn, so	 * that ResultColumn must percolate up to the new PRN.  However,	 * that ResultColumn will point to a new expression, a VirtualColumnNode, 	 * which points to the FromTable and the ResultColumn that is the source for	 * the ColumnReference.  	 * (The new PRN will have the original of the ResultColumnList and	 * the ResultColumns from that list.  The FromTable will get shallow copies	 * of the ResultColumnList and its ResultColumns.  ResultColumn.expression	 * will remain at the FromTable, with the PRN getting a new 	 * VirtualColumnNode for each ResultColumn.expression.)	 * We then project out the non-referenced columns.  If there are no referenced	 * columns, then the PRN's ResultColumnList will consist of a single ResultColumn	 * whose expression is 1.	 *	 * @param numTables			Number of tables in the DML Statement	 * @param gbl				The group by list, if any	 * @param fromList			The from list, if any	 *	 * @return The generated ProjectRestrictNode atop the original FromTable.	 *	 * @exception StandardException		Thrown on error	 */	public ResultSetNode preprocess(int numTables,									GroupByList gbl,									FromList fromList)								throws StandardException

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -