private ExprNodeDesc constructFilterExpr(
      Map<List<ExprNodeDesc>, List<List<String>>> skewedValuesMap,
      boolean skewed) {

      ExprNodeDesc finalExprNodeDesc = null;
      try {
        for (Map.Entry<List<ExprNodeDesc>, List<List<String>>> mapEntry :
          skewedValuesMap.entrySet()) {
          List<ExprNodeDesc> keyCols = mapEntry.getKey();
          List<List<String>> skewedValuesList = mapEntry.getValue();

          for (List<String> skewedValues : skewedValuesList) {
            int keyPos = 0;
            ExprNodeDesc currExprNodeDesc = null;

            // Make the following condition: all the values match for all the columns
            for (String skewedValue : skewedValues) {
              List<ExprNodeDesc> children = new ArrayList<ExprNodeDesc>();

              // We have ensured that the keys are columns
              ExprNodeColumnDesc keyCol = (ExprNodeColumnDesc) keyCols.get(keyPos).clone();
              keyPos++;
              children.add(keyCol);

              // Convert the constants available as strings to the corresponding objects
              children.add(createConstDesc(skewedValue, keyCol));

              ExprNodeGenericFuncDesc expr = null;
              // Create the equality condition
              expr = ExprNodeGenericFuncDesc.newInstance(new GenericUDFOPEqual(), children);
              if (currExprNodeDesc == null) {
                currExprNodeDesc = expr;
              } else {
                // If there are previous nodes, then AND the current node with the previous one
                List<ExprNodeDesc> childrenAND = new ArrayList<ExprNodeDesc>();
                childrenAND.add(currExprNodeDesc);
                childrenAND.add(expr);
                currExprNodeDesc =
                  ExprNodeGenericFuncDesc.newInstance(new GenericUDFOPAnd(), childrenAND);
              }
            }

            // If there are more than one skewed values,
            // then OR the current node with the previous one
            if (finalExprNodeDesc == null) {
              finalExprNodeDesc = currExprNodeDesc;
            } else {
              List<ExprNodeDesc> childrenOR = new ArrayList<ExprNodeDesc>();
              childrenOR.add(finalExprNodeDesc);
              childrenOR.add(currExprNodeDesc);

              finalExprNodeDesc =
                ExprNodeGenericFuncDesc.newInstance(new GenericUDFOPOr(), childrenOR);
            }
          }
        }

        // Add a NOT operator in the beginning (this is for the cloned operator because we
        // want the values which are not skewed
        if (skewed == false) {
          List<ExprNodeDesc> childrenNOT = new ArrayList<ExprNodeDesc>();
          childrenNOT.add(finalExprNodeDesc);
          finalExprNodeDesc =
            ExprNodeGenericFuncDesc.newInstance(new GenericUDFOPNot(), childrenNOT);
        }
      } catch (UDFArgumentException e) {
        // Ignore the exception because we are not comparing Long vs. String here.
        // There should never be an exception
        assert false;
      }
      return finalExprNodeDesc;
    }
Construct the filter expression from the skewed keys and skewed values.
If the skewed join keys are (k1), and (k1,k3) with the skewed values
(1,2) and ((2,3),(4,5)) respectively, the filter expression would be:
(k1=1) or (k1=2) or ((k1=2) and (k3=3)) or ((k1=4) and (k3=5)).
ql/src/java/org/apache/hadoop/hive/ql/optimizer/SkewJoinOptimizer.java