[Enhancement] Optimize parsing predicates with large number of CompoundPredicates (#63139)

Signed-off-by: shuming.li <ming.moriarty@gmail.com>
This commit is contained in:
shuming.li 2025-09-17 16:37:29 +08:00 committed by GitHub
parent 40f0eca6ed
commit 7c8a29660a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 703 additions and 4 deletions

View File

@ -3916,4 +3916,8 @@ public class Config extends ConfigBase {
@ConfField(mutable = true, comment = "Enable desensitize sql in query dump")
public static boolean enable_desensitize_query_dump = false;
@ConfField(mutable = true, comment = "The threshold to flatten compound predicate from deep tree to a balanced tree to " +
"avoid stack over flow")
public static int compound_predicate_flatten_threshold = 512;
}

View File

@ -62,6 +62,7 @@ public class CompoundPredicate extends Predicate {
if (e2 != null) {
children.add(e2);
}
incrDepth();
}
protected CompoundPredicate(CompoundPredicate other) {

View File

@ -210,6 +210,9 @@ public abstract class Expr extends TreeNode<Expr> implements ParseNode, Cloneabl
// passed to BE storage engine
private boolean isIndexOnlyFilter = false;
// depth is used to indicate the depth of the same operator in the tree
protected int depth = 0;
protected Expr() {
pos = NodePosition.ZERO;
type = Type.INVALID;
@ -246,6 +249,7 @@ public abstract class Expr extends TreeNode<Expr> implements ParseNode, Cloneabl
printSqlInParens = other.printSqlInParens;
children = Expr.cloneList(other.children);
hints = Lists.newArrayList(hints);
depth = other.depth;
}
@SuppressWarnings("unchecked")
@ -278,6 +282,15 @@ public abstract class Expr extends TreeNode<Expr> implements ParseNode, Cloneabl
return originType;
}
public int getDepth() {
return depth;
}
public void incrDepth() {
int curDepth = children.stream().mapToInt(Expr::getDepth).max().orElse(0);
this.depth = curDepth + 1;
}
private Optional<Expr> replaceLargeStringLiteralImpl() {
if (this instanceof LargeStringLiteral) {
return Optional.of(new StringLiteral(((LargeStringLiteral) this).getValue()));

View File

@ -524,6 +524,7 @@ import com.starrocks.sql.ast.warehouse.cngroup.CreateCnGroupStmt;
import com.starrocks.sql.ast.warehouse.cngroup.DropCnGroupStmt;
import com.starrocks.sql.ast.warehouse.cngroup.EnableDisableCnGroupStmt;
import com.starrocks.sql.common.PListCell;
import com.starrocks.sql.parser.rewriter.CompoundPredicateExprRewriter;
import com.starrocks.sql.util.EitherOr;
import com.starrocks.statistic.StatsConstants;
import com.starrocks.transaction.GtidGenerator;
@ -548,6 +549,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
@ -596,6 +598,8 @@ public class AstBuilder extends com.starrocks.sql.parser.StarRocksBaseVisitor<Pa
Lists.newArrayList(FunctionSet.SUBSTR, FunctionSet.SUBSTRING,
FunctionSet.FROM_UNIXTIME, FunctionSet.FROM_UNIXTIME_MS,
FunctionSet.STR2DATE);
// rewriter
private static final CompoundPredicateExprRewriter COMPOUND_PREDICATE_EXPR_REWRITER = new CompoundPredicateExprRewriter();
protected AstBuilder(long sqlMode) {
this(sqlMode, new IdentityHashMap<>());
@ -7243,11 +7247,50 @@ public class AstBuilder extends com.starrocks.sql.parser.StarRocksBaseVisitor<Pa
null, createPos(context));
}
private record LogicalBinaryNode(com.starrocks.sql.parser.StarRocksParser.LogicalBinaryContext context,
CompoundPredicate.Operator operator) {}
// Iteratively build a left-deep CompoundPredicate tree for LogicalBinaryContext,
// allowing each node to have its own operator, using LogicalBinaryNode for clarity.
// Corrected: Properly builds left-deep tree by pushing all contexts and operators,
// and reconstructing from the bottom up, preserving associativity.
private CompoundPredicate buildCompoundPredicateIterative(
com.starrocks.sql.parser.StarRocksParser.LogicalBinaryContext context) {
// Stack to store all contexts and their operators from leftmost to root
Deque<LogicalBinaryNode> nodeStack = new java.util.ArrayDeque<>();
com.starrocks.sql.parser.StarRocksParser.LogicalBinaryContext current = context;
// Traverse all the way down the left chain, pushing each context and operator
while (true) {
nodeStack.push(new LogicalBinaryNode(current, getLogicalBinaryOperator(current.operator)));
if (current.left instanceof com.starrocks.sql.parser.StarRocksParser.LogicalBinaryContext) {
current = (com.starrocks.sql.parser.StarRocksParser.LogicalBinaryContext) current.left;
} else {
break;
}
}
// The leftmost leaf expression
Expr result = (Expr) visit(current.left);
// Rebuild the tree from the bottom up (leftmost to root)
while (!nodeStack.isEmpty()) {
LogicalBinaryNode node = nodeStack.pop();
Expr right = (Expr) visit(node.context.right);
result = new CompoundPredicate(node.operator(), result, right, createPos(node.context()));
}
return (CompoundPredicate) result;
}
@Override
public ParseNode visitLogicalBinary(com.starrocks.sql.parser.StarRocksParser.LogicalBinaryContext context) {
Expr left = (Expr) visit(context.left);
Expr right = (Expr) visit(context.right);
return new CompoundPredicate(getLogicalBinaryOperator(context.operator), left, right, createPos(context));
if (Config.compound_predicate_flatten_threshold > 0) {
CompoundPredicate result = buildCompoundPredicateIterative(context);
return COMPOUND_PREDICATE_EXPR_REWRITER.rewrite(result);
} else {
Expr left = (Expr) visit(context.left);
Expr right = (Expr) visit(context.right);
return new CompoundPredicate(getLogicalBinaryOperator(context.operator), left, right, createPos(context));
}
}
private static CompoundPredicate.Operator getLogicalBinaryOperator(Token token) {

View File

@ -0,0 +1,104 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed 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
//
// https://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 com.starrocks.sql.parser.rewriter;
import com.starrocks.common.Config;
import com.starrocks.sql.ast.expression.CompoundPredicate;
import com.starrocks.sql.ast.expression.Expr;
import com.starrocks.sql.parser.NodePosition;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
/**
* Optimizes CompoundPredicate expressions by flattening and balancing long chains of
* AND/OR predicates into a balanced binary tree. This transformation helps avoid
* deep recursion and potential stack overflow for queries with very long AND/OR chains.
* The optimization is only applied if the predicate tree exceeds a certain depth threshold.
*
* Additionally, optimizes OR predicates where all children are equality predicates
* on the same column into an IN predicate for better performance.
*/
public class CompoundPredicateExprRewriter {
/**
* Rewrites a CompoundPredicate expression into a balanced binary tree if it is a long
* chain of AND/OR predicates of the same operator and exceeds the flatten threshold.
* Also rewrites OR chains of equality predicates on the same column into an IN predicate.
* @param input the input expression
* @return the rewritten (possibly balanced or IN-optimized) expression
*/
public Expr rewrite(Expr input) {
if (Config.compound_predicate_flatten_threshold <= 0 ||
input == null || !(input instanceof CompoundPredicate)) {
return input;
}
CompoundPredicate compoundPredicate = (CompoundPredicate) input;
if (compoundPredicate.getDepth() < Config.compound_predicate_flatten_threshold) {
return input;
}
CompoundPredicate.Operator op = compoundPredicate.getOp();
List<Expr> operands = new ArrayList<>();
for (Expr child : compoundPredicate.getChildren()) {
// Flatten left and right subtrees if they are the same operator
if (child instanceof CompoundPredicate && ((CompoundPredicate) child).getOp() == op) {
operands.addAll(flattenOperands(child, op));
} else {
Expr rewrittenLeft = rewrite(child);
operands.add(rewrittenLeft);
}
}
// TODO: Optimize OR predicates of the form: col = v1 OR col = v2 OR ... => col IN (v1, v2, ...)
return buildBalanced(operands, op, 0, operands.size() - 1);
}
/**
* Recursively builds a balanced binary tree from a list of operands.
*/
private Expr buildBalanced(List<Expr> ops, CompoundPredicate.Operator op, int l, int r) {
if (l == r) {
return ops.get(l);
}
int m = (l + r) >>> 1;
Expr leftExpr = buildBalanced(ops, op, l, m);
Expr rightExpr = buildBalanced(ops, op, m + 1, r);
return new CompoundPredicate(op, leftExpr, rightExpr, NodePosition.ZERO);
}
/**
* Flattens a left- or right-deep tree of CompoundPredicates with the same operator
* into a list of operands.
*/
private List<Expr> flattenOperands(Expr expr, CompoundPredicate.Operator op) {
List<Expr> operands = new ArrayList<>();
Deque<Expr> stack = new ArrayDeque<>();
stack.push(expr);
while (!stack.isEmpty()) {
Expr current = stack.pop();
if (current instanceof CompoundPredicate) {
CompoundPredicate cp = (CompoundPredicate) current;
if (cp.getOp() == op) {
for (Expr child : cp.getChildren()) {
stack.push(child);
}
continue;
}
}
operands.add(current);
}
return operands;
}
}

View File

@ -0,0 +1,267 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed 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
//
// https://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 com.starrocks.sql.parser.rewriter;
import com.starrocks.common.Config;
import com.starrocks.sql.ast.expression.BinaryPredicate;
import com.starrocks.sql.ast.expression.BinaryType;
import com.starrocks.sql.ast.expression.BoolLiteral;
import com.starrocks.sql.ast.expression.CompoundPredicate;
import com.starrocks.sql.ast.expression.Expr;
import com.starrocks.sql.ast.expression.IntLiteral;
import com.starrocks.sql.ast.expression.SlotRef;
import com.starrocks.sql.ast.expression.StringLiteral;
import com.starrocks.sql.ast.expression.TableName;
import com.starrocks.utframe.StarRocksTestBase;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class CompoundPredicateExprRewriterTest extends StarRocksTestBase {
private CompoundPredicateExprRewriter rewriter;
private int originalThreshold;
@BeforeEach
public void setUp() {
rewriter = new CompoundPredicateExprRewriter();
// Save original threshold and set a lower value for testing
originalThreshold = Config.compound_predicate_flatten_threshold;
Config.compound_predicate_flatten_threshold = 3;
}
@AfterEach
public void tearDown() {
// Restore original threshold
Config.compound_predicate_flatten_threshold = originalThreshold;
}
// Helper methods to create test expressions
private SlotRef createSlotRef(String columnName) {
return new SlotRef(new TableName("test_db", "test_table"), columnName);
}
private IntLiteral createIntLiteral(long value) {
return new IntLiteral(value);
}
private StringLiteral createStringLiteral(String value) {
return new StringLiteral(value);
}
private BoolLiteral createBoolLiteral(boolean value) {
return new BoolLiteral(value);
}
private BinaryPredicate createBinaryPredicate(Expr left, BinaryType op, Expr right) {
return new BinaryPredicate(op, left, right);
}
private CompoundPredicate createCompoundPredicate(CompoundPredicate.Operator op, Expr left, Expr right) {
return new CompoundPredicate(op, left, right);
}
/**
* Test that null input returns null
*/
@Test
public void testRewriteWithNullInput() {
Expr result = rewriter.rewrite(null);
assertNull(result);
}
/**
* Test that non-CompoundPredicate input returns unchanged
*/
@Test
public void testRewriteWithNonCompoundPredicate() {
SlotRef slotRef = createSlotRef("col1");
Expr result = rewriter.rewrite(slotRef);
assertSame(slotRef, result);
}
/**
* Test that compound predicate below threshold returns unchanged
*/
@Test
public void testRewriteWithShallowPredicate() {
SlotRef col1 = createSlotRef("col1");
IntLiteral val1 = createIntLiteral(1);
IntLiteral val2 = createIntLiteral(2);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.EQ, val1);
BinaryPredicate pred2 = createBinaryPredicate(col1, BinaryType.EQ, val2);
CompoundPredicate compound = createCompoundPredicate(CompoundPredicate.Operator.AND, pred1, pred2);
Expr result = rewriter.rewrite(compound);
assertSame(compound, result);
}
/**
* Test that compound predicate with threshold disabled (0 or negative) returns unchanged
*/
@Test
public void testRewriteWithDisabledThreshold() {
Config.compound_predicate_flatten_threshold = 0;
SlotRef col1 = createSlotRef("col1");
IntLiteral val1 = createIntLiteral(1);
IntLiteral val2 = createIntLiteral(2);
IntLiteral val3 = createIntLiteral(3);
IntLiteral val4 = createIntLiteral(4);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.EQ, val1);
BinaryPredicate pred2 = createBinaryPredicate(col1, BinaryType.EQ, val2);
BinaryPredicate pred3 = createBinaryPredicate(col1, BinaryType.EQ, val3);
BinaryPredicate pred4 = createBinaryPredicate(col1, BinaryType.EQ, val4);
CompoundPredicate compound = createCompoundPredicate(CompoundPredicate.Operator.AND,
createCompoundPredicate(CompoundPredicate.Operator.AND, pred1, pred2),
createCompoundPredicate(CompoundPredicate.Operator.AND, pred3, pred4));
Expr result = rewriter.rewrite(compound);
assertSame(compound, result);
}
/**
* Test that OR conversion fails when operators are not equality
*/
@Test
public void testOrToInPredicateConversion_NonEqualityOperators() {
SlotRef col1 = createSlotRef("col1");
IntLiteral val1 = createIntLiteral(1);
IntLiteral val2 = createIntLiteral(2);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.LT, val1);
BinaryPredicate pred2 = createBinaryPredicate(col1, BinaryType.GT, val2);
CompoundPredicate compound = createCompoundPredicate(CompoundPredicate.Operator.OR, pred1, pred2);
Expr result = rewriter.rewrite(compound);
// Should not convert to IN predicate, should return balanced tree
assertTrue(result instanceof CompoundPredicate);
CompoundPredicate resultCompound = (CompoundPredicate) result;
assertEquals(CompoundPredicate.Operator.OR, resultCompound.getOp());
}
/**
* Test that OR conversion fails when operands are not BinaryPredicates
*/
@Test
public void testOrToInPredicateConversion_NonBinaryPredicates() {
SlotRef col1 = createSlotRef("col1");
IntLiteral val1 = createIntLiteral(1);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.EQ, val1);
CompoundPredicate nestedOr = createCompoundPredicate(CompoundPredicate.Operator.OR,
createBinaryPredicate(col1, BinaryType.EQ, val1),
createBinaryPredicate(col1, BinaryType.EQ, val1));
CompoundPredicate compound = createCompoundPredicate(CompoundPredicate.Operator.OR, pred1, nestedOr);
Expr result = rewriter.rewrite(compound);
// Should not convert to IN predicate, should return balanced tree
assertTrue(result instanceof CompoundPredicate);
CompoundPredicate resultCompound = (CompoundPredicate) result;
assertEquals(CompoundPredicate.Operator.OR, resultCompound.getOp());
}
/**
* Test balanced tree building for AND predicates
*/
@Test
public void testBalancedTreeBuilding_AndPredicates() {
SlotRef col1 = createSlotRef("col1");
IntLiteral val1 = createIntLiteral(1);
IntLiteral val2 = createIntLiteral(2);
IntLiteral val3 = createIntLiteral(3);
IntLiteral val4 = createIntLiteral(4);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.EQ, val1);
BinaryPredicate pred2 = createBinaryPredicate(col1, BinaryType.EQ, val2);
BinaryPredicate pred3 = createBinaryPredicate(col1, BinaryType.EQ, val3);
BinaryPredicate pred4 = createBinaryPredicate(col1, BinaryType.EQ, val4);
// Create a deep AND chain that exceeds threshold
CompoundPredicate compound = createCompoundPredicate(CompoundPredicate.Operator.AND,
createCompoundPredicate(CompoundPredicate.Operator.AND, pred1, pred2),
createCompoundPredicate(CompoundPredicate.Operator.AND, pred3, pred4));
Expr result = rewriter.rewrite(compound);
assertTrue(result instanceof CompoundPredicate);
CompoundPredicate resultCompound = (CompoundPredicate) result;
assertEquals(CompoundPredicate.Operator.AND, resultCompound.getOp());
// Verify the tree is balanced by checking depth
assertTrue(resultCompound.getDepth() <= 3); // Should be balanced
}
/**
* Test balanced tree building for OR predicates (when IN conversion fails)
*/
@Test
public void testBalancedTreeBuilding_OrPredicates() {
SlotRef col1 = createSlotRef("col1");
SlotRef col2 = createSlotRef("col2");
IntLiteral val1 = createIntLiteral(1);
IntLiteral val2 = createIntLiteral(2);
IntLiteral val3 = createIntLiteral(3);
IntLiteral val4 = createIntLiteral(4);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.EQ, val1);
BinaryPredicate pred2 = createBinaryPredicate(col2, BinaryType.EQ, val2);
BinaryPredicate pred3 = createBinaryPredicate(col1, BinaryType.EQ, val3);
BinaryPredicate pred4 = createBinaryPredicate(col2, BinaryType.EQ, val4);
// Create a deep OR chain that exceeds threshold but can't be converted to IN
CompoundPredicate compound = createCompoundPredicate(CompoundPredicate.Operator.OR,
createCompoundPredicate(CompoundPredicate.Operator.OR, pred1, pred2),
createCompoundPredicate(CompoundPredicate.Operator.OR, pred3, pred4));
Expr result = rewriter.rewrite(compound);
assertTrue(result instanceof CompoundPredicate);
CompoundPredicate resultCompound = (CompoundPredicate) result;
assertEquals(CompoundPredicate.Operator.OR, resultCompound.getOp());
// Verify the tree is balanced by checking depth
assertTrue(resultCompound.getDepth() <= 3); // Should be balanced
}
/**
* Test that NOT operator is not processed for balancing
*/
@Test
public void testNotOperatorNotProcessed() {
SlotRef col1 = createSlotRef("col1");
IntLiteral val1 = createIntLiteral(1);
BinaryPredicate pred1 = createBinaryPredicate(col1, BinaryType.EQ, val1);
CompoundPredicate notPredicate = createCompoundPredicate(CompoundPredicate.Operator.NOT, pred1, null);
Expr result = rewriter.rewrite(notPredicate);
// NOT predicates should not be processed for balancing
assertSame(notPredicate, result);
}
}

