Search in sources :

Example 86 with Pair

use of org.apache.calcite.util.Pair in project calcite by apache.

the class RexImplicationChecker method checkSupport.

/**
 * Looks at the usage of variables in first and second conjunction to decide
 * whether this kind of expression is currently supported for proving first
 * implies second.
 *
 * <ol>
 * <li>Variables should be used only once in both the conjunction against
 * given set of operations only: &gt;, &lt;, &le;, &ge;, =; &ne;.
 *
 * <li>All the variables used in second condition should be used even in the
 * first.
 *
 * <li>If operator used for variable in first is op1 and op2 for second, then
 * we support these combination for conjunction (op1, op2) then op1, op2
 * belongs to one of the following sets:
 *
 * <ul>
 *    <li>(&lt;, &le;) X (&lt;, &le;) <i>note: X represents cartesian product</i>
 *    <li>(&gt; / &ge;) X (&gt;, &ge;)
 *    <li>(=) X (&gt;, &ge;, &lt;, &le;, =, &ne;)
 *    <li>(&ne;, =)
 * </ul>
 *
 * <li>We support at most 2 operators to be be used for a variable in first
 * and second usages.
 *
 * </ol>
 *
 * @return whether input usage pattern is supported
 */
private boolean checkSupport(InputUsageFinder firstUsageFinder, InputUsageFinder secondUsageFinder) {
    final Map<RexInputRef, InputRefUsage<SqlOperator, RexNode>> firstUsageMap = firstUsageFinder.usageMap;
    final Map<RexInputRef, InputRefUsage<SqlOperator, RexNode>> secondUsageMap = secondUsageFinder.usageMap;
    for (Map.Entry<RexInputRef, InputRefUsage<SqlOperator, RexNode>> entry : secondUsageMap.entrySet()) {
        final InputRefUsage<SqlOperator, RexNode> secondUsage = entry.getValue();
        final List<Pair<SqlOperator, RexNode>> secondUsageList = secondUsage.usageList;
        final int secondLen = secondUsageList.size();
        if (secondUsage.usageCount != secondLen || secondLen > 2) {
            return false;
        }
        final InputRefUsage<SqlOperator, RexNode> firstUsage = firstUsageMap.get(entry.getKey());
        if (firstUsage == null || firstUsage.usageList.size() != firstUsage.usageCount || firstUsage.usageCount > 2) {
            return false;
        }
        final List<Pair<SqlOperator, RexNode>> firstUsageList = firstUsage.usageList;
        final int firstLen = firstUsageList.size();
        final SqlKind fKind = firstUsageList.get(0).getKey().getKind();
        final SqlKind sKind = secondUsageList.get(0).getKey().getKind();
        final SqlKind fKind2 = (firstUsageList.size() == 2) ? firstUsageList.get(1).getKey().getKind() : null;
        final SqlKind sKind2 = (secondUsageList.size() == 2) ? secondUsageList.get(1).getKey().getKind() : null;
        if (firstLen == 2 && secondLen == 2 && !(isEquivalentOp(fKind, sKind) && isEquivalentOp(fKind2, sKind2)) && !(isEquivalentOp(fKind, sKind2) && isEquivalentOp(fKind2, sKind))) {
            return false;
        } else if (firstLen == 1 && secondLen == 1 && fKind != SqlKind.EQUALS && !isSupportedUnaryOperators(sKind) && !isEquivalentOp(fKind, sKind)) {
            return false;
        } else if (firstLen == 1 && secondLen == 2 && fKind != SqlKind.EQUALS) {
            return false;
        } else if (firstLen == 2 && secondLen == 1) {
            // x > 30 and x > 40 implies x < 70
            if (!isOppositeOp(fKind, fKind2) && !isSupportedUnaryOperators(sKind) && !(isEquivalentOp(fKind, fKind2) && isEquivalentOp(fKind, sKind))) {
                return false;
            }
        }
    }
    return true;
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) RexInputRef(org.apache.calcite.rex.RexInputRef) SqlKind(org.apache.calcite.sql.SqlKind) HashMap(java.util.HashMap) Map(java.util.Map) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 87 with Pair

