Skip to content

Commit d7a8dd6

Browse files
committed
feat(cli): refactor CLI with AST-based parsing and client-side WHERE filtering
Major Refactoring: - Migrated from regex-based SQL parsing to Apache Calcite AST nodes - Created comprehensive AST node hierarchy (~1,430 lines) - Refactored 24 executor methods across 6 executors - Added structured exception hierarchy for better error handling WHERE Clause Filtering: - Implemented client-side WHERE filtering for Log table scans - Support all comparison operators: =, <>, >, <, >=, <= - Support logical operators: AND, OR with nested conditions - Smart column fetching: columnsToFetch = SELECT cols ∪ WHERE cols - Server-side projection optimization + client-side filtering - Post-filter projection to final SELECT columns Architecture: - Log tables: Server projection + client WHERE filtering - KV tables: Primary key lookup only (Lookup API, unchanged) Example Flow: SELECT name FROM events WHERE age > 25 AND status = 'active' 1. Extract WHERE columns: [age, status] 2. Calculate fetch: [name, age, status] 3. Server projection: fetch these 3 columns only 4. Client filter: age > 25 AND status = 'active' 5. Client project: [name] 6. Display: name column only Components: - FlussStatement: Base AST node for all SQL statements - FlussStatementParser: AST-based statement router - WhereClauseEvaluator: Predicate evaluation + column extraction - QueryExecutor: Smart projection + filtering orchestration - 6 specialized executors: DDL, DML, Query, Metadata, Cluster, ACL Testing & Coverage: - Added 201 comprehensive unit tests (all passing) - Test coverage: 70.4% instruction, 58.2% line - Removed 120 lines of dead code (ALTER SERVER TAG feature) Code Quality: - Java 8 compatible (replaced Map.of, List.of, etc.) - License headers compliant - Checkstyle & Spotless formatting applied - Proper error handling with typed exceptions This refactoring provides a solid foundation for future CLI enhancements and fixes the WHERE clause filtering bug for Log table queries.
1 parent 13df27f commit d7a8dd6

36 files changed

+6499
-2324
lines changed

