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

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


The following commit(s) were added to refs/heads/master by this push:
     new db0fef1160 PHOENIX-7654 Restrict BSON datatype in composite PK as last 
part of the pk column (#2212)
db0fef1160 is described below

commit db0fef1160585682d6004aebe2e353f69efd1780
Author: Rahul Kumar <[email protected]>
AuthorDate: Tue Jul 8 04:04:59 2025 +0530

    PHOENIX-7654 Restrict BSON datatype in composite PK as last part of the pk 
column (#2212)
---
 .../apache/phoenix/exception/SQLExceptionCode.java |  4 ++
 .../org/apache/phoenix/schema/MetaDataClient.java  | 13 +++++++
 .../org/apache/phoenix/end2end/AlterTableIT.java   | 25 ++++++++++++
 .../java/org/apache/phoenix/end2end/Bson4IT.java   | 44 ++++++++++++++++++++++
 4 files changed, 86 insertions(+)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
index f9492003f3..c85395ad2f 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
@@ -238,8 +238,12 @@ public enum SQLExceptionCode {
     VARBINARY_IN_ROW_KEY(1005, "42J03",
         "The VARBINARY/ARRAY type can only be used as the last part of a 
multi-part row key. "
             + "For Binary types, you can use VARBINARY_ENCODED for early part 
of multi-part row key."),
+    BSON_IN_ROW_KEY(1157, "42J03",
+        "The BSON type can only be used as the last part of a multi-part row 
key."),
     NOT_NULLABLE_COLUMN_IN_ROW_KEY(1006, "42J04", "Only nullable columns may 
be added to primary key."),
     VARBINARY_LAST_PK(1015, "42J04", "Cannot add column to table when the last 
PK column is of type VARBINARY or ARRAY."),
+    BSON_LAST_PK(1156, "42J04",
+        "Cannot add column to table when the last PK column is of type BSON."),
     NULLABLE_FIXED_WIDTH_LAST_PK(1023, "42J04", "Cannot add column to table 
when the last PK column is nullable and fixed width."),
     CANNOT_MODIFY_VIEW_PK(1036, "42J04", "Cannot modify the primary key of a 
VIEW if last PK column of parent is variable length."),
     BASE_TABLE_COLUMN(1037, "42J04", "Cannot modify columns of base table used 
by tenant-specific tables."),
diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 18d4cdb7fc..5b9498644f 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -283,6 +283,7 @@ import org.apache.phoenix.schema.PTable.ViewType;
 import org.apache.phoenix.schema.stats.GuidePostsKey;
 import org.apache.phoenix.schema.stats.StatisticsUtil;
 import org.apache.phoenix.schema.task.Task;
+import org.apache.phoenix.schema.types.PBson;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PDate;
 import org.apache.phoenix.schema.types.PLong;
@@ -3287,6 +3288,13 @@ public class MetaDataClient {
                         .setTableName(tableName)
                         .setColumnName(column.getName().getString())
                         .build().buildException();
+                } else if (colDef.getDataType() == PBson.INSTANCE && 
SchemaUtil.isPKColumn(column)
+                    && pkColumnsIterator.hasNext()) {
+                    throw new 
SQLExceptionInfo.Builder(SQLExceptionCode.BSON_IN_ROW_KEY)
+                        .setSchemaName(schemaName)
+                        .setTableName(tableName)
+                        .setColumnName(column.getName().getString())
+                        .build().buildException();
                 }
                 if (column.getFamilyName() != null) {
                     familyNames.put(
@@ -4633,6 +4641,11 @@ public class MetaDataClient {
                         throw new 
SQLExceptionInfo.Builder(SQLExceptionCode.VARBINARY_LAST_PK)
                         
.setColumnName(lastPK.getName().getString()).build().buildException();
                     }
+                    // Disallow adding columns if the last column in the 
primary key is BSON.
+                    if (lastPK.getDataType() == PBson.INSTANCE) {
+                        throw new 
SQLExceptionInfo.Builder(SQLExceptionCode.BSON_LAST_PK)
+                            
.setColumnName(lastPK.getName().getString()).build().buildException();
+                    }
                     // Disallow adding columns if last column in the primary 
key is fixed width
                     // and nullable.
                     if (lastPK.isNullable() && 
lastPK.getDataType().isFixedWidth()) {
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
index 5648d0409c..5f20ac6518 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
@@ -155,6 +155,31 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
         }
     }
 
+    @Test
+    public void testAlterTableWithBSONKey() throws Exception {
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        conn.setAutoCommit(false);
+
+        String ddl = "CREATE TABLE  " + dataTableFullName +
+            "  (a_string varchar not null, a_bson BSON not null, col1 integer" 
+
+            "  CONSTRAINT pk PRIMARY KEY (a_string, a_bson)) " + 
tableDDLOptions;
+        createTestTable(getUrl(), ddl);
+
+        conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " 
SET DISABLE_WAL = true");
+
+        try {
+            ddl = "ALTER TABLE " + dataTableFullName + " ADD b_string VARCHAR 
NULL PRIMARY KEY";
+            PreparedStatement stmt = conn.prepareStatement(ddl);
+            stmt.execute();
+            fail("Should have caught bad alter.");
+        } catch (SQLException e) {
+            assertEquals(SQLExceptionCode.BSON_LAST_PK.getErrorCode(), 
e.getErrorCode());
+        } finally {
+            conn.close();
+        }
+    }
+
     @Test
     public void testDropSystemTable() throws Exception {
         Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java
index 8c15854200..c20a7bbd23 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Bson4IT.java
@@ -33,6 +33,7 @@ import java.util.Collection;
 import java.util.Properties;
 
 import org.apache.hadoop.hbase.util.Pair;
+import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.jdbc.PhoenixStatement;
 import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
 import org.apache.phoenix.schema.types.PDouble;
@@ -43,6 +44,7 @@ import org.bson.BsonDouble;
 import org.bson.BsonNull;
 import org.bson.BsonString;
 import org.bson.RawBsonDocument;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
@@ -59,6 +61,7 @@ import static 
org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -993,6 +996,47 @@ public class Bson4IT extends ParallelStatsDisabledIT {
     }
   }
 
+  @Test
+  public void testIndexingONBsonNotAllowed() throws Exception {
+    Assume.assumeTrue(this.coveredIndex && this.columnEncoded);
+    Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+    String tableName = generateUniqueName();
+    String indexName1 = "IDX1_" + tableName;
+    String indexName2 = "IDX2_" + tableName;
+    try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+      String ddl =
+          "CREATE TABLE " + tableName + " "
+              + "(PK1 VARCHAR NOT NULL, C1 VARCHAR, COL BSON "
+              + " CONSTRAINT pk PRIMARY KEY(PK1)) "
+              + (this.columnEncoded ? "" : "COLUMN_ENCODED_BYTES=0");
+      String indexDdl1 = "CREATE INDEX " + indexName1 + " ON " + tableName + 
"(COL)";
+      String indexDdl2 = "CREATE INDEX " + indexName2 + " ON " + tableName + 
"(C1)";
+
+      conn.createStatement().execute(ddl);
+      try {
+        conn.createStatement().execute(indexDdl1);
+        fail("Should have seen SQLExceptionCode.BSON_IN_ROW_KEY");
+      } catch (SQLException e) {
+        assertEquals(SQLExceptionCode.BSON_IN_ROW_KEY.getErrorCode(), 
e.getErrorCode());
+      }
+
+      conn.createStatement().execute(indexDdl2);
+
+      String sample1 = getJsonString("json/sample_01.json");
+      String sample2 = getJsonString("json/sample_02.json");
+      String sample3 = getJsonString("json/sample_03.json");
+      BsonDocument bsonDocument1 = RawBsonDocument.parse(sample1);
+      BsonDocument bsonDocument2 = RawBsonDocument.parse(sample2);
+      BsonDocument bsonDocument3 = RawBsonDocument.parse(sample3);
+
+      upsertRows(conn, tableName, bsonDocument1, bsonDocument2, bsonDocument3);
+      conn.commit();
+      ResultSet rs = conn.createStatement().executeQuery("SELECT count(*) FROM 
" + indexName2);
+      assertTrue(rs.next());
+      assertEquals(3, rs.getInt(1));
+    }
+  }
+
   private static void upsertRowsWithBsonPkCol(Connection conn, String 
tableName,
                                               BsonDocument bsonDocument1,
                                               BsonDocument bsonDocument2,

Reply via email to