lowka commented on code in PR #4221:
URL: https://github.com/apache/ignite-3/pull/4221#discussion_r1721260022


##########
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerHelper.java:
##########
@@ -343,4 +360,171 @@ static boolean hasSubQuery(SqlNode node) {
             return super.visit(call);
         }
     }
+
+
+    /**
+     * Tries to optimize a query that looks like {@code SELECT count(*)}.
+     *
+     * @param planner Planner.
+     * @param txContext Transactional context.
+     * @param node Query node.
+     * @return Plan node with list of aliases, if the optimization is 
applicable.
+     */
+    public static @Nullable Pair<IgniteRel, List<String>> 
tryOptimizeSelectCount(
+            IgnitePlanner planner,
+            @Nullable QueryTransactionContext txContext,
+            SqlNode node
+    ) {
+        if (txContext != null && txContext.explicitTx() != null) {
+            return null;
+        }
+
+        if (!(node instanceof SqlSelect)) {
+            return null;
+        }
+
+        SqlSelect select = (SqlSelect) node;
+
+        if (select.getGroup() != null
+                || select.getWhere() != null
+                || select.getHaving() != null
+                || select.getQualify() != null
+                || !select.getWindowList().isEmpty()
+                || select.getOffset() != null
+                || select.getFetch() != null) {
+            return null;
+        }
+
+        IgniteSqlToRelConvertor converter = planner.sqlToRelConverter();
+
+        RelOptTable targetTable;
+
+        if (select.getFrom() != null) {
+            SqlNode from = SqlUtil.stripAs(select.getFrom());
+            // Skip non-references such as VALUES ..
+            if (from.getKind() != SqlKind.IDENTIFIER) {
+                return null;
+            }
+
+            targetTable = converter.getTargetTable(select.getFrom());
+            IgniteDataSource dataSource = 
targetTable.unwrap(IgniteDataSource.class);
+            if (!(dataSource instanceof IgniteTable)) {
+                return null;
+            }
+        } else {
+            // Try to optimize SELECT count(*) as well
+            targetTable = null;
+        }
+
+        IgniteTypeFactory typeFactory = planner.getTypeFactory();
+
+        // SELECT COUNT(*) ... row type
+        RelDataType countResultType = 
typeFactory.createSqlType(SqlTypeName.BIGINT);
+
+        RelDataTypeFactory.Builder inputRowBuilder = new Builder(typeFactory);
+        inputRowBuilder.add("ROWCOUNT", countResultType);
+        RelDataType inputRowType = inputRowBuilder.build();
+
+        RelDataType getCountType = 
inputRowType.getFieldList().get(0).getType();
+
+        // Build projection
+        // Rewrites SELECT count(*) ... as Project(exprs = [lit, $0, ... ]), 
where $0 references a row that stores a count.
+        // So we can feed results of get count operation into a projection to 
compute final results.
+
+        List<RexNode> expressions = new ArrayList<>();
+        List<String> expressionNames = new ArrayList<>();
+        boolean countAdded = false;
+
+        for (SqlNode selectItem : select.getSelectList()) {
+            SqlNode expr = SqlUtil.stripAs(selectItem);
+
+            if (isCountStar(planner.validator(), expr)) {
+                SqlCall call = (SqlCall) expr;
+
+                // Reject COUNT(DISTINCT id), but allow COUNT(DISTINCT 1)
+                if (call.getFunctionQuantifier() != null && 
call.getOperandList().get(0).getKind() != SqlKind.LITERAL) {
+                    return null;
+                }
+
+                RexBuilder rexBuilder = planner.cluster().getRexBuilder();
+                RexSlot countValRef = rexBuilder.makeInputRef(getCountType, 0);
+
+                expressions.add(countValRef);
+
+                countAdded = true;
+            } else if (isCountNull(expr)) {

Review Comment:
   Removed this piece of code.



##########
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlannerHelper.java:
##########
@@ -343,4 +360,171 @@ static boolean hasSubQuery(SqlNode node) {
             return super.visit(call);
         }
     }
+
+
+    /**
+     * Tries to optimize a query that looks like {@code SELECT count(*)}.
+     *
+     * @param planner Planner.
+     * @param txContext Transactional context.
+     * @param node Query node.
+     * @return Plan node with list of aliases, if the optimization is 
applicable.
+     */
+    public static @Nullable Pair<IgniteRel, List<String>> 
tryOptimizeSelectCount(
+            IgnitePlanner planner,
+            @Nullable QueryTransactionContext txContext,
+            SqlNode node
+    ) {
+        if (txContext != null && txContext.explicitTx() != null) {
+            return null;
+        }
+
+        if (!(node instanceof SqlSelect)) {
+            return null;
+        }
+
+        SqlSelect select = (SqlSelect) node;
+
+        if (select.getGroup() != null
+                || select.getWhere() != null
+                || select.getHaving() != null
+                || select.getQualify() != null
+                || !select.getWindowList().isEmpty()
+                || select.getOffset() != null
+                || select.getFetch() != null) {
+            return null;
+        }
+
+        IgniteSqlToRelConvertor converter = planner.sqlToRelConverter();
+
+        RelOptTable targetTable;
+
+        if (select.getFrom() != null) {
+            SqlNode from = SqlUtil.stripAs(select.getFrom());
+            // Skip non-references such as VALUES ..
+            if (from.getKind() != SqlKind.IDENTIFIER) {
+                return null;
+            }
+
+            targetTable = converter.getTargetTable(select.getFrom());
+            IgniteDataSource dataSource = 
targetTable.unwrap(IgniteDataSource.class);
+            if (!(dataSource instanceof IgniteTable)) {
+                return null;
+            }
+        } else {
+            // Try to optimize SELECT count(*) as well

Review Comment:
   Removed this piece of code.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to