fluss-cli/pom.xml

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -188,29 +188,23 @@
188188
<exclude>org.apache.logging.log4j:log4j-slf4j-impl</exclude>
189189
</excludes>
190190
</artifactSet>
191-
<transformers>
192-
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
193-
<mainClass>org.apache.fluss.cli.FlussCliMain</mainClass>
194-
</transformer>
195-
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
196-
</transformers>
197191
<filters>
198192
<filter>
199193
<artifact>*:*</artifact>
200194
<excludes>
201195
<exclude>META-INF/*.SF</exclude>
202-
<exclude>META-INF/*.DSA</exclude>
203-
<exclude>META-INF/*.RSA</exclude>
204-
<exclude>META-INF/NOTICE</exclude>
205-
<exclude>META-INF/NOTICE.txt</exclude>
206-
<exclude>META-INF/LICENSE</exclude>
207-
<exclude>META-INF/LICENSE.txt</exclude>
208-
<exclude>META-INF/maven/**</exclude>
209-
<exclude>log4j.properties</exclude>
210-
<exclude>log4j2.properties</exclude>
196+
<exclude>LICENSE</exclude>
197+
<exclude>NOTICE</exclude>
198+
<!-- Exclude files with forbidden licenses -->
199+
<exclude>javax/transaction/package.html</exclude>
211200
</excludes>
212201
</filter>
213202
</filters>
203+
<transformers>
204+
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
205+
<mainClass>org.apache.fluss.cli.FlussCliMain</mainClass>
206+
</transformer>
207+
</transformers>
214208
</configuration>
215209
</execution>
216210
</executions>

fluss-cli/src/main/java/org/apache/fluss/cli/command/SqlCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import java.io.File;
3030
import java.io.PrintWriter;
31+
import java.nio.charset.StandardCharsets;
3132
import java.nio.file.Files;
3233
import java.util.concurrent.Callable;
3334

@@ -74,7 +75,8 @@ public Integer call() throws Exception {
7475
SqlExecutor executor = new SqlExecutor(connectionManager, out);
7576

7677
if (sqlFile != null) {
77-
String sql = Files.readString(sqlFile.toPath());
78+
String sql =
79+
new String(Files.readAllBytes(sqlFile.toPath()), StandardCharsets.UTF_8);
7880
executor.executeSql(sql);
7981
} else if (sqlStatement != null) {
8082
executor.executeSql(sqlStatement);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.exception;
19+
20+
/** Exception thrown when a database is not found. */
21+
public class DatabaseNotFoundException extends SqlExecutionException {
22+
23+
public DatabaseNotFoundException(String databaseName) {
24+
super("Database not found: " + databaseName);
25+
}
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.exception;
19+
20+
/** Exception thrown when query execution fails. */
21+
public class QueryExecutionException extends SqlExecutionException {
22+
23+
public QueryExecutionException(String message) {
24+
super(message);
25+
}
26+
27+
public QueryExecutionException(String message, Throwable cause) {
28+
super(message, cause);
29+
}
30+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.exception;
19+
20+
import org.apache.fluss.exception.FlussException;
21+
22+
/** Base exception for SQL execution errors in the CLI. */
23+
public class SqlExecutionException extends FlussException {
24+
25+
public SqlExecutionException(String message) {
26+
super(message);
27+
}
28+
29+
public SqlExecutionException(String message, Throwable cause) {
30+
super(message, cause);
31+
}
32+
33+
public SqlExecutionException(Throwable cause) {
34+
super(cause);
35+
}
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.exception;
19+
20+
import org.apache.fluss.exception.FlussException;
21+
22+
/** Exception thrown when SQL parsing fails. */
23+
public class SqlParseException extends FlussException {
24+
25+
public SqlParseException(String message) {
26+
super(message);
27+
}
28+
29+
public SqlParseException(String message, Throwable cause) {
30+
super(message, cause);
31+
}
32+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.fluss.cli.exception;
19+
20+
/** Exception thrown when a table is not found. */
21+
public class TableNotFoundException extends SqlExecutionException {
22+
23+
public TableNotFoundException(String tablePath) {
24+
super("Table not found: " + tablePath);
25+
}
26+
}

fluss-cli/src/main/java/org/apache/fluss/cli/sql/CalciteSqlParser.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public SqlStatementType classifyRawStatement(String sql) {
118118
return SqlStatementType.SHOW_TABLES;
119119
} else if (upper.startsWith("SHOW SERVERS")) {
120120
return SqlStatementType.SHOW_SERVERS;
121-
} else if (upper.startsWith("USING ")) {
121+
} else if (upper.startsWith("USE ")) {
122122
return SqlStatementType.USE_DATABASE;
123123
} else if (upper.startsWith("SHOW CREATE TABLE")) {
124124
return SqlStatementType.SHOW_CREATE_TABLE;
@@ -151,8 +151,6 @@ public SqlStatementType classifyRawStatement(String sql) {
151151
return SqlStatementType.REBALANCE_CLUSTER;
152152
} else if (upper.startsWith("CANCEL REBALANCE")) {
153153
return SqlStatementType.CANCEL_REBALANCE;
154-
} else if (upper.startsWith("ALTER SERVER TAG")) {
155-
return SqlStatementType.ALTER_SERVER_TAG;
156154
} else if (upper.startsWith("DESCRIBE ") || upper.startsWith("DESC ")) {
157155
return SqlStatementType.DESCRIBE_TABLE;
158156
} else if (upper.startsWith("ALTER TABLE")) {
@@ -229,7 +227,6 @@ public enum SqlStatementType {
229227
REBALANCE_CLUSTER,
230228
SHOW_REBALANCE,
231229
CANCEL_REBALANCE,
232-
ALTER_SERVER_TAG,
233230
UNKNOWN
234231
}
235232
}

0 commit comments

Comments
 (0)