[improvement][fix](insert)(replay) support SHOW LAST INSERT stmt and fix json replay bug (#8355)
1. support SHOW LAST INSERT
In the current implementation, the insert operation returns a json string to describe the result information
of the insert. But this information is in the session track field of the mysql protocol,
and it is difficult to obtain programmatically.
Therefore, I provide a new syntax `show last insert` to explicitly obtain the result of the latest insert operation,
and return a normal query result set to facilitate the user to obtain the result information of the insert.
2. the `ReturnRows` field in fe.audit.log of insert operation will be set to the loaded row num of the insert.
3. Fix a bug described in #8354
This commit is contained in:
@ -2876,6 +2876,11 @@ show_param ::=
|
||||
{:
|
||||
RESULT = new ShowTableCreationStmt(db, parser.wild);
|
||||
:}
|
||||
/* show last insert */
|
||||
| KW_LAST KW_INSERT
|
||||
{:
|
||||
RESULT = new ShowLastInsertStmt();
|
||||
:}
|
||||
;
|
||||
|
||||
opt_tmp ::=
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
// 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.analysis;
|
||||
|
||||
import org.apache.doris.catalog.Column;
|
||||
import org.apache.doris.catalog.ScalarType;
|
||||
import org.apache.doris.qe.ShowResultSetMetaData;
|
||||
|
||||
// SHOW LAST INSERT
|
||||
public class ShowLastInsertStmt extends ShowStmt {
|
||||
private static final ShowResultSetMetaData META_DATA =
|
||||
ShowResultSetMetaData.builder()
|
||||
.addColumn(new Column("TransactionId", ScalarType.createVarchar(128)))
|
||||
.addColumn(new Column("Label", ScalarType.createVarchar(128)))
|
||||
.addColumn(new Column("Database", ScalarType.createVarchar(128)))
|
||||
.addColumn(new Column("Table", ScalarType.createVarchar(128)))
|
||||
.addColumn(new Column("TransactionStatus", ScalarType.createVarchar(64)))
|
||||
.addColumn(new Column("LoadedRows", ScalarType.createVarchar(128)))
|
||||
.addColumn(new Column("FilteredRows", ScalarType.createVarchar(128)))
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void analyze(Analyzer analyzer) {
|
||||
// No need to check priv here. Bacause `show last insert` can only view
|
||||
// the insert result of current session.
|
||||
// So if user does not have priv to insert, than there is no result to show.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSql() {
|
||||
return "SHOW INSERT RESULT";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toSql();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShowResultSetMetaData getMetaData() {
|
||||
return META_DATA;
|
||||
}
|
||||
}
|
||||
@ -33,6 +33,7 @@ import org.apache.doris.resource.Tag;
|
||||
import org.apache.doris.thrift.TResourceInfo;
|
||||
import org.apache.doris.thrift.TUniqueId;
|
||||
import org.apache.doris.transaction.TransactionEntry;
|
||||
import org.apache.doris.transaction.TransactionStatus;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
@ -134,6 +135,21 @@ public class ConnectContext {
|
||||
// The FE ip current connected
|
||||
private String currentConnectedFEIp = "";
|
||||
|
||||
private InsertResult insertResult;
|
||||
|
||||
public void setOrUpdateInsertResult(long txnId, String label, String db, String tbl,
|
||||
TransactionStatus txnStatus, long loadedRows, int filteredRows) {
|
||||
if (isTxnModel() && insertResult != null) {
|
||||
insertResult.updateResult(txnStatus, loadedRows, filteredRows);
|
||||
} else {
|
||||
insertResult = new InsertResult(txnId, label, db, tbl, txnStatus, loadedRows, filteredRows);
|
||||
}
|
||||
}
|
||||
|
||||
public InsertResult getInsertResult() {
|
||||
return insertResult;
|
||||
}
|
||||
|
||||
public static ConnectContext get() {
|
||||
return threadLocalInfo.get();
|
||||
}
|
||||
@ -544,4 +560,5 @@ public class ConnectContext {
|
||||
public String getQueryIdentifier() {
|
||||
return "stmt[" + stmtId + ", " + DebugUtil.printId(queryId) + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
// 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.qe;
|
||||
|
||||
import org.apache.doris.transaction.TransactionStatus;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// Save the result of last insert operation.
|
||||
// So that user can view it by executing SHOW LAST INSERT.
|
||||
public class InsertResult {
|
||||
public long txnId;
|
||||
public String label;
|
||||
public String db;
|
||||
public String tbl;
|
||||
public TransactionStatus txnStatus;
|
||||
public long loadedRows;
|
||||
public long filteredRows;
|
||||
|
||||
public InsertResult(long txnId, String label, String db, String tbl, TransactionStatus txnStatus,
|
||||
long loadedRows, long filteredRows) {
|
||||
this.txnId = txnId;
|
||||
this.label = label;
|
||||
this.db = db;
|
||||
this.tbl = tbl;
|
||||
this.txnStatus = txnStatus;
|
||||
this.loadedRows = loadedRows;
|
||||
this.filteredRows = filteredRows;
|
||||
}
|
||||
|
||||
public void updateResult(TransactionStatus txnStatus, long loadedRows, int filteredRows) {
|
||||
this.txnStatus = txnStatus;
|
||||
this.loadedRows += loadedRows;
|
||||
this.filteredRows += filteredRows;
|
||||
}
|
||||
|
||||
public List<String> toRow() {
|
||||
List<String> row = Lists.newArrayList();
|
||||
row.add(String.valueOf(txnId));
|
||||
row.add(label);
|
||||
row.add(db);
|
||||
row.add(tbl);
|
||||
row.add(txnStatus.name());
|
||||
row.add(String.valueOf(loadedRows));
|
||||
row.add(String.valueOf(filteredRows));
|
||||
return row;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1000,10 +1000,11 @@ public class SessionVariable implements Serializable, Writable {
|
||||
field.set(this, root.get(attr.name()));
|
||||
break;
|
||||
case "int":
|
||||
field.set(this, root.get(attr.name()));
|
||||
// root.get(attr.name()) always return Long type, so need to convert it.
|
||||
field.set(this, Integer.valueOf(root.get(attr.name()).toString()));
|
||||
break;
|
||||
case "long":
|
||||
field.set(this, root.get(attr.name()));
|
||||
field.set(this, (Long) root.get(attr.name()));
|
||||
break;
|
||||
case "float":
|
||||
field.set(this, root.get(attr.name()));
|
||||
@ -1107,3 +1108,4 @@ public class SessionVariable implements Serializable, Writable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@ import org.apache.doris.analysis.ShowFrontendsStmt;
|
||||
import org.apache.doris.analysis.ShowFunctionsStmt;
|
||||
import org.apache.doris.analysis.ShowGrantsStmt;
|
||||
import org.apache.doris.analysis.ShowIndexStmt;
|
||||
import org.apache.doris.analysis.ShowLastInsertStmt;
|
||||
import org.apache.doris.analysis.ShowLoadProfileStmt;
|
||||
import org.apache.doris.analysis.ShowLoadStmt;
|
||||
import org.apache.doris.analysis.ShowLoadWarningsStmt;
|
||||
@ -157,6 +158,7 @@ import org.apache.doris.system.Backend;
|
||||
import org.apache.doris.system.SystemInfoService;
|
||||
import org.apache.doris.thrift.TUnit;
|
||||
import org.apache.doris.transaction.GlobalTransactionMgr;
|
||||
import org.apache.doris.transaction.TransactionStatus;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
@ -165,7 +167,6 @@ import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.apache.doris.transaction.TransactionStatus;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@ -330,6 +331,8 @@ public class ShowExecutor {
|
||||
handleShowColumnStats();
|
||||
} else if (stmt instanceof ShowTableCreationStmt) {
|
||||
handleShowTableCreation();
|
||||
} else if (stmt instanceof ShowLastInsertStmt) {
|
||||
handleShowLastInsert();
|
||||
} else {
|
||||
handleEmtpy();
|
||||
}
|
||||
@ -2108,4 +2111,17 @@ public class ShowExecutor {
|
||||
resultSet = new ShowResultSet(showMetaData, resultRowSet);
|
||||
}
|
||||
|
||||
private void handleShowLastInsert() {
|
||||
ShowLastInsertStmt showStmt = (ShowLastInsertStmt) stmt;
|
||||
List<List<String>> resultRowSet = Lists.newArrayList();
|
||||
if (ConnectContext.get() != null) {
|
||||
InsertResult insertResult = ConnectContext.get().getInsertResult();
|
||||
if (insertResult != null) {
|
||||
resultRowSet.add(insertResult.toRow());
|
||||
}
|
||||
}
|
||||
ShowResultSetMetaData showMetaData = showStmt.getMetaData();
|
||||
resultSet = new ShowResultSet(showMetaData, resultRowSet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1375,6 +1375,13 @@ public class StmtExecutor implements ProfileWriter {
|
||||
sb.append("}");
|
||||
|
||||
context.getState().setOk(loadedRows, filteredRows, sb.toString());
|
||||
|
||||
// set insert result in connection context,
|
||||
// so that user can use `show insert result` to get info of the last insert operation.
|
||||
context.setOrUpdateInsertResult(txnId, label, insertStmt.getDb(), insertStmt.getTbl(),
|
||||
txnStatus, loadedRows, filteredRows);
|
||||
// update it, so that user can get loaded rows in fe.audit.log
|
||||
context.updateReturnRows((int) loadedRows);
|
||||
}
|
||||
|
||||
private void handleUnsupportedStmt() {
|
||||
|
||||
Reference in New Issue
Block a user