use of org.apache.calcite.util.Pair in project calcite by apache.

the class JdbcTest method testCloneQueries.

/**
 * A selection of queries generated by Mondrian.
 */
@Ignore
@Test
public void testCloneQueries() {
    CalciteAssert.AssertThat with = CalciteAssert.that().with(CalciteAssert.Config.FOODMART_CLONE);
    for (Ord<Pair<String, String>> query : Ord.zip(FOODMART_QUERIES)) {
        try {
            // uncomment to run specific queries:
            // if (query.i != FOODMART_QUERIES.size() - 1) continue;
            final String sql = query.e.left;
            if (sql.startsWith("ignore:")) {
                continue;
            }
            final String expected = query.e.right;
            final CalciteAssert.AssertQuery query1 = with.query(sql);
            if (expected != null) {
                if (sql.contains("order by")) {
                    query1.returns(expected);
                } else {
                    query1.returnsUnordered(expected.split("\n"));
                }
            } else {
                query1.runs();
            }
        } catch (Throwable e) {
            throw new RuntimeException("while running query #" + query.i, e);
        }
    }
}
Also used : CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Pair(org.apache.calcite.util.Pair) Ignore(org.junit.Ignore) Test(org.junit.Test)

Example 88 with Pair

use of org.apache.calcite.util.Pair in project calcite by apache.

the class SqlTesterImpl method buildQuery2.

/**
 * Builds a query that extracts all literals as columns in an underlying
 * select.
 *
 * <p>For example,</p>
 *
 * <blockquote>{@code 1 < 5}</blockquote>
 *
 * <p>becomes</p>
 *
 * <blockquote>{@code SELECT p0 < p1
 * FROM (VALUES (1, 5)) AS t(p0, p1)}</blockquote>
 *
 * <p>Null literals don't have enough type information to be extracted.
 * We push down {@code CAST(NULL AS type)} but raw nulls such as
 * {@code CASE 1 WHEN 2 THEN 'a' ELSE NULL END} are left as is.</p>
 *
 * @param expression Scalar expression
 * @return Query that evaluates a scalar expression
 */
private String buildQuery2(String expression) {
    // "values (1 < 5)"
    // becomes
    // "select p0 < p1 from (values (1, 5)) as t(p0, p1)"
    SqlNode x;
    final String sql = "values (" + expression + ")";
    try {
        x = parseQuery(sql);
    } catch (SqlParseException e) {
        throw new RuntimeException(e);
    }
    final Collection<SqlNode> literalSet = new LinkedHashSet<>();
    x.accept(new SqlShuttle() {

        private final List<SqlOperator> ops = ImmutableList.of(SqlStdOperatorTable.LITERAL_CHAIN, SqlStdOperatorTable.LOCALTIME, SqlStdOperatorTable.LOCALTIMESTAMP, SqlStdOperatorTable.CURRENT_TIME, SqlStdOperatorTable.CURRENT_TIMESTAMP);

        @Override
        public SqlNode visit(SqlLiteral literal) {
            if (!isNull(literal) && literal.getTypeName() != SqlTypeName.SYMBOL) {
                literalSet.add(literal);
            }
            return literal;
        }

        @Override
        public SqlNode visit(SqlCall call) {
            final SqlOperator operator = call.getOperator();
            if (operator == SqlStdOperatorTable.CAST && isNull(call.operand(0))) {
                literalSet.add(call);
                return call;
            } else if (ops.contains(operator)) {
                // literal"
                return call;
            } else {
                return super.visit(call);
            }
        }

        private boolean isNull(SqlNode sqlNode) {
            return sqlNode instanceof SqlLiteral && ((SqlLiteral) sqlNode).getTypeName() == SqlTypeName.NULL;
        }
    });
    final List<SqlNode> nodes = new ArrayList<>(literalSet);
    Collections.sort(nodes, new Comparator<SqlNode>() {

        public int compare(SqlNode o1, SqlNode o2) {
            final SqlParserPos pos0 = o1.getParserPosition();
            final SqlParserPos pos1 = o2.getParserPosition();
            int c = -Utilities.compare(pos0.getLineNum(), pos1.getLineNum());
            if (c != 0) {
                return c;
            }
            return -Utilities.compare(pos0.getColumnNum(), pos1.getColumnNum());
        }
    });
    String sql2 = sql;
    final List<Pair<String, String>> values = new ArrayList<>();
    int p = 0;
    for (SqlNode literal : nodes) {
        final SqlParserPos pos = literal.getParserPosition();
        final int start = SqlParserUtil.lineColToIndex(sql, pos.getLineNum(), pos.getColumnNum());
        final int end = SqlParserUtil.lineColToIndex(sql, pos.getEndLineNum(), pos.getEndColumnNum()) + 1;
        String param = "p" + (p++);
        values.add(Pair.of(sql2.substring(start, end), param));
        sql2 = sql2.substring(0, start) + param + sql2.substring(end);
    }
    if (values.isEmpty()) {
        values.add(Pair.of("1", "p0"));
    }
    return "select " + sql2.substring("values (".length(), sql2.length() - 1) + " from (values (" + Util.commaList(Pair.left(values)) + ")) as t(" + Util.commaList(Pair.right(values)) + ")";
}
Also used : LinkedHashSet(java.util.LinkedHashSet) SqlShuttle(org.apache.calcite.sql.util.SqlShuttle) SqlParseException(org.apache.calcite.sql.parser.SqlParseException) SqlParserPos(org.apache.calcite.sql.parser.SqlParserPos) SqlOperator(org.apache.calcite.sql.SqlOperator) SqlCall(org.apache.calcite.sql.SqlCall) ArrayList(java.util.ArrayList) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode) Pair(org.apache.calcite.util.Pair)

