From 43894ccee9ffd8c10ababc7b89d8754a0f82218a Mon Sep 17 00:00:00 2001
From: Palash Chauhan
Date: Fri, 23 Jan 2026 15:33:53 -0800
Subject: [PATCH 1/3] PHOENIX-7753 : Allow uncovered index creation on tables
with relaxed conditional TTL
---
.../apache/phoenix/schema/MetaDataClient.java | 11 ++-
.../schema/ConditionalTTLExpressionTest.java | 74 ++++++++++++-------
2 files changed, 57 insertions(+), 28 deletions(-)
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 edb38da970c..4795c39dcf5 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
@@ -2529,7 +2529,11 @@ private PTable createTableInternal(CreateTableStatement statement, byte[][] spli
} else {
ttlFromHierarchy = checkAndGetTTLFromHierarchy(parent, tableName);
if (!ttlFromHierarchy.equals(TTL_EXPRESSION_NOT_DEFINED)) {
- ttlFromHierarchy.validateTTLOnCreate(connection, statement, parent, tableProps);
+ if (parent.hasConditionalTTL() && !parent.isStrictTTL()) {
+ ttlFromHierarchy = TTL_EXPRESSION_NOT_DEFINED;
+ } else {
+ ttlFromHierarchy.validateTTLOnCreate(connection, statement, parent, tableProps);
+ }
}
}
@@ -6413,7 +6417,10 @@ private boolean evaluateStmtProperties(MetaProperties metaProperties,
}
if (metaProperties.getTTL() != table.getTTLExpression()) {
TTLExpression newTTL = metaProperties.getTTL();
- newTTL.validateTTLOnAlter(connection, table);
+ boolean isStrictTTL = metaProperties.isStrictTTL() != null ? metaProperties.isStrictTTL : true;
+ if (!(newTTL instanceof ConditionalTTLExpression) || isStrictTTL) {
+ newTTL.validateTTLOnAlter(connection, table);
+ }
metaPropertiesEvaluated.setTTL(getCompatibleTTLExpression(metaProperties.getTTL(),
table.getType(), table.getViewType(), table.getName().toString()));
changingPhoenixTableProperty = true;
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
index b82dd5e72d8..b81a9998130 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
@@ -55,7 +55,7 @@
public class ConditionalTTLExpressionTest extends BaseConnectionlessQueryTest {
- private static void assertConditonTTL(Connection conn, String tableName, String ttlExpr)
+ private static void assertConditionTTL(Connection conn, String tableName, String ttlExpr)
throws SQLException {
TTLExpression expected = new ConditionalTTLExpression(ttlExpr);
assertTTL(conn, tableName, expected);
@@ -105,7 +105,7 @@ public void testBasicExpression() throws SQLException {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
String query = String.format("SELECT count(*) from %s where k1 > 3", tableName);
validateScan(conn, tableName, query, ttl, false, Lists.newArrayList("col1"));
}
@@ -174,17 +174,17 @@ public void testSingleNonDefaultColumnFamilyIsAllowed() throws SQLException {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
// create global index
String indexName = "I_" + generateUniqueName();
ddl = String.format("create index %s on %s (col2) include(col1)", indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
// create local index
indexName = "L_" + generateUniqueName();
ddl = String.format("create local index %s on %s (col2) include(col1)", indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
}
}
@@ -198,23 +198,23 @@ public void testDefaultColumnFamily() throws SQLException {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
// create view
String viewName = "GV_" + generateUniqueName();
ddl = String.format("create view %s (col3 varchar) as select * from %s where k1 = 2",
viewName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, viewName, ttl);
+ assertConditionTTL(conn, viewName, ttl);
// create global index
String indexName = "I_" + generateUniqueName();
ddl = String.format("create index %s on %s (col2) include(col1)", indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
// create local index
indexName = "L_" + generateUniqueName();
ddl = String.format("create local index %s on %s (col2) include(col1)", indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
}
}
@@ -301,7 +301,7 @@ public void testMultipleColumnFamilyNotAllowedOnAddColumn3() throws SQLException
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
// add a new column in a different column family
String alterDDL = String.format("alter table %s add A.col3 varchar", tableName);
try {
@@ -369,7 +369,7 @@ public void testNullExpression() throws SQLException {
String ddl = String.format(ddlTemplate, tableName, ttl);
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
String query = String.format("SELECT count(*) from %s", tableName);
validateScan(conn, tableName, query, ttl, false, Lists.newArrayList("col1", "col2"));
}
@@ -387,14 +387,14 @@ public void testBooleanColumn() throws SQLException {
try (Connection conn = DriverManager.getConnection(getUrl())) {
String ddl = String.format(ddlTemplate, tableName, ttl);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
query = String.format("SELECT k1, k2 from %s where (k1,k2) IN ((1,2), (3,4))", tableName);
validateScan(conn, tableName, query, ttl, false, Lists.newArrayList("expired"));
ddl = String.format(indexTemplate, indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
// validate the scan on index
query = String.format("SELECT count(*) from %s", tableName);
@@ -411,7 +411,7 @@ public void testNot() throws SQLException {
String ddl = String.format(ddlTemplate, tableName, ttl);
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
}
}
@@ -425,7 +425,7 @@ public void testPhoenixRowTimestamp() throws SQLException {
String query;
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
query = String.format("select col1 from %s where k1 = 7 AND k2 > 12", tableName);
validateScan(conn, tableName, query, ttl, false, Lists.newArrayList("col1"));
}
@@ -441,7 +441,7 @@ public void testBooleanCaseExpression() throws SQLException {
String ddl = String.format(ddlTemplate, tableName, ttl);
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, expectedTTLExpr);
+ assertConditionTTL(conn, tableName, expectedTTLExpr);
}
}
@@ -460,7 +460,7 @@ public void testCondTTLOnTopLevelView() throws SQLException {
ddl = String.format(viewTemplate, viewName, tableName, ttl);
conn.createStatement().execute(ddl);
assertTTL(conn, tableName, TTL_EXPRESSION_NOT_DEFINED);
- assertConditonTTL(conn, viewName, ttl);
+ assertConditionTTL(conn, viewName, ttl);
String query = String.format("select k3 from %s", viewName);
validateScan(conn, viewName, query, ttl, false, Lists.newArrayList("k2", "k3"));
}
@@ -487,11 +487,11 @@ public void testCondTTLOnMultiLevelView() throws SQLException {
conn.createStatement().execute(ddl);
assertTTL(conn, tableName, TTL_EXPRESSION_NOT_DEFINED);
assertTTL(conn, parentView, TTL_EXPRESSION_NOT_DEFINED);
- assertConditonTTL(conn, childView, ttl);
+ assertConditionTTL(conn, childView, ttl);
// create an index on child view
ddl = String.format(indexOnChildTemplate, indexName, childView);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
}
}
@@ -505,7 +505,7 @@ public void testInListTTLExpr() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl())) {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
query = String.format("select col1 from %s where id IN ('abc', 'fff')", tableName);
validateScan(conn, tableName, query, ttl, false, Lists.newArrayList("col1", "col2"));
}
@@ -524,10 +524,10 @@ public void testPartialIndex() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl())) {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
ddl = String.format(indexTemplate, indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
query = String.format("select col3 from %s where col1 > 60", tableName);
validateScan(conn, tableName, query, ttl, true,
Lists.newArrayList("0:col2", "0:col3", "0:col4"));
@@ -535,7 +535,7 @@ public void testPartialIndex() throws Exception {
}
@Test
- public void testUncoveredIndex() throws Exception {
+ public void testUncoveredIndexStrictTTL() throws Exception {
String ddlTemplate = "create table %s (id varchar not null primary key, "
+ "col1 integer, col2 integer, col3 double, col4 varchar) TTL = '%s'";
String tableName = generateUniqueName();
@@ -546,7 +546,7 @@ public void testUncoveredIndex() throws Exception {
try (Connection conn = DriverManager.getConnection(getUrl())) {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
ddl = String.format(indexTemplate, indexName, tableName);
try {
conn.createStatement().execute(ddl);
@@ -557,10 +557,28 @@ public void testUncoveredIndex() throws Exception {
indexTemplate = "create uncovered index %s on %s (col4, col2) ";
ddl = String.format(indexTemplate, indexName, tableName);
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, indexName, ttl);
+ assertConditionTTL(conn, indexName, ttl);
}
}
+ @Test
+ public void testUncoveredIndexRelaxedTTL() throws Exception {
+ String ddlTemplate = "create table %s (id varchar not null primary key, "
+ + "col1 integer, col2 integer, col3 double, col4 varchar) TTL = '%s', IS_STRICT_TTL=false";
+ String tableName = generateUniqueName();
+ String indexTemplate = "create uncovered index %s on %s (col1) ";
+ String indexName = generateUniqueName();
+ String ttl = "col2 > 100 AND col4='expired'";
+ try (Connection conn = DriverManager.getConnection(getUrl())) {
+ String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
+ conn.createStatement().execute(ddl);
+ assertConditionTTL(conn, tableName, ttl);
+ ddl = String.format(indexTemplate, indexName, tableName);
+ conn.createStatement().execute(ddl);
+ assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
+ }
+ }
+
@Test
public void testCreatingIndexWithMissingExprCols() throws Exception {
String ddlTemplate = "create table %s (id varchar not null primary key, "
@@ -602,6 +620,10 @@ public void testSettingCondTTLOnTableWithIndexWithMissingExprCols() throws Excep
} catch (SQLException e) {
assertTrue(e.getCause() instanceof ColumnNotFoundException);
}
+ // relaxed ttl
+ ddl = String.format("alter table %s set TTL = '%s', IS_STRICT_TTL = false", tableName, retainSingleQuotes(ttl));
+ conn.createStatement().execute(ddl);
+ assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
}
}
@@ -615,7 +637,7 @@ public void testScanColumns() throws Exception {
String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
try (Connection conn = DriverManager.getConnection(getUrl())) {
conn.createStatement().execute(ddl);
- assertConditonTTL(conn, tableName, ttl);
+ assertConditionTTL(conn, tableName, ttl);
String query = String.format("select * from %s where k1 > 3", tableName);
// select * so all columns should be read
validateScan(conn, tableName, query, ttl, false, Collections.EMPTY_LIST);
From 14ec5e087c21dc64f303803e7f4cf592e79c8956 Mon Sep 17 00:00:00 2001
From: Palash Chauhan
Date: Fri, 23 Jan 2026 15:44:17 -0800
Subject: [PATCH 2/3] spotless and more tests
---
.../apache/phoenix/schema/MetaDataClient.java | 15 +++---
.../schema/ConditionalTTLExpressionTest.java | 54 +++++++++++++------
2 files changed, 45 insertions(+), 24 deletions(-)
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 4795c39dcf5..481b44bfa9e 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
@@ -2529,11 +2529,11 @@ private PTable createTableInternal(CreateTableStatement statement, byte[][] spli
} else {
ttlFromHierarchy = checkAndGetTTLFromHierarchy(parent, tableName);
if (!ttlFromHierarchy.equals(TTL_EXPRESSION_NOT_DEFINED)) {
- if (parent.hasConditionalTTL() && !parent.isStrictTTL()) {
- ttlFromHierarchy = TTL_EXPRESSION_NOT_DEFINED;
- } else {
- ttlFromHierarchy.validateTTLOnCreate(connection, statement, parent, tableProps);
- }
+ if (parent.hasConditionalTTL() && !parent.isStrictTTL()) {
+ ttlFromHierarchy = TTL_EXPRESSION_NOT_DEFINED;
+ } else {
+ ttlFromHierarchy.validateTTLOnCreate(connection, statement, parent, tableProps);
+ }
}
}
@@ -6417,9 +6417,10 @@ private boolean evaluateStmtProperties(MetaProperties metaProperties,
}
if (metaProperties.getTTL() != table.getTTLExpression()) {
TTLExpression newTTL = metaProperties.getTTL();
- boolean isStrictTTL = metaProperties.isStrictTTL() != null ? metaProperties.isStrictTTL : true;
+ boolean isStrictTTL =
+ metaProperties.isStrictTTL() != null ? metaProperties.isStrictTTL : table.isStrictTTL();
if (!(newTTL instanceof ConditionalTTLExpression) || isStrictTTL) {
- newTTL.validateTTLOnAlter(connection, table);
+ newTTL.validateTTLOnAlter(connection, table);
}
metaPropertiesEvaluated.setTTL(getCompatibleTTLExpression(metaProperties.getTTL(),
table.getType(), table.getViewType(), table.getName().toString()));
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
index b81a9998130..7e6fa9128f2 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
@@ -561,23 +561,23 @@ public void testUncoveredIndexStrictTTL() throws Exception {
}
}
- @Test
- public void testUncoveredIndexRelaxedTTL() throws Exception {
- String ddlTemplate = "create table %s (id varchar not null primary key, "
- + "col1 integer, col2 integer, col3 double, col4 varchar) TTL = '%s', IS_STRICT_TTL=false";
- String tableName = generateUniqueName();
- String indexTemplate = "create uncovered index %s on %s (col1) ";
- String indexName = generateUniqueName();
- String ttl = "col2 > 100 AND col4='expired'";
- try (Connection conn = DriverManager.getConnection(getUrl())) {
- String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
- conn.createStatement().execute(ddl);
- assertConditionTTL(conn, tableName, ttl);
- ddl = String.format(indexTemplate, indexName, tableName);
- conn.createStatement().execute(ddl);
- assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
- }
+ @Test
+ public void testUncoveredIndexRelaxedTTL() throws Exception {
+ String ddlTemplate = "create table %s (id varchar not null primary key, "
+ + "col1 integer, col2 integer, col3 double, col4 varchar) TTL = '%s', IS_STRICT_TTL=false";
+ String tableName = generateUniqueName();
+ String indexTemplate = "create uncovered index %s on %s (col1) ";
+ String indexName = generateUniqueName();
+ String ttl = "col2 > 100 AND col4='expired'";
+ try (Connection conn = DriverManager.getConnection(getUrl())) {
+ String ddl = String.format(ddlTemplate, tableName, retainSingleQuotes(ttl));
+ conn.createStatement().execute(ddl);
+ assertConditionTTL(conn, tableName, ttl);
+ ddl = String.format(indexTemplate, indexName, tableName);
+ conn.createStatement().execute(ddl);
+ assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
}
+ }
@Test
public void testCreatingIndexWithMissingExprCols() throws Exception {
@@ -621,7 +621,27 @@ public void testSettingCondTTLOnTableWithIndexWithMissingExprCols() throws Excep
assertTrue(e.getCause() instanceof ColumnNotFoundException);
}
// relaxed ttl
- ddl = String.format("alter table %s set TTL = '%s', IS_STRICT_TTL = false", tableName, retainSingleQuotes(ttl));
+ ddl = String.format("alter table %s set TTL = '%s', IS_STRICT_TTL = false", tableName,
+ retainSingleQuotes(ttl));
+ conn.createStatement().execute(ddl);
+ assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
+ }
+ }
+
+ @Test
+ public void testSettingCondTTLOnTableWithRelaxedTTLAndUncoveredIndex() throws Exception {
+ String ddlTemplate = "create table %s (id varchar not null primary key, "
+ + "col1 integer, col2 integer, col3 double, col4 varchar) IS_STRICT_TTL = false";
+ String tableName = generateUniqueName();
+ String indexTemplate = "create uncovered index %s on %s (col1)";
+ String indexName = generateUniqueName();
+ String ttl = "col2 > 100 AND col4='expired'";
+ try (Connection conn = DriverManager.getConnection(getUrl())) {
+ String ddl = String.format(ddlTemplate, tableName);
+ conn.createStatement().execute(ddl);
+ ddl = String.format(indexTemplate, indexName, tableName);
+ conn.createStatement().execute(ddl);
+ ddl = String.format("alter table %s set TTL = '%s'", tableName, retainSingleQuotes(ttl));
conn.createStatement().execute(ddl);
assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
}
From 2940014e5603785bde9d34b8bb8bb0d9fe17a087 Mon Sep 17 00:00:00 2001
From: Palash Chauhan
Date: Thu, 29 Jan 2026 14:38:37 -0800
Subject: [PATCH 3/3] review fixes
---
.../phoenix/schema/ConditionalTTLExpression.java | 12 +++++++++---
.../apache/phoenix/schema/LiteralTTLExpression.java | 2 +-
.../org/apache/phoenix/schema/MetaDataClient.java | 10 ++++++----
.../org/apache/phoenix/schema/TTLExpression.java | 8 +++++---
.../phoenix/schema/ConditionalTTLExpressionTest.java | 8 ++++++--
5 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/ConditionalTTLExpression.java b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/ConditionalTTLExpression.java
index a5ec9263df3..d504cdff27b 100644
--- a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/ConditionalTTLExpression.java
+++ b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/ConditionalTTLExpression.java
@@ -18,6 +18,7 @@
package org.apache.phoenix.schema;
import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN;
+import static org.apache.phoenix.schema.PTable.IndexType.UNCOVERED_GLOBAL;
import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.NON_ENCODED_QUALIFIERS;
import static org.apache.phoenix.schema.PTableType.CDC;
import static org.apache.phoenix.schema.PTableType.VIEW;
@@ -181,17 +182,22 @@ public void validateTTLOnCreate(PhoenixConnection conn, CreateTableStatement cre
/**
* @param table TABLE | VIEW referenced in ALTER statement
*/
- public void validateTTLOnAlter(PhoenixConnection conn, PTable table) throws SQLException {
+ public void validateTTLOnAlter(PhoenixConnection conn, PTable table, boolean isStrictTTL)
+ throws SQLException {
// first validate the expression on the entity being changed
validateTTLExpression(conn, table, null);
for (PTable index : table.getIndexes()) {
try {
- if (CDCUtil.isCDCIndex(index)) {
+ if (
+ CDCUtil.isCDCIndex(index)
+ || (!isStrictTTL && UNCOVERED_GLOBAL.equals(index.getIndexType()))
+ ) {
// CDC index doesn't inherit ConditionTTL expression
+ // skip validation if index is uncovered and TTL is not strict
continue;
}
- // verify that the new expression is covered by all the existing indexes
+ // verify that the new expression is covered by all the existing covered indexes
buildExpression(conn, index, table);
} catch (ColumnNotFoundException | ColumnFamilyNotFoundException e) {
throw new SQLException(
diff --git a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/LiteralTTLExpression.java b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/LiteralTTLExpression.java
index 6890ee121cc..d791dcdd449 100644
--- a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/LiteralTTLExpression.java
+++ b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/LiteralTTLExpression.java
@@ -89,7 +89,7 @@ public void validateTTLOnCreate(PhoenixConnection conn, CreateTableStatement cre
}
@Override
- public void validateTTLOnAlter(PhoenixConnection connection, PTable table) {
+ public void validateTTLOnAlter(PhoenixConnection connection, PTable table, boolean isStrictTTL) {
}
@Override
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 481b44bfa9e..0852edef9da 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
@@ -129,6 +129,7 @@
import static org.apache.phoenix.schema.PTable.EncodedCQCounter.NULL_COUNTER;
import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN;
import static org.apache.phoenix.schema.PTable.ImmutableStorageScheme.SINGLE_CELL_ARRAY_WITH_OFFSETS;
+import static org.apache.phoenix.schema.PTable.IndexType.UNCOVERED_GLOBAL;
import static org.apache.phoenix.schema.PTable.QualifierEncodingScheme.NON_ENCODED_QUALIFIERS;
import static org.apache.phoenix.schema.PTable.ViewType.MAPPED;
import static org.apache.phoenix.schema.PTableType.CDC;
@@ -2529,7 +2530,10 @@ private PTable createTableInternal(CreateTableStatement statement, byte[][] spli
} else {
ttlFromHierarchy = checkAndGetTTLFromHierarchy(parent, tableName);
if (!ttlFromHierarchy.equals(TTL_EXPRESSION_NOT_DEFINED)) {
- if (parent.hasConditionalTTL() && !parent.isStrictTTL()) {
+ if (
+ UNCOVERED_GLOBAL.equals(indexType) && parent.hasConditionalTTL()
+ && !parent.isStrictTTL()
+ ) {
ttlFromHierarchy = TTL_EXPRESSION_NOT_DEFINED;
} else {
ttlFromHierarchy.validateTTLOnCreate(connection, statement, parent, tableProps);
@@ -6419,9 +6423,7 @@ private boolean evaluateStmtProperties(MetaProperties metaProperties,
TTLExpression newTTL = metaProperties.getTTL();
boolean isStrictTTL =
metaProperties.isStrictTTL() != null ? metaProperties.isStrictTTL : table.isStrictTTL();
- if (!(newTTL instanceof ConditionalTTLExpression) || isStrictTTL) {
- newTTL.validateTTLOnAlter(connection, table);
- }
+ newTTL.validateTTLOnAlter(connection, table, isStrictTTL);
metaPropertiesEvaluated.setTTL(getCompatibleTTLExpression(metaProperties.getTTL(),
table.getType(), table.getViewType(), table.getName().toString()));
changingPhoenixTableProperty = true;
diff --git a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/TTLExpression.java b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/TTLExpression.java
index ef4b65a0f0a..313660cef9d 100644
--- a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/TTLExpression.java
+++ b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/TTLExpression.java
@@ -44,10 +44,12 @@ void validateTTLOnCreate(PhoenixConnection conn, CreateTableStatement create, PT
/**
* Validate the TTL expression on ALTER [TABLE | VIEW]
- * @param connection Phoenix connection
- * @param table PTable of the entity being changed
+ * @param connection Phoenix connection
+ * @param table PTable of the entity being changed
+ * @param isStrictTTL True if the TTL being set is strict
*/
- void validateTTLOnAlter(PhoenixConnection connection, PTable table) throws SQLException;
+ void validateTTLOnAlter(PhoenixConnection connection, PTable table, boolean isStrictTTL)
+ throws SQLException;
/**
* Compile the TTL expression so that it can be evaluated against of a row of cells
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
index 7e6fa9128f2..5de46ead0c8 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/ConditionalTTLExpressionTest.java
@@ -623,8 +623,12 @@ public void testSettingCondTTLOnTableWithIndexWithMissingExprCols() throws Excep
// relaxed ttl
ddl = String.format("alter table %s set TTL = '%s', IS_STRICT_TTL = false", tableName,
retainSingleQuotes(ttl));
- conn.createStatement().execute(ddl);
- assertTTL(conn, indexName, TTL_EXPRESSION_NOT_DEFINED);
+ try {
+ conn.createStatement().execute(ddl);
+ fail("Should have thrown ColumnNotFoundException");
+ } catch (SQLException e) {
+ assertTrue(e.getCause() instanceof ColumnNotFoundException);
+ }
}
}