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

xiangfu 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 4aecd77fd5 Changes to support private columns (#11484)
4aecd77fd5 is described below

commit 4aecd77fd5d98d3b69da895a5550daf5b9d11a14
Author: Gonzalo Ortiz Jaureguizar <[email protected]>
AuthorDate: Mon Sep 4 17:30:13 2023 +0200

    Changes to support private columns (#11484)
    
    * Changes to support private columns
    
    * Fix code style and add javadoc
    
    * Create some tests to verify correct select star projection
---
 .../pinot/integration/tests/ClusterTest.java       | 38 ++++++++++++++++++++++
 .../tests/MultiStageEngineIntegrationTest.java     | 26 +++++++++++++++
 .../org/apache/pinot/query/validate/Validator.java | 24 ++++++++++++++
 3 files changed, 88 insertions(+)

diff --git 
a/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterTest.java
 
b/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterTest.java
index 2a278166c7..9845318f30 100644
--- 
a/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterTest.java
+++ 
b/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/ClusterTest.java
@@ -30,6 +30,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
@@ -76,6 +77,7 @@ import org.apache.pinot.spi.utils.JsonUtils;
 import org.apache.pinot.spi.utils.NetUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 
 import static 
org.apache.pinot.integration.tests.ClusterIntegrationTestUtils.getBrokerQueryApiUrl;
@@ -513,6 +515,42 @@ public abstract class ClusterTest extends ControllerTest {
         sendPostRequest(controllerBaseApiUrl + "/sql", 
JsonUtils.objectToString(payload), headers));
   }
 
+  public List<String> getColumns(JsonNode response) {
+    JsonNode resultTableJson = response.get("resultTable");
+    Assert.assertNotNull(resultTableJson, "'resultTable' is null");
+    JsonNode dataSchemaJson = resultTableJson.get("dataSchema");
+    Assert.assertNotNull(resultTableJson, "'resultTable.dataSchema' is null");
+    JsonNode colNamesJson = dataSchemaJson.get("columnNames");
+    Assert.assertNotNull(resultTableJson, 
"'resultTable.dataSchema.columnNames' is null");
+
+    List<String> cols = new ArrayList<>();
+    int i = 0;
+    for (JsonNode jsonNode : colNamesJson) {
+      String colName = jsonNode.textValue();
+      Assert.assertNotNull(colName, "Column at index " + i + " is not a 
string");
+      cols.add(colName);
+      i++;
+    }
+    return cols;
+  }
+
+  public void assertNoError(JsonNode response) {
+    JsonNode exceptionsJson = response.get("exceptions");
+    Iterator<JsonNode> exIterator = exceptionsJson.iterator();
+    if (exIterator.hasNext()) {
+      Assert.fail("There is at least one exception: " + exIterator.next());
+    }
+  }
+
+  @DataProvider(name = "systemColumns")
+  public Object[][] systemColumns() {
+    return new Object[][] {
+        {"$docId"},
+        {"$hostName"},
+        {"$segmentName"}
+    };
+  }
+
   @DataProvider(name = "useBothQueryEngines")
   public Object[][] useBothQueryEngines() {
     return new Object[][]{
diff --git 
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
 
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
index 28ba7be826..f6a2345a62 100644
--- 
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
+++ 
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java
@@ -674,6 +674,32 @@ public class MultiStageEngineIntegrationTest extends 
BaseClusterIntegrationTestS
     
Assert.assertEquals(jsonNode.get("resultTable").get("dataSchema").get("columnDataTypes").get(0).asText(),
 "DOUBLE");
   }
 
+  @Test
+  public void selectStarDoesNotProjectSystemColumns()
+      throws Exception {
+    JsonNode jsonNode = postQuery("select * from mytable limit 0");
+    List<String> columns = getColumns(jsonNode);
+    for (int i = 0; i < columns.size(); i++) {
+      String colName = columns.get(i);
+      Assert.assertFalse(colName.startsWith("$"), "Column " + colName + " 
(found at index " + i + " is a system column "
+          + "and shouldn't be included in select *");
+    }
+  }
+
+  @Test(dataProvider = "systemColumns")
+  public void systemColumnsCanBeSelected(String systemColumn)
+      throws Exception {
+    JsonNode jsonNode = postQuery("select " + systemColumn + " from mytable 
limit 0");
+    assertNoError(jsonNode);
+  }
+
+  @Test(dataProvider = "systemColumns")
+  public void systemColumnsCanBeUsedInWhere(String systemColumn)
+      throws Exception {
+    JsonNode jsonNode = postQuery("select 1 from mytable where " + 
systemColumn + " is not null limit 0");
+    assertNoError(jsonNode);
+  }
+
   @AfterClass
   public void tearDown()
       throws Exception {
diff --git 
a/pinot-query-planner/src/main/java/org/apache/pinot/query/validate/Validator.java
 
b/pinot-query-planner/src/main/java/org/apache/pinot/query/validate/Validator.java
index 14a0797957..6a3aa25d1a 100644
--- 
a/pinot-query-planner/src/main/java/org/apache/pinot/query/validate/Validator.java
+++ 
b/pinot-query-planner/src/main/java/org/apache/pinot/query/validate/Validator.java
@@ -20,14 +20,19 @@ package org.apache.pinot.query.validate;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rel.type.RelRecordType;
 import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.SqlOperatorTable;
 import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.validate.SelectScope;
 import org.apache.calcite.sql.validate.SqlConformanceEnum;
 import org.apache.calcite.sql.validate.SqlValidatorCatalogReader;
 import org.apache.calcite.sql.validate.SqlValidatorImpl;
@@ -124,4 +129,23 @@ public class Validator extends SqlValidatorImpl {
     List<String> names = identifier.names;
     return names.get(names.size() - 1);
   }
+
+  /**
+   * This method is only called by Calcite when adding rows to select as a 
result of doing {@code select *}.
+   *
+   * This is just a patch knowing the internals of Calcite, but there is no 
officially supported solution right now.
+   * See <a 
href="https://lists.apache.org/thread/c71fkv329001hjjq7bp4hm56q6yx6dvw";>this 
question in the dev email
+   * list</a>
+   */
+  @Override
+  protected void addToSelectList(List<SqlNode> list, Set<String> aliases,
+      List<Map.Entry<String, RelDataType>> fieldList, SqlNode exp, SelectScope 
scope, boolean includeSystemVars) {
+    if (exp.getKind() == SqlKind.IDENTIFIER) {
+      SqlIdentifier sqlIdentifier = (SqlIdentifier) exp;
+      if (sqlIdentifier.names.stream().anyMatch(s -> s.startsWith("$"))) {
+        return;
+      }
+    }
+    super.addToSelectList(list, aliases, fieldList, exp, scope, 
includeSystemVars);
+  }
 }


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

Reply via email to