예제 #1
0
  /**
   * Check whether a join is valid. Invalid joins are CROSS JOIN, FULL OUTER JOIN, any join without
   * criteria, any join with no equality criteria, and any outer join that has the outer side not
   * the same as the dependent.
   *
   * @param joinNode The join node to check
   * @param sourceNode The access node being considered
   * @param analysisRecord TODO
   * @return True if valid for making dependent
   * @throws TeiidComponentException
   * @throws QueryMetadataException
   */
  boolean isValidJoin(PlanNode joinNode, PlanNode sourceNode, AnalysisRecord analysisRecord)
      throws QueryMetadataException, TeiidComponentException {
    JoinType jtype = (JoinType) joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);

    // Check that join is not a CROSS join or FULL OUTER join
    if (jtype.equals(JoinType.JOIN_CROSS) || jtype.equals(JoinType.JOIN_FULL_OUTER)) {
      sourceNode.recordDebugAnnotation(
          "parent join is CROSS or FULL OUTER",
          null,
          "Rejecting dependent join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return false;
    }

    if (!joinNode.getExportedCorrelatedReferences().isEmpty()) {
      sourceNode.recordDebugAnnotation(
          "parent join has a correlated nested table",
          null,
          "Rejecting dependent join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return false;
    }

    // Check that join criteria exist
    List jcrit = (List) joinNode.getProperty(NodeConstants.Info.JOIN_CRITERIA);
    if (jcrit == null || jcrit.size() == 0) {
      sourceNode.recordDebugAnnotation(
          "parent join has has no join criteria",
          null,
          "Rejecting dependent join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return false;
    }

    if (joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS) == null) {
      sourceNode.recordDebugAnnotation(
          "parent join has no equa-join predicates",
          null,
          "Rejecting dependent join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return false;
    }

    // Check that for a left or right outer join the dependent side must be the inner
    if (jtype.isOuter() && JoinUtil.getInnerSideJoinNodes(joinNode)[0] != sourceNode) {
      sourceNode.recordDebugAnnotation(
          "node is on outer side of the join",
          null,
          "Rejecting dependent join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return false;
    }

    return true;
  }
예제 #2
0
  PlanNode chooseDepWithoutCosting(
      PlanNode rootNode1, PlanNode rootNode2, AnalysisRecord analysisRecord)
      throws QueryMetadataException, TeiidComponentException {
    PlanNode sourceNode1 = FrameUtil.findJoinSourceNode(rootNode1);
    PlanNode sourceNode2 = null;

    if (rootNode2 != null) {
      sourceNode2 = FrameUtil.findJoinSourceNode(rootNode2);
    }
    if (sourceNode1.hasCollectionProperty(NodeConstants.Info.ACCESS_PATTERNS)) {
      if (sourceNode2 != null
          && sourceNode2.hasCollectionProperty(NodeConstants.Info.ACCESS_PATTERNS)) {
        // Return null - query planning should fail because both access nodes
        // have unsatisfied access patterns
        rootNode1
            .getParent()
            .recordDebugAnnotation(
                "both children have unsatisfied access patterns",
                null,
                "Neither node can be made dependent",
                analysisRecord,
                null); //$NON-NLS-1$ //$NON-NLS-2$
        return null;
      }
      rootNode1.recordDebugAnnotation(
          "unsatisfied access pattern detected",
          null,
          "marking as dependent side of join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return rootNode1;
    } else if (sourceNode2 != null
        && sourceNode2.hasCollectionProperty(NodeConstants.Info.ACCESS_PATTERNS)) {
      // Access node 2 has unsatisfied access pattern,
      // so try to make node 2 dependent
      sourceNode2.recordDebugAnnotation(
          "unsatisfied access pattern detected",
          null,
          "marking as dependent side of join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return rootNode2;
    }

    // Check for hints, which over-rule heuristics
    if (sourceNode1.hasProperty(NodeConstants.Info.MAKE_DEP)) {
      sourceNode1.recordDebugAnnotation(
          "MAKE_DEP hint detected",
          null,
          "marking as dependent side of join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      rootNode1.setProperty(Info.MAKE_DEP, sourceNode1.getProperty(Info.MAKE_DEP));
      return rootNode1;
    } else if (sourceNode2 != null && sourceNode2.hasProperty(NodeConstants.Info.MAKE_DEP)) {
      sourceNode2.recordDebugAnnotation(
          "MAKE_DEP hint detected",
          null,
          "marking as dependent side of join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      rootNode2.setProperty(Info.MAKE_DEP, sourceNode2.getProperty(Info.MAKE_DEP));
      return rootNode2;
    } else if (sourceNode1.hasBooleanProperty(NodeConstants.Info.MAKE_IND) && sourceNode2 != null) {
      sourceNode2.recordDebugAnnotation(
          "MAKE_IND hint detected",
          null,
          "marking as dependent side of join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return rootNode2;
    } else if (sourceNode2 != null && sourceNode2.hasBooleanProperty(NodeConstants.Info.MAKE_IND)) {
      sourceNode1.recordDebugAnnotation(
          "MAKE_IND hint detected",
          null,
          "marking as dependent side of join",
          analysisRecord,
          null); //$NON-NLS-1$ //$NON-NLS-2$
      return rootNode1;
    }

    return null;
  }