Example 89 with Pair

use of org.apache.calcite.util.Pair in project calcite by apache.

the class DiffRepository method update.

/**
 * Creates a new document with a given resource.
 *
 * <p>This method is synchronized, in case two threads are running test
 * cases of this test at the same time.
 *
 * @param testCaseName Test case name
 * @param resourceName Resource name
 * @param value        New value of resource
 */
private synchronized void update(String testCaseName, String resourceName, String value) {
    final List<Pair<String, Element>> map = new ArrayList<>();
    Element testCaseElement = getTestCaseElement(testCaseName, true, map);
    if (testCaseElement == null) {
        testCaseElement = doc.createElement(TEST_CASE_TAG);
        testCaseElement.setAttribute(TEST_CASE_NAME_ATTR, testCaseName);
        Node refElement = ref(testCaseName, map);
        root.insertBefore(testCaseElement, refElement);
    }
    Element resourceElement = getResourceElement(testCaseElement, resourceName, true);
    if (resourceElement == null) {
        resourceElement = doc.createElement(RESOURCE_TAG);
        resourceElement.setAttribute(RESOURCE_NAME_ATTR, resourceName);
        testCaseElement.appendChild(resourceElement);
    } else {
        removeAllChildren(resourceElement);
    }
    if (!value.equals("")) {
        resourceElement.appendChild(doc.createCDATASection(value));
    }
    // Write out the document.
    flushDoc();
}
Also used : Element(org.w3c.dom.Element) Node(org.w3c.dom.Node) ArrayList(java.util.ArrayList) Pair(org.apache.calcite.util.Pair)

Example 90 with Pair

use of org.apache.calcite.util.Pair in project calcite by apache.

the class AggregateExpandDistinctAggregatesRule method createSelectDistinct.

