diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index e849529332..b26019aa3e 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -115,7 +115,40 @@ statementBase constraint #addConstraint | ALTER TABLE table=multipartIdentifier DROP CONSTRAINT constraintName=errorCapturingIdentifier #dropConstraint - | SHOW CONSTRAINTS FROM table=multipartIdentifier #showConstraint + | SHOW CONSTRAINTS FROM table=multipartIdentifier #showConstraint + | unsupportedStatement #unsupported + ; + +unsupportedStatement + : SET identifier AS DEFAULT STORAGE VAULT #setDefaultStorageVault + | SET PROPERTY (FOR user=identifierOrText)? propertyItemList #setUserProperties + | SET (GLOBAL | LOCAL | SESSION)? identifier EQ (expression | DEFAULT) #setSystemVariableWithType + | SET variable #setSystemVariableWithoutType + | SET (CHAR SET | CHARSET) (charsetName=identifierOrText | DEFAULT) #setCharset + | SET NAMES EQ expression #setNames + | SET (GLOBAL | LOCAL | SESSION)? TRANSACTION + ( transactionAccessMode + | isolationLevel + | transactionAccessMode COMMA isolationLevel + | isolationLevel COMMA transactionAccessMode) #setTransaction + | SET NAMES (charsetName=identifierOrText | DEFAULT) (COLLATE collateName=identifierOrText | DEFAULT)? #setCollate + | SET PASSWORD (FOR userIdentify)? EQ (STRING_LITERAL | (PASSWORD LEFT_PAREN STRING_LITERAL RIGHT_PAREN)) #setPassword + | SET LDAP_ADMIN_PASSWORD EQ (STRING_LITERAL | (PASSWORD LEFT_PAREN STRING_LITERAL RIGHT_PAREN)) #setLdapAdminPassword + | USE (catalog=identifier DOT)? database=identifier #useDatabase + | USE ((catalog=identifier DOT)? database=identifier)? ATSIGN cluster=identifier #useCloudCluster + ; + +variable + : (ATSIGN ATSIGN (GLOBAL | LOCAL | SESSION)?)? identifier EQ (expression | DEFAULT) #setSystemVariable + | ATSIGN identifier EQ expression #setUserVariable + ; + +transactionAccessMode + : READ (ONLY | WRITE) + ; + +isolationLevel + : ISOLATION LEVEL ((READ UNCOMMITTED) | (READ COMMITTED) | (REPEATABLE READ) | (SERIALIZABLE)) ; constraint diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/exceptions/MustFallbackException.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/exceptions/MustFallbackException.java new file mode 100644 index 0000000000..83a4f17fc6 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/exceptions/MustFallbackException.java @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.nereids.exceptions; + +/** + * Exception for unsupported command to run in Nereids. + */ +public class MustFallbackException extends RuntimeException { + public MustFallbackException(String msg) { + super(String.format("Must fallback to legacy planner, because %s", msg)); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 239d898f02..e44609d75f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -189,6 +189,7 @@ import org.apache.doris.nereids.DorisParser.TimestampaddContext; import org.apache.doris.nereids.DorisParser.TimestampdiffContext; import org.apache.doris.nereids.DorisParser.TypeConstructorContext; import org.apache.doris.nereids.DorisParser.UnitIdentifierContext; +import org.apache.doris.nereids.DorisParser.UnsupportedContext; import org.apache.doris.nereids.DorisParser.UpdateAssignmentContext; import org.apache.doris.nereids.DorisParser.UpdateAssignmentSeqContext; import org.apache.doris.nereids.DorisParser.UpdateContext; @@ -379,6 +380,7 @@ import org.apache.doris.nereids.trees.plans.commands.ResumeMTMVCommand; import org.apache.doris.nereids.trees.plans.commands.ShowConstraintsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateProcedureCommand; import org.apache.doris.nereids.trees.plans.commands.ShowProcedureStatusCommand; +import org.apache.doris.nereids.trees.plans.commands.UnsupportedCommand; import org.apache.doris.nereids.trees.plans.commands.UpdateCommand; import org.apache.doris.nereids.trees.plans.commands.info.AlterMTMVInfo; import org.apache.doris.nereids.trees.plans.commands.info.AlterMTMVPropertyInfo; @@ -3492,4 +3494,9 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { FuncNameInfo procedureName = new FuncNameInfo(nameParts); return ParserUtils.withOrigin(ctx, () -> new ShowCreateProcedureCommand(procedureName)); } + + @Override + public Object visitUnsupported(UnsupportedContext ctx) { + return UnsupportedCommand.INSTANCE; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java index bf4741cff4..3db3ffa3d9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java @@ -152,5 +152,7 @@ public enum PlanType { SHOW_PROCEDURE_COMMAND, SHOW_CREATE_PROCEDURE_COMMAND, CREATE_VIEW_COMMAND, - ALTER_VIEW_COMMAND + ALTER_VIEW_COMMAND, + + UNSUPPORTED_COMMAND } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsupportedCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsupportedCommand.java new file mode 100644 index 0000000000..10025d8822 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UnsupportedCommand.java @@ -0,0 +1,46 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.nereids.trees.plans.commands; + +import org.apache.doris.nereids.exceptions.MustFallbackException; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.StmtExecutor; + +/** + * all Nereids' unsupported command + */ +public class UnsupportedCommand extends Command implements NoForward { + + public static UnsupportedCommand INSTANCE = new UnsupportedCommand(); + + public UnsupportedCommand() { + super(PlanType.UNSUPPORTED_COMMAND); + } + + @Override + public void run(ConnectContext ctx, StmtExecutor executor) throws Exception { + throw new MustFallbackException("unsupported command"); + } + + @Override + public R accept(PlanVisitor visitor, C context) { + return visitor.visitUnsupportedCommand(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java index d23cb855af..f82dd1a794 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/CommandVisitor.java @@ -42,6 +42,7 @@ import org.apache.doris.nereids.trees.plans.commands.ResumeMTMVCommand; import org.apache.doris.nereids.trees.plans.commands.ShowConstraintsCommand; import org.apache.doris.nereids.trees.plans.commands.ShowCreateProcedureCommand; import org.apache.doris.nereids.trees.plans.commands.ShowProcedureStatusCommand; +import org.apache.doris.nereids.trees.plans.commands.UnsupportedCommand; import org.apache.doris.nereids.trees.plans.commands.UpdateCommand; import org.apache.doris.nereids.trees.plans.commands.insert.BatchInsertIntoTableCommand; import org.apache.doris.nereids.trees.plans.commands.insert.InsertIntoTableCommand; @@ -166,4 +167,8 @@ public interface CommandVisitor { default R visitAlterViewCommand(AlterViewCommand alterViewCommand, C context) { return visitCommand(alterViewCommand, context); } + + default R visitUnsupportedCommand(UnsupportedCommand unsupportedCommand, C context) { + return visitCommand(unsupportedCommand, context); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index 755fecc326..3bdfe73848 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -129,6 +129,7 @@ import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.nereids.NereidsPlanner; import org.apache.doris.nereids.PlanProcess; import org.apache.doris.nereids.StatementContext; +import org.apache.doris.nereids.exceptions.MustFallbackException; import org.apache.doris.nereids.exceptions.ParseException; import org.apache.doris.nereids.glue.LogicalPlanAdapter; import org.apache.doris.nereids.minidump.MinidumpUtils; @@ -555,7 +556,9 @@ public class StmtExecutor { .getLogicalPlan()).isExternalTableSink(); } boolean forceFallback = isInsertCommand && !isExternalTableInsert && !context.isTxnModel(); - if (e instanceof NereidsException && !context.getSessionVariable().enableFallbackToOriginalPlanner + if (e instanceof NereidsException + && !(((NereidsException) e).getException() instanceof MustFallbackException) + && !context.getSessionVariable().enableFallbackToOriginalPlanner && !forceFallback) { LOG.warn("Analyze failed. {}", context.getQueryIdentifier(), e); context.getState().setError(e.getMessage()); @@ -674,9 +677,14 @@ public class StmtExecutor { } try { ((Command) logicalPlan).run(context, this); + } catch (MustFallbackException e) { + if (LOG.isDebugEnabled()) { + LOG.debug("Command({}) process failed.", originStmt.originStmt, e); + } + throw new NereidsException("Command(" + originStmt.originStmt + ") process failed.", e); } catch (QueryStateException e) { if (LOG.isDebugEnabled()) { - LOG.debug("Command(" + originStmt.originStmt + ") process failed.", e); + LOG.debug("Command({}) process failed.", originStmt.originStmt, e); } context.setState(e.getQueryState()); throw new NereidsException("Command(" + originStmt.originStmt + ") process failed", @@ -684,7 +692,7 @@ public class StmtExecutor { } catch (UserException e) { // Return message to info client what happened. if (LOG.isDebugEnabled()) { - LOG.debug("Command(" + originStmt.originStmt + ") process failed.", e); + LOG.debug("Command({}) process failed.", originStmt.originStmt, e); } context.getState().setError(e.getMysqlErrorCode(), e.getMessage()); throw new NereidsException("Command (" + originStmt.originStmt + ") process failed", @@ -692,7 +700,7 @@ public class StmtExecutor { } catch (Exception e) { // Maybe our bug if (LOG.isDebugEnabled()) { - LOG.debug("Command (" + originStmt.originStmt + ") process failed.", e); + LOG.debug("Command({}) process failed.", originStmt.originStmt, e); } context.getState().setError(ErrorCode.ERR_UNKNOWN_ERROR, e.getMessage()); throw new NereidsException("Command (" + originStmt.originStmt + ") process failed.",