View File

@ -0,0 +1,89 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed 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
//
// https://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 com.starrocks.sql.plan;
import com.starrocks.common.FeConstants;
import com.starrocks.sql.optimizer.rule.transformation.materialization.MVTestBase;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class InvalidPlanTest extends MVTestBase {
@BeforeAll
public static void beforeAll() throws Exception {
MVTestBase.beforeClass();
FeConstants.unitTestView = false;
}
@Test
public void testWithLargeBinaryPredicates() throws Exception {
starRocksAssert.withTable("CREATE TABLE `test_table` (\n" +
" `id` bigint(20) NOT NULL,\n" +
" `cargo_code` bigint(20) NOT NULL,\n" +
" `cargo_upc` varchar(100) NULL,\n" +
" `cargo_name` varchar(256) NULL,\n" +
" `item1_desc` varchar(256) NULL,\n" +
" `upc_nbr` varchar(64) NULL,\n" +
" `vendor_nbr` varchar(64) NULL,\n" +
" `division` varchar(64) NULL,\n" +
" `sub_division` varchar(64) NULL,\n" +
" `sub_division_en` varchar(200) NULL,\n" +
" `category` varchar(200) NULL,\n" +
" `category_cn` varchar(200) NULL,\n" +
" `category_en` varchar(200) NULL,\n" +
" `sub_category` varchar(200) NULL,\n" +
" `sub_category_cn` varchar(200) NULL,\n" +
" `sub_category_en` varchar(200) NULL,\n" +
" `node_code` varchar(200) NOT NULL,\n" +
" `node_type` varchar(200) NULL,\n" +
" `storage_area` varchar(256) NULL,\n" +
" `fragile_flag` int(11) NULL,\n" +
" `storehouse_sell_date` int(11) NULL,\n" +
" `custom_box_gauge` int(11) NULL,\n" +
" `minimum_order_quantity` int(11) NULL,\n" +
" `activation_status` int(11) NULL,\n" +
" `day_sold_out_flag` int(11) NULL,\n" +
" `new_category_flag` int(11) NULL,\n" +
" `updated_time` datetime NULL,\n" +
" `calc_node_code_cargo_code` varchar(200) NULL,\n" +
" `sell_by_date` int(11) NULL,\n" +
" `dc_storage_conditions_code` varchar(200) NULL,\n" +
" `dc_storage_conditions` varchar(256) NULL,\n" +
" `deleted_flag` int(11) NULL,\n" +
" `specification` varchar(255) NULL,\n" +
" `lead_time_day` int(11) NULL,\n" +
" `lead_time_hour` int(11) NULL,\n" +
" `next_status` int(11) NULL,\n" +
" `next_switch_time` datetime NULL,\n" +
" `cloud_status` int(11) NULL,\n" +
" `latest_activate_date` datetime NULL,\n" +
" `long_desc` varchar(256) NULL,\n" +
" `activate_effect_time` datetime NULL,\n" +
" `inactivate_effect_time` datetime NULL,\n" +
" `ti` int(11) NULL,\n" +
" `hi` int(11) NULL\n" +
") ENGINE=OLAP \n" +
"PRIMARY KEY(`id`)\n" +
"DISTRIBUTED BY HASH(`id`) BUCKETS 20 \n" +
"PROPERTIES (\n" +
"\"replication_num\" = \"1\"\n" +
");");
String sql = ReplayFromDumpTestBase.geContentFromFile("bugs/large_binary_predicate1.sql");
String plan = getFragmentPlan(sql);
PlanTestBase.assertContains(plan, " 0:OlapScanNode\n" +
" TABLE: test_table\n" +
" PREAGGREGATION: ON\n" +
" PREDICATES: 32: deleted_flag = 0, 2: cargo_code IN ");
}
}

View File

@ -149,8 +149,13 @@ public class ReplayFromDumpTestBase extends StarRocksTestBase {
}
protected static String getDumpInfoFromFile(String fileName) throws Exception {
String completeFileName = fileName + ".json";
return geContentFromFile(completeFileName);
}
public static String geContentFromFile(String completeFileName) throws Exception {
String path = Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResource("sql")).getPath();
File file = new File(path + "/" + fileName + ".json");
File file = new File(path + "/" + completeFileName);
StringBuilder sb = new StringBuilder();
String tempStr;
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long