/**
 * Given an {@link org.apache.calcite.rel.core.Aggregate}
 * and the ordinals of the arguments to a
 * particular call to an aggregate function, creates a 'select distinct'
 * relational expression which projects the group columns and those
 * arguments but nothing else.
 *
 * <p>For example, given
 *
 * <blockquote>
 * <pre>select f0, count(distinct f1), count(distinct f2)
 * from t group by f0</pre>
 * </blockquote>
 *
 * <p>and the argument list
 *
 * <blockquote>{2}</blockquote>
 *
 * <p>returns
 *
 * <blockquote>
 * <pre>select distinct f0, f2 from t</pre>
 * </blockquote>
 *
 * <p>The <code>sourceOf</code> map is populated with the source of each
 * column; in this case sourceOf.get(0) = 0, and sourceOf.get(1) = 2.
 *
 * @param relBuilder Relational expression builder
 * @param aggregate Aggregate relational expression
 * @param argList   Ordinals of columns to make distinct
 * @param filterArg Ordinal of column to filter on, or -1
 * @param sourceOf  Out parameter, is populated with a map of where each
 *                  output field came from
 * @return Aggregate relational expression which projects the required
 * columns
 */
private RelBuilder createSelectDistinct(RelBuilder relBuilder, Aggregate aggregate, List<Integer> argList, int filterArg, Map<Integer, Integer> sourceOf) {
    relBuilder.push(aggregate.getInput());
    final List<Pair<RexNode, String>> projects = new ArrayList<>();
    final List<RelDataTypeField> childFields = relBuilder.peek().getRowType().getFieldList();
    for (int i : aggregate.getGroupSet()) {
        sourceOf.put(i, projects.size());
        projects.add(RexInputRef.of2(i, childFields));
    }
    for (Integer arg : argList) {
        if (filterArg >= 0) {
            // Implement
            // agg(DISTINCT arg) FILTER $f
            // by generating
            // SELECT DISTINCT ... CASE WHEN $f THEN arg ELSE NULL END AS arg
            // and then applying
            // agg(arg)
            // as usual.
            // 
            // It works except for (rare) agg functions that need to see null
            // values.
            final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
            final RexInputRef filterRef = RexInputRef.of(filterArg, childFields);
            final Pair<RexNode, String> argRef = RexInputRef.of2(arg, childFields);
            RexNode condition = rexBuilder.makeCall(SqlStdOperatorTable.CASE, filterRef, argRef.left, rexBuilder.ensureType(argRef.left.getType(), rexBuilder.makeCast(argRef.left.getType(), rexBuilder.constantNull()), true));
            sourceOf.put(arg, projects.size());
            projects.add(Pair.of(condition, "i$" + argRef.right));
            continue;
        }
        if (sourceOf.get(arg) != null) {
            continue;
        }
        sourceOf.put(arg, projects.size());
        projects.add(RexInputRef.of2(arg, childFields));
    }
    relBuilder.project(Pair.left(projects), Pair.right(projects));
    // Get the distinct values of the GROUP BY fields and the arguments
    // to the agg functions.
    relBuilder.push(aggregate.copy(aggregate.getTraitSet(), relBuilder.build(), false, ImmutableBitSet.range(projects.size()), null, ImmutableList.<AggregateCall>of()));
    return relBuilder;
}
Also used : ArrayList(java.util.ArrayList) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RexBuilder(org.apache.calcite.rex.RexBuilder) RexInputRef(org.apache.calcite.rex.RexInputRef) Pair(org.apache.calcite.util.Pair) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

Pair (org.apache.calcite.util.Pair)112 RexNode (org.apache.calcite.rex.RexNode)72 ArrayList (java.util.ArrayList)70 RelNode (org.apache.calcite.rel.RelNode)59 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)55 RexInputRef (org.apache.calcite.rex.RexInputRef)29 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)29 HashMap (java.util.HashMap)26 RexBuilder (org.apache.calcite.rex.RexBuilder)23 Map (java.util.Map)21 AggregateCall (org.apache.calcite.rel.core.AggregateCall)20 List (java.util.List)19 RelDataType (org.apache.calcite.rel.type.RelDataType)19 ImmutableList (com.google.common.collect.ImmutableList)18 JoinRelType (org.apache.calcite.rel.core.JoinRelType)16 TreeMap (java.util.TreeMap)14 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)13 RelBuilder (org.apache.calcite.tools.RelBuilder)13 ImmutableMap (com.google.common.collect.ImmutableMap)12 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)12