Skip to content

Commit b8eb186

Browse files
authored
[fix](prepared statement)Fix prepareCommand couldn't get fields metadata bug. (#49206)
### What problem does this PR solve? Fix prepareCommand couldn't get fields metadata bug. In the prepare stage, Doris should return the output column info to the client, this is required by mysql api definition. Issue Number: close #xxx Related PR: #xxx Problem Summary: ### Release note None ### Check List (For Author) - Test <!-- At least one of them must be included. --> - [ ] Regression test - [ ] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason <!-- Add your reason? --> - Behavior changed: - [ ] No. - [ ] Yes. <!-- Explain the behavior change --> - Does this need documentation? - [ ] No. - [ ] Yes. <!-- Add document PR link here. eg: apache/doris-website#1214 --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label <!-- Add branch pick label that this PR should merge into -->
1 parent 08da6a7 commit b8eb186

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+466
-44
lines changed

fe/fe-core/src/main/java/org/apache/doris/nereids/StatementContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ public enum TableFrom {
214214

215215
private boolean privChecked;
216216

217+
private boolean prepareStage = false;
218+
217219
public StatementContext() {
218220
this(ConnectContext.get(), null, 0);
219221
}
@@ -774,4 +776,12 @@ public boolean isPrivChecked() {
774776
public void setPrivChecked(boolean privChecked) {
775777
this.privChecked = privChecked;
776778
}
779+
780+
public void setPrepareStage(boolean isPrepare) {
781+
this.prepareStage = isPrepare;
782+
}
783+
784+
public boolean isPrepareStage() {
785+
return prepareStage;
786+
}
777787
}

fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,11 @@ public Expression visitPlaceholder(Placeholder placeholder, ExpressionRewriteCon
623623
}
624624
Expression realExpr = context.cascadesContext.getStatementContext()
625625
.getIdToPlaceholderRealExpr().get(placeholder.getPlaceholderId());
626+
// In prepare stage, the realExpr has not been set, set it to NullLiteral so that we can plan the statement
627+
// and get the output slots in prepare stage, which is required by Mysql api definition.
628+
if (realExpr == null && context.cascadesContext.getStatementContext().isPrepareStage()) {
629+
realExpr = new NullLiteral();
630+
}
626631
return visit(realExpr, context);
627632
}
628633

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/Command.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@
2828
import org.apache.doris.nereids.trees.plans.Plan;
2929
import org.apache.doris.nereids.trees.plans.PlanType;
3030
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
31+
import org.apache.doris.qe.CommonResultSet.CommonResultSetMetaData;
3132
import org.apache.doris.qe.ConnectContext;
33+
import org.apache.doris.qe.ResultSetMetaData;
3234
import org.apache.doris.qe.StmtExecutor;
3335

3436
import com.google.common.collect.ImmutableList;
37+
import com.google.common.collect.Lists;
3538

3639
import java.util.List;
3740
import java.util.Optional;
@@ -130,4 +133,10 @@ public void verifyCommandSupported(ConnectContext ctx) throws DdlException {
130133
// see checkStmtSupported() in fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
131134
// override this method if the command is not supported in cloud mode
132135
protected void checkSupportedInCloudMode(ConnectContext ctx) throws DdlException {}
136+
137+
// For prepare statement only, used to get the result set metadata in prepare stage.
138+
// Subclass need to override this to return correct metadata.
139+
public ResultSetMetaData getResultSetMetaData() {
140+
return new CommonResultSetMetaData(Lists.newArrayList());
141+
}
133142
}

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ExecuteCommand.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
6565

