This is an automated email from the ASF dual-hosted git repository.

yashmayya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new fffc79c0cc1 Support Object parameters for column arguments in scalar 
function wrapper (#19789)
fffc79c0cc1 is described below

commit fffc79c0cc1eb1e72ecb4ffd4dc70e1213252291
Author: Yash Mayya <[email protected]>
AuthorDate: Mon Oct 12 16:43:17 2026 -0700

    Support Object parameters for column arguments in scalar function wrapper 
(#19789)
---
 .../function/ScalarTransformFunctionWrapper.java   |  62 ++++++-
 .../ScalarTransformFunctionWrapperTest.java        |  47 +++++
 .../ObjectParameterScalarFunctionsQueriesTest.java | 195 +++++++++++++++++++++
 .../queries/ObjectParameterFunctions.json          |  60 +++++++
 4 files changed, 361 insertions(+), 3 deletions(-)

diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapper.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapper.java
index 03f650871ab..f55123a3295 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapper.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapper.java
@@ -50,6 +50,7 @@ public class ScalarTransformFunctionWrapper extends 
BaseTransformFunction {
   private int _numNonLiteralArguments;
   private int[] _nonLiteralIndices;
   private TransformFunction[] _nonLiteralFunctions;
+  private PinotDataType[] _nonLiteralTypes;
   private Object[][] _nonLiteralValues;
 
   public ScalarTransformFunctionWrapper(FunctionInfo functionInfo) {
@@ -91,6 +92,7 @@ public class ScalarTransformFunctionWrapper extends 
BaseTransformFunction {
     _scalarArguments = new Object[numArguments];
     _nonLiteralIndices = new int[numArguments];
     _nonLiteralFunctions = new TransformFunction[numArguments];
+    _nonLiteralTypes = new PinotDataType[numArguments];
     for (int i = 0; i < numArguments; i++) {
       TransformFunction transformFunction = arguments.get(i);
       if (transformFunction instanceof LiteralTransformFunction) {
@@ -146,6 +148,9 @@ public class ScalarTransformFunctionWrapper extends 
BaseTransformFunction {
       } else {
         _nonLiteralIndices[_numNonLiteralArguments] = i;
         _nonLiteralFunctions[_numNonLiteralArguments] = transformFunction;
+        _nonLiteralTypes[_numNonLiteralArguments] = parameterTypes[i] != 
PinotDataType.OBJECT
+            ? parameterTypes[i]
+            : getObjectArgumentType(transformFunction.getResultMetadata());
         _numNonLiteralArguments++;
       }
     }
@@ -374,11 +379,46 @@ public class ScalarTransformFunctionWrapper extends 
BaseTransformFunction {
     return _stringValuesMV;
   }
 
-  /// Helper method to fetch values for the non-literal transform functions 
based on the parameter types.
+  /// Returns the type to read an argument for an `Object` parameter, so that 
the function gets the external Java value
+  /// of the argument result type, the same as `ColumnDataType.toExternal()` 
in the multi-stage engine `FunctionOperand`
+  /// for that type. Complex types such as MAP are not supported.
+  private PinotDataType getObjectArgumentType(TransformResultMetadata 
argumentMetadata) {
+    DataType dataType = argumentMetadata.getDataType();
+    boolean singleValue = argumentMetadata.isSingleValue();
+    switch (dataType) {
+      case INT:
+        return singleValue ? PinotDataType.INT : 
PinotDataType.PRIMITIVE_INT_ARRAY;
+      case LONG:
+        return singleValue ? PinotDataType.LONG : 
PinotDataType.PRIMITIVE_LONG_ARRAY;
+      case FLOAT:
+        return singleValue ? PinotDataType.FLOAT : 
PinotDataType.PRIMITIVE_FLOAT_ARRAY;
+      case DOUBLE:
+        return singleValue ? PinotDataType.DOUBLE : 
PinotDataType.PRIMITIVE_DOUBLE_ARRAY;
+      case BIG_DECIMAL:
+        return singleValue ? PinotDataType.BIG_DECIMAL : 
PinotDataType.BIG_DECIMAL_ARRAY;
+      case BOOLEAN:
+        return singleValue ? PinotDataType.BOOLEAN : 
PinotDataType.PRIMITIVE_BOOLEAN_ARRAY;
+      case TIMESTAMP:
+        return singleValue ? PinotDataType.TIMESTAMP : 
PinotDataType.TIMESTAMP_ARRAY;
+      case STRING:
+      case JSON:
+        return singleValue ? PinotDataType.STRING : PinotDataType.STRING_ARRAY;
+      case BYTES:
+        return singleValue ? PinotDataType.BYTES : PinotDataType.BYTES_ARRAY;
+      case UUID:
+        return singleValue ? PinotDataType.UUID : PinotDataType.UUID_ARRAY;
+      default:
+        throw new IllegalArgumentException(
+            String.format("Unsupported argument type: %s for Object parameter 
of method: %s", dataType,
+                _functionInvoker.getMethod()));
+    }
+  }
+
+  /// Helper method to fetch values for the non-literal transform functions 
based on the parameter types. For an
+  /// `Object` parameter, the values are read based on the argument result 
type (see [#getObjectArgumentType]).
   private void getNonLiteralValues(ValueBlock valueBlock) {
-    PinotDataType[] parameterTypes = _functionInvoker.getParameterTypes();
     for (int i = 0; i < _numNonLiteralArguments; i++) {
-      PinotDataType parameterType = parameterTypes[_nonLiteralIndices[i]];
+      PinotDataType parameterType = _nonLiteralTypes[i];
       TransformFunction transformFunction = _nonLiteralFunctions[i];
       switch (parameterType) {
         case INT:
@@ -485,6 +525,22 @@ public class ScalarTransformFunctionWrapper extends 
BaseTransformFunction {
         case BYTES_ARRAY:
           _nonLiteralValues[i] = 
transformFunction.transformToBytesValuesMV(valueBlock);
           break;
+        case UUID_ARRAY: {
+          byte[][][] bytesValuesMV = 
transformFunction.transformToBytesValuesMV(valueBlock);
+          int numRows = bytesValuesMV.length;
+          UUID[][] uuidValuesMV = new UUID[numRows][];
+          for (int j = 0; j < numRows; j++) {
+            byte[][] bytesValues = bytesValuesMV[j];
+            int numValues = bytesValues.length;
+            UUID[] uuidValues = new UUID[numValues];
+            for (int k = 0; k < numValues; k++) {
+              uuidValues[k] = UuidUtils.toUUID(bytesValues[k]);
+            }
+            uuidValuesMV[j] = uuidValues;
+          }
+          _nonLiteralValues[i] = uuidValuesMV;
+          break;
+        }
         default:
           throw new IllegalStateException("Unsupported parameter type: " + 
parameterType);
       }
diff --git 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapperTest.java
 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapperTest.java
index 7beecd92954..50e9775d257 100644
--- 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapperTest.java
+++ 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/ScalarTransformFunctionWrapperTest.java
@@ -49,6 +49,7 @@ import org.apache.pinot.spi.utils.BigDecimalUtils;
 import org.apache.pinot.spi.utils.CommonConstants.NullValuePlaceHolder;
 import org.apache.pinot.spi.utils.UuidUtils;
 import org.roaringbitmap.RoaringBitmap;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import static org.testng.Assert.assertEquals;
@@ -1712,6 +1713,52 @@ public class ScalarTransformFunctionWrapperTest extends 
BaseTransformFunctionTes
     testTransformFunction(transformFunction, expectedValues);
   }
 
+  // Test-only scalar function with an `Object` parameter, registered the same 
way as the ones above. It returns the
+  // Java class of the argument, so the test below can check which class an 
`Object` parameter receives per type.
+
+  @ScalarFunction
+  public static String objectArgumentClass(Object value) {
+    return value.getClass().getSimpleName();
+  }
+
+  @DataProvider
+  public static Object[][] objectArgumentClassDataProvider() {
+    // The argument should be the external Java value, the same as 
ColumnDataType.toExternal() in the multi-stage
+    // engine FunctionOperand.
+    return new Object[][]{
+        {INT_SV_COLUMN, "Integer"},
+        {LONG_SV_COLUMN, "Long"},
+        {FLOAT_SV_COLUMN, "Float"},
+        {DOUBLE_SV_COLUMN, "Double"},
+        {BIG_DECIMAL_SV_COLUMN, "BigDecimal"},
+        {String.format("CAST(%s AS BOOLEAN)", INT_SV_COLUMN), "Boolean"},
+        {TIMESTAMP_COLUMN, "Timestamp"},
+        {STRING_SV_COLUMN, "String"},
+        {JSON_COLUMN, "String"},
+        {BYTES_SV_COLUMN, "byte[]"},
+        {UUID_SV_COLUMN, "UUID"},
+        {INT_MV_COLUMN, "int[]"},
+        {LONG_MV_COLUMN, "long[]"},
+        {FLOAT_MV_COLUMN, "float[]"},
+        {DOUBLE_MV_COLUMN, "double[]"},
+        {String.format("CAST(%s AS BIG_DECIMAL)", INT_MV_COLUMN), 
"BigDecimal[]"},
+        {String.format("CAST(%s AS BOOLEAN)", INT_MV_COLUMN), "boolean[]"},
+        {String.format("CAST(%s AS TIMESTAMP)", LONG_MV_COLUMN), 
"Timestamp[]"},
+        {STRING_MV_COLUMN, "String[]"}
+    };
+  }
+
+  @Test(dataProvider = "objectArgumentClassDataProvider")
+  public void testObjectParameter(String argument, String expectedClass) {
+    ExpressionContext expression =
+        
RequestContextUtils.getExpression(String.format("objectArgumentClass(%s)", 
argument));
+    TransformFunction transformFunction = 
TransformFunctionFactory.get(expression, _dataSourceMap);
+    assertTrue(transformFunction instanceof ScalarTransformFunctionWrapper);
+    String[] expectedValues = new String[NUM_ROWS];
+    Arrays.fill(expectedValues, expectedClass);
+    testTransformFunction(transformFunction, expectedValues);
+  }
+
   private static class StaticUuidTransformFunction extends 
BaseTransformFunction {
     private static final TransformResultMetadata RESULT_METADATA =
         new TransformResultMetadata(DataType.UUID, true, false);
diff --git 
a/pinot-core/src/test/java/org/apache/pinot/queries/ObjectParameterScalarFunctionsQueriesTest.java
 
b/pinot-core/src/test/java/org/apache/pinot/queries/ObjectParameterScalarFunctionsQueriesTest.java
new file mode 100644
index 00000000000..870b071662f
--- /dev/null
+++ 
b/pinot-core/src/test/java/org/apache/pinot/queries/ObjectParameterScalarFunctionsQueriesTest.java
@@ -0,0 +1,195 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.queries;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.List;
+import org.apache.commons.io.FileUtils;
+import org.apache.pinot.common.function.scalar.StringFunctions;
+import org.apache.pinot.common.response.broker.BrokerResponseNative;
+import org.apache.pinot.core.function.scalar.SketchFunctions;
+import 
org.apache.pinot.segment.local.indexsegment.immutable.ImmutableSegmentLoader;
+import 
org.apache.pinot.segment.local.segment.creator.impl.SegmentIndexCreationDriverImpl;
+import org.apache.pinot.segment.local.segment.readers.GenericRowRecordReader;
+import org.apache.pinot.segment.spi.ImmutableSegment;
+import org.apache.pinot.segment.spi.IndexSegment;
+import org.apache.pinot.segment.spi.creator.SegmentGeneratorConfig;
+import org.apache.pinot.spi.config.table.TableConfig;
+import org.apache.pinot.spi.config.table.TableType;
+import org.apache.pinot.spi.data.FieldSpec.DataType;
+import org.apache.pinot.spi.data.Schema;
+import org.apache.pinot.spi.data.readers.GenericRow;
+import org.apache.pinot.spi.utils.ReadMode;
+import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+
+/// Queries test for scalar functions with an `Object` parameter (e.g. the 
sketch functions and `jsonFormat`) on column
+/// arguments. The function should get the external Java value of the column 
type.
+public class ObjectParameterScalarFunctionsQueriesTest extends BaseQueriesTest 
{
+  private static final File INDEX_DIR =
+      new File(FileUtils.getTempDirectory(), 
"ObjectParameterScalarFunctionsQueriesTest");
+  private static final String RAW_TABLE_NAME = "testTable";
+  private static final String SEGMENT_NAME = "testSegment";
+
+  private static final String INT_COLUMN = "intCol";
+  private static final String LONG_COLUMN = "longCol";
+  private static final String FLOAT_COLUMN = "floatCol";
+  private static final String DOUBLE_COLUMN = "doubleCol";
+  private static final String BIG_DECIMAL_COLUMN = "bigDecimalCol";
+  private static final String BOOLEAN_COLUMN = "booleanCol";
+  private static final String TIMESTAMP_COLUMN = "timestampCol";
+  private static final String STRING_COLUMN = "stringCol";
+  private static final String BYTES_COLUMN = "bytesCol";
+  private static final String UUID_COLUMN = "uuidCol";
+  private static final String INT_MV_COLUMN = "intMVCol";
+  private static final String BOOLEAN_MV_COLUMN = "booleanMVCol";
+  private static final String STRING_MV_COLUMN = "stringMVCol";
+  private static final String BYTES_MV_COLUMN = "bytesMVCol";
+  private static final String UUID_MV_COLUMN = "uuidMVCol";
+  private static final String UUID_1 = "550e8400-e29b-41d4-a716-446655440000";
+  private static final String UUID_2 = "123e4567-e89b-12d3-a456-426614174000";
+  private static final Schema SCHEMA = new Schema.SchemaBuilder()
+      .addSingleValueDimension(INT_COLUMN, DataType.INT)
+      .addSingleValueDimension(LONG_COLUMN, DataType.LONG)
+      .addSingleValueDimension(FLOAT_COLUMN, DataType.FLOAT)
+      .addSingleValueDimension(DOUBLE_COLUMN, DataType.DOUBLE)
+      .addMetric(BIG_DECIMAL_COLUMN, DataType.BIG_DECIMAL)
+      .addSingleValueDimension(BOOLEAN_COLUMN, DataType.BOOLEAN)
+      .addSingleValueDimension(TIMESTAMP_COLUMN, DataType.TIMESTAMP)
+      .addSingleValueDimension(STRING_COLUMN, DataType.STRING)
+      .addSingleValueDimension(BYTES_COLUMN, DataType.BYTES)
+      .addSingleValueDimension(UUID_COLUMN, DataType.UUID)
+      .addMultiValueDimension(INT_MV_COLUMN, DataType.INT)
+      .addMultiValueDimension(BOOLEAN_MV_COLUMN, DataType.BOOLEAN)
+      .addMultiValueDimension(STRING_MV_COLUMN, DataType.STRING)
+      .addMultiValueDimension(BYTES_MV_COLUMN, DataType.BYTES)
+      .addMultiValueDimension(UUID_MV_COLUMN, DataType.UUID)
+      .build();
+  private static final TableConfig TABLE_CONFIG =
+      new 
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME).build();
+
+  private IndexSegment _indexSegment;
+  private List<IndexSegment> _indexSegments;
+
+  @Override
+  protected String getFilter() {
+    return "";
+  }
+
+  @Override
+  protected IndexSegment getIndexSegment() {
+    return _indexSegment;
+  }
+
+  @Override
+  protected List<IndexSegment> getIndexSegments() {
+    return _indexSegments;
+  }
+
+  @BeforeClass
+  public void setUp()
+      throws Exception {
+    FileUtils.deleteDirectory(INDEX_DIR);
+
+    GenericRow record = new GenericRow();
+    record.putValue(INT_COLUMN, 1);
+    record.putValue(LONG_COLUMN, 2L);
+    record.putValue(FLOAT_COLUMN, 1.5f);
+    record.putValue(DOUBLE_COLUMN, 2.5);
+    record.putValue(BIG_DECIMAL_COLUMN, new BigDecimal("3.25"));
+    record.putValue(BOOLEAN_COLUMN, true);
+    record.putValue(TIMESTAMP_COLUMN, 1700000000000L);
+    record.putValue(STRING_COLUMN, "abc");
+    record.putValue(BYTES_COLUMN, new byte[]{1, 2, 3});
+    record.putValue(UUID_COLUMN, UUID_1);
+    record.putValue(INT_MV_COLUMN, new Object[]{1, 2});
+    record.putValue(BOOLEAN_MV_COLUMN, new Object[]{true, false});
+    record.putValue(STRING_MV_COLUMN, new Object[]{"a", "b"});
+    record.putValue(BYTES_MV_COLUMN, new Object[]{new byte[]{1, 2}, new 
byte[]{3}});
+    record.putValue(UUID_MV_COLUMN, new Object[]{UUID_1, UUID_2});
+
+    SegmentGeneratorConfig segmentGeneratorConfig = new 
SegmentGeneratorConfig(TABLE_CONFIG, SCHEMA);
+    segmentGeneratorConfig.setTableName(RAW_TABLE_NAME);
+    segmentGeneratorConfig.setSegmentName(SEGMENT_NAME);
+    segmentGeneratorConfig.setOutDir(INDEX_DIR.getPath());
+
+    SegmentIndexCreationDriverImpl driver = new 
SegmentIndexCreationDriverImpl();
+    driver.init(segmentGeneratorConfig, new 
GenericRowRecordReader(List.of(record)));
+    driver.build();
+
+    ImmutableSegment immutableSegment = ImmutableSegmentLoader.load(new 
File(INDEX_DIR, SEGMENT_NAME), ReadMode.mmap);
+    _indexSegment = immutableSegment;
+    _indexSegments = List.of(immutableSegment, immutableSegment);
+  }
+
+  @Test
+  public void testSketchFunctions() {
+    String query = "SELECT toBase64(toThetaSketch(intCol)), 
toBase64(toHLL(longCol)), "
+        + "toBase64(toCpcSketch(doubleCol)), toBase64(toULL(stringCol)), "
+        + "toBase64(toIntegerSumTupleSketch(bigDecimalCol, intCol)), 
toBase64(toThetaSketch(bytesCol)), "
+        + "getThetaSketchEstimate(toThetaSketch(floatCol)) FROM testTable 
LIMIT 1";
+    Object[] expectedRow = new Object[]{
+        StringFunctions.toBase64(SketchFunctions.toThetaSketch(1)),
+        StringFunctions.toBase64(SketchFunctions.toHLL(2L)),
+        StringFunctions.toBase64(SketchFunctions.toCpcSketch(2.5)),
+        StringFunctions.toBase64(SketchFunctions.toULL("abc")),
+        StringFunctions.toBase64(SketchFunctions.toIntegerSumTupleSketch(new 
BigDecimal("3.25"), 1)),
+        StringFunctions.toBase64(SketchFunctions.toThetaSketch(new byte[]{1, 
2, 3})),
+        1L
+    };
+    List<Object[]> rows = getRows(query);
+    assertEquals(rows.size(), 1);
+    assertEquals(rows.get(0), expectedRow);
+  }
+
+  @Test
+  public void testJsonFormat() {
+    String query = "SELECT jsonFormat(intCol), jsonFormat(longCol), 
jsonFormat(floatCol), jsonFormat(doubleCol), "
+        + "jsonFormat(bigDecimalCol), jsonFormat(booleanCol), 
jsonFormat(timestampCol), jsonFormat(stringCol), "
+        + "jsonFormat(bytesCol), jsonFormat(uuidCol), jsonFormat(intMVCol), 
jsonFormat(booleanMVCol), "
+        + "jsonFormat(stringMVCol), jsonFormat(bytesMVCol), 
jsonFormat(uuidMVCol) FROM testTable LIMIT 1";
+    Object[] expectedRow = new Object[]{
+        "1", "2", "1.5", "2.5", "3.25", "true", "1700000000000", "\"abc\"", 
"\"AQID\"", "\"" + UUID_1 + "\"",
+        "[1,2]", "[true,false]", "[\"a\",\"b\"]", "[\"AQI=\",\"Aw==\"]", "[\"" 
+ UUID_1 + "\",\"" + UUID_2 + "\"]"
+    };
+    List<Object[]> rows = getRows(query);
+    assertEquals(rows.size(), 1);
+    assertEquals(rows.get(0), expectedRow);
+  }
+
+  private List<Object[]> getRows(String query) {
+    BrokerResponseNative brokerResponse = getBrokerResponse(query);
+    assertTrue(brokerResponse.getExceptions().isEmpty(), 
brokerResponse.getExceptions().toString());
+    return brokerResponse.getResultTable().getRows();
+  }
+
+  @AfterClass
+  public void tearDown()
+      throws Exception {
+    _indexSegment.destroy();
+    FileUtils.deleteDirectory(INDEX_DIR);
+  }
+}
diff --git 
a/pinot-query-runtime/src/test/resources/queries/ObjectParameterFunctions.json 
b/pinot-query-runtime/src/test/resources/queries/ObjectParameterFunctions.json
new file mode 100644
index 00000000000..f12874602e6
--- /dev/null
+++ 
b/pinot-query-runtime/src/test/resources/queries/ObjectParameterFunctions.json
@@ -0,0 +1,60 @@
+{
+  "object_parameter_functions": {
+    "comments": "Scalar functions with an Object parameter get the external 
Java value of the column type. In the leaf stage the call runs in 
ScalarTransformFunctionWrapper, above a stage boundary it runs in 
FunctionOperand; for column arguments both must return the same result.",
+    "tables": {
+      "tbl": {
+        "schema": [
+          {"name": "intCol", "type": "INT"},
+          {"name": "longCol", "type": "LONG"},
+          {"name": "floatCol", "type": "FLOAT"},
+          {"name": "doubleCol", "type": "DOUBLE"},
+          {"name": "bigDecimalCol", "type": "BIG_DECIMAL"},
+          {"name": "boolCol", "type": "BOOLEAN"},
+          {"name": "strCol", "type": "STRING"},
+          {"name": "bytesCol", "type": "BYTES"},
+          {"name": "intArrayCol", "type": "INT", "isSingleValue": false},
+          {"name": "strArrayCol", "type": "STRING", "isSingleValue": false}
+        ],
+        "inputs": [
+          [1, 10000000001, 1.5, 1.25, "1.125", true, "a", "AA01", [1, 2], 
["a", "b"]],
+          ["------"],
+          [2, 10000000002, 2.5, 2.25, "2.375", false, "b", "AA02", [3], ["c"]]
+        ]
+      }
+    },
+    "queries": [
+      {
+        "description": "jsonFormat on columns in the leaf stage",
+        "sql": "SELECT intCol, jsonFormat(intCol), jsonFormat(longCol), 
jsonFormat(floatCol), jsonFormat(doubleCol), jsonFormat(bigDecimalCol), 
jsonFormat(boolCol), jsonFormat(strCol), jsonFormat(bytesCol), 
jsonFormat(intArrayCol), jsonFormat(strArrayCol) FROM {tbl}",
+        "outputs": [
+          [1, "1", "10000000001", "1.5", "1.25", "1.125", "true", "\"a\"", 
"\"qgE=\"", "[1,2]", "[\"a\",\"b\"]"],
+          [2, "2", "10000000002", "2.5", "2.25", "2.375", "false", "\"b\"", 
"\"qgI=\"", "[3]", "[\"c\"]"]
+        ]
+      },
+      {
+        "description": "jsonFormat on columns above a stage boundary",
+        "sql": "SELECT intCol, jsonFormat(intCol), jsonFormat(longCol), 
jsonFormat(floatCol), jsonFormat(doubleCol), jsonFormat(bigDecimalCol), 
jsonFormat(boolCol), jsonFormat(strCol), jsonFormat(bytesCol), 
jsonFormat(intArrayCol), jsonFormat(strArrayCol) FROM (SELECT * FROM {tbl} 
ORDER BY intCol LIMIT 10)",
+        "outputs": [
+          [1, "1", "10000000001", "1.5", "1.25", "1.125", "true", "\"a\"", 
"\"qgE=\"", "[1,2]", "[\"a\",\"b\"]"],
+          [2, "2", "10000000002", "2.5", "2.25", "2.375", "false", "\"b\"", 
"\"qgI=\"", "[3]", "[\"c\"]"]
+        ]
+      },
+      {
+        "description": "toThetaSketch on a column in the leaf stage",
+        "sql": "SELECT intCol, toBase64(toThetaSketch(intCol)) FROM {tbl}",
+        "outputs": [
+          [1, "AQMDAAA6zJMV+X3LvYahBQ=="],
+          [2, "AQMDAAA6zJPDl/wSgXCdHg=="]
+        ]
+      },
+      {
+        "description": "toThetaSketch on a column above a stage boundary",
+        "sql": "SELECT intCol, toBase64(toThetaSketch(intCol)) FROM (SELECT 
intCol FROM {tbl} GROUP BY intCol)",
+        "outputs": [
+          [1, "AQMDAAA6zJMV+X3LvYahBQ=="],
+          [2, "AQMDAAA6zJPDl/wSgXCdHg=="]
+        ]
+      }
+    ]
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to