alex-plekhanov commented on a change in pull request #9085:
URL: https://github.com/apache/ignite/pull/9085#discussion_r630770867



##########
File path: 
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/fun/IgniteSqlFunctions.java
##########
@@ -16,22 +16,149 @@
  */
 package org.apache.ignite.internal.processors.query.calcite.fun;
 
+import org.apache.calcite.DataContext;
+import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.Linq4j;
 import org.apache.calcite.linq4j.function.Strict;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.ScannableTable;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.Statistic;
+import org.apache.calcite.schema.Statistics;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.checkerframework.checker.nullness.qual.Nullable;
 
 /**
  * Ignite SQL functions.
  */
-public class IgniteSqlFunctions  {
+public class IgniteSqlFunctions {
     /**
      * Default constructor.
      */
     private IgniteSqlFunctions() {
         // No-op.
     }
 
+    /** SQL SYSTEM_RANGE(start, end) table function. */
+    public static ScannableTable system_range(Object rangeStart, Object 
rangeEnd) {
+        return new RangeTable(rangeStart, rangeEnd, 1L);
+    }
+
+    /** SQL SYSTEM_RANGE(start, end, increment) table function. */
+    public static ScannableTable system_range(Object rangeStart, Object 
rangeEnd, Object increment) {
+        return new RangeTable(rangeStart, rangeEnd, increment);
+    }
+
     /** SQL LENGTH(string) function. */
     @Strict
     public static int length(String str) {
         return str.length();
     }
+
+    /** */
+    private static class RangeTable implements ScannableTable {
+        /** Start of the range. */
+        private final Object rangeStart;
+
+        /** End of the range. */
+        private final Object rangeEnd;
+
+        /** Increment. */
+        private final Object increment;
+
+        /**
+         * Note: {@code Object} arguments required here due to:
+         * 1. {@code NULL} arguments need to be supported, so we can't use 
{@code long} arguments type.
+         * 2. {@code Integer} and other numeric classes can be converted to 
{@code long} type by java, but can't be
+         *      converted to {@code Long} type, so we can't use {@code Long} 
arguments type either.
+         * Instead, we accept {@code Object} arguments type and try to convert 
valid types to {@code long}.
+         */
+        RangeTable(Object rangeStart, Object rangeEnd, Object increment) {
+            this.rangeStart = rangeStart;
+            this.rangeEnd = rangeEnd;
+            this.increment = increment;
+        }
+
+        /** {@inheritDoc} */
+        @Override public RelDataType getRowType(RelDataTypeFactory 
typeFactory) {
+            return typeFactory.builder().add("X", SqlTypeName.BIGINT).build();
+        }
+
+        /** {@inheritDoc} */
+        @Override public Enumerable<@Nullable Object[]> scan(DataContext root) 
{
+            if (rangeStart == null || rangeEnd == null || increment == null)
+                return Linq4j.emptyEnumerable();
+
+            long rangeStart = convertToLongArg(this.rangeStart, "rangeStart");
+            long rangeEnd = convertToLongArg(this.rangeEnd, "rangeEnd");
+            long increment = convertToLongArg(this.increment, "increment");
+
+            if (increment == 0L)
+                throw new IllegalArgumentException("Increment can't be 0");
+
+            return new AbstractEnumerable<@Nullable Object[]>() {
+                @Override public Enumerator<@Nullable Object[]> enumerator() {
+                    return new Enumerator<Object[]>() {
+                        long cur = rangeStart - increment;
+
+                        @Override public Object[] current() {
+                            return new Object[] { cur };
+                        }
+
+                        @Override public boolean moveNext() {
+                            cur += increment;
+
+                            return increment > 0L ? cur <= rangeEnd : cur >= 
rangeEnd;
+                        }
+
+                        @Override public void reset() {
+                            cur = rangeStart - increment;
+                        }
+
+                        @Override public void close() {
+                            // No-op.
+                        }
+                    };
+                }
+            };
+        }
+
+        /** */
+        private long convertToLongArg(Object val, String name) {
+            if (val instanceof Byte || val instanceof Short || val instanceof 
Integer || val instanceof Long)

Review comment:
       Yes, we can, but do we really need it? H2 `system_range` supports only 
`Long` arguments, DuckDB `range` also supports only `Long` arguments and this 
looks enough.




-- 
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.

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


Reply via email to