6666
@Override
6767
public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
68+
StatementContext statementContext = ctx.getStatementContext();
69+
statementContext.setPrepareStage(false);
6870
PreparedStatementContext preparedStmtCtx = ctx.getPreparedStementContext(stmtName);
6971
if (null == preparedStmtCtx) {
7072
throw new AnalysisException(

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/HelpCommand.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exc
125125
return resultSet;
126126
}
127127

128+
@Override
129+
public ShowResultSetMetaData getMetaData() {
130+
return ShowResultSetMetaData.builder().build();
131+
}
132+
128133
@Override
129134
public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
130135
return visitor.visitHelpCommand(this, context);

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/PrepareCommand.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,24 @@
1818
package org.apache.doris.nereids.trees.plans.commands;
1919

2020
import org.apache.doris.analysis.StmtType;
21+
import org.apache.doris.catalog.Column;
2122
import org.apache.doris.mysql.MysqlCommand;
23+
import org.apache.doris.nereids.StatementContext;
2224
import org.apache.doris.nereids.trees.expressions.Placeholder;
25+
import org.apache.doris.nereids.trees.expressions.Slot;
26+
import org.apache.doris.nereids.trees.expressions.SlotReference;
2327
import org.apache.doris.nereids.trees.plans.PlanType;
2428
import org.apache.doris.nereids.trees.plans.commands.insert.InsertIntoTableCommand;
2529
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
2630
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
31+
import org.apache.doris.nereids.types.DataType;
2732
import org.apache.doris.qe.ConnectContext;
2833
import org.apache.doris.qe.OriginStatement;
2934
import org.apache.doris.qe.PreparedStatementContext;
35+
import org.apache.doris.qe.ResultSetMetaData;
3036
import org.apache.doris.qe.StmtExecutor;
3137

38+
import com.google.common.collect.Lists;
3239
import org.apache.logging.log4j.LogManager;
3340
import org.apache.logging.log4j.Logger;
3441

@@ -99,6 +106,18 @@ public List<String> getLabels() {
99106
@Override
100107
public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
101108
List<String> labels = getLabels();
109+
StatementContext statementContext = ctx.getStatementContext();
110+
statementContext.setPrepareStage(true);
111+
List<Slot> slots;
112+
if (logicalPlan instanceof Command) {
113+
ResultSetMetaData md = ((Command) logicalPlan).getResultSetMetaData();
114+
slots = Lists.newArrayList();
115+
for (Column c : md.getColumns()) {
116+
slots.add(new SlotReference(c.getName(), DataType.fromCatalogType(c.getType())));
117+
}
118+
} else {
119+
slots = executor.planPrepareStatementSlots();
120+
}
102121
// register prepareStmt
103122
if (LOG.isDebugEnabled()) {
104123
LOG.debug("add prepared statement {}, isBinaryProtocol {}",
@@ -111,7 +130,7 @@ public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
111130
ctx.addPreparedStatementContext(name,
112131
new PreparedStatementContext(this, ctx, ctx.getStatementContext(), name));
113132
if (ctx.getCommand() == MysqlCommand.COM_STMT_PREPARE && !ctx.isProxy()) {
114-
executor.sendStmtPrepareOK(Integer.parseInt(name), labels);
133+
executor.sendStmtPrepareOK(Integer.parseInt(name), labels, slots);
115134
}
116135
}
117136

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowAnalyzeCommand.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ private ShowResultSet handleShowAnalyze() {
206206
analysisInfo.catalogId, analysisInfo.dbId, analysisInfo.tblId, e.getMessage());
207207
}
208208
}
209-
return new ShowResultSet(META_DATA, resultRows);
209+
return new ShowResultSet(getMetaData(), resultRows);
210+
}
211+
212+
@Override
213+
public ShowResultSetMetaData getMetaData() {
214+
return META_DATA;
210215
}
211216

212217
@Override

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowAuthorsCommand.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,14 @@ public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
5050
return visitor.visitShowAuthorsCommand(this, context);
5151
}
5252

53+
@Override
54+
public ShowResultSetMetaData getMetaData() {
55+
return META_DATA;
56+
}
57+
5358
@Override
5459
public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
5560
List<List<String>> rowSet = Lists.newArrayList();
56-
return new ShowResultSet(META_DATA, rowSet);
61+
return new ShowResultSet(getMetaData(), rowSet);
5762
}
5863
}

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowBackupCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public ShowBackupCommand(String dbName, Expression where) {
7979
/**
8080
* get metadata
8181
*/
82-
private ShowResultSetMetaData getMetaData() {
82+
public ShowResultSetMetaData getMetaData() {
8383
ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder();
8484
for (String title : TITLE_NAMES) {
8585
builder.addColumn(new Column(title, ScalarType.STRING));

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCharsetCommand.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public ShowCharsetCommand() {
4646
super(PlanType.SHOW_CHARSET_COMMAND);
4747
}
4848

49+
@Override
50+
public ShowResultSetMetaData getMetaData() {
51+
return CHARSET_META_DATA;
52+
}
53+
4954
@Override
5055
public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exception {
5156
List<List<String>> rows = Lists.newArrayList();
@@ -57,7 +62,7 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exc
5762
row.add("4");
5863
rows.add(row);
5964

60-
return new ShowResultSet(CHARSET_META_DATA, rows);
65+
return new ShowResultSet(getMetaData(), rows);
6166
}
6267

6368
@Override

0 commit comments

Comments
 (0)