-
Notifications
You must be signed in to change notification settings - Fork 8.9k
feature: support Oracle Batch Insert #7675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 2.x
Are you sure you want to change the base?
Changes from 6 commits
336b9bc
210147e
f98bd61
aaa1589
35e518d
6af3533
8e68f03
1a91697
342daf7
8d50934
82d32e1
495185a
ecd619b
8ccd886
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By default, only the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, we only support batch insert of multiple columns (same columns) in a single table. We will continue to support this in the future. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
/* | ||
* 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.seata.sqlparser.druid.oracle; | ||
|
||
import com.alibaba.druid.sql.ast.SQLExpr; | ||
import com.alibaba.druid.sql.ast.SQLStatement; | ||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; | ||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; | ||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr; | ||
import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr; | ||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr; | ||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; | ||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; | ||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; | ||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; | ||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor; | ||
import org.apache.seata.common.util.CollectionUtils; | ||
import org.apache.seata.sqlparser.SQLInsertRecognizer; | ||
import org.apache.seata.sqlparser.SQLType; | ||
import org.apache.seata.sqlparser.struct.NotPlaceholderExpr; | ||
import org.apache.seata.sqlparser.struct.Null; | ||
import org.apache.seata.sqlparser.struct.SqlMethodExpr; | ||
import org.apache.seata.sqlparser.struct.SqlSequenceExpr; | ||
import org.apache.seata.sqlparser.util.ColumnUtils; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.List; | ||
|
||
/** | ||
* Oracle Multi Insert Recognizer for INSERT ALL statements | ||
*/ | ||
public class OracleMultiInsertRecognizer extends BaseOracleRecognizer implements SQLInsertRecognizer { | ||
|
||
private final OracleMultiInsertStatement ast; | ||
|
||
public OracleMultiInsertRecognizer(String originalSQL, SQLStatement ast) { | ||
super(originalSQL); | ||
this.ast = (OracleMultiInsertStatement) ast; | ||
} | ||
|
||
@Override | ||
public SQLType getSQLType() { | ||
return SQLType.INSERT; | ||
} | ||
|
||
@Override | ||
public String getTableAlias() { | ||
// Oracle Multi Insert usually only one table is involved, take the table alias of the first inserted item | ||
if (!CollectionUtils.isEmpty(ast.getEntries())) { | ||
OracleMultiInsertStatement.Entry firstEntry = ast.getEntries().get(0); | ||
maple525866 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if (firstEntry instanceof OracleMultiInsertStatement.InsertIntoClause) { | ||
OracleMultiInsertStatement.InsertIntoClause insertClause = | ||
(OracleMultiInsertStatement.InsertIntoClause) firstEntry; | ||
if (insertClause.getTableSource() != null) { | ||
return insertClause.getTableSource().getAlias(); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public String getTableName() { | ||
// Oracle Multi Insert usually only one table is involved, take the table alias of the first inserted item | ||
if (!CollectionUtils.isEmpty(ast.getEntries())) { | ||
OracleMultiInsertStatement.Entry firstEntry = ast.getEntries().get(0); | ||
if (firstEntry instanceof OracleMultiInsertStatement.InsertIntoClause) { | ||
OracleMultiInsertStatement.InsertIntoClause insertClause = | ||
(OracleMultiInsertStatement.InsertIntoClause) firstEntry; | ||
if (insertClause.getTableSource() != null) { | ||
StringBuilder sb = new StringBuilder(); | ||
OracleOutputVisitor visitor = new OracleOutputVisitor(sb) { | ||
@Override | ||
public boolean visit(SQLExprTableSource x) { | ||
printTableSourceExpr(x.getExpr()); | ||
return false; | ||
} | ||
}; | ||
visitor.visit(insertClause.getTableSource()); | ||
return sb.toString(); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public boolean insertColumnsIsEmpty() { | ||
if (!CollectionUtils.isEmpty(ast.getEntries())) { | ||
OracleMultiInsertStatement.Entry firstEntry = ast.getEntries().get(0); | ||
maple525866 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if (firstEntry instanceof OracleMultiInsertStatement.InsertIntoClause) { | ||
OracleMultiInsertStatement.InsertIntoClause insertClause = | ||
(OracleMultiInsertStatement.InsertIntoClause) firstEntry; | ||
return CollectionUtils.isEmpty(insertClause.getColumns()); | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
@Override | ||
public List<String> getInsertColumns() { | ||
if (!CollectionUtils.isEmpty(ast.getEntries())) { | ||
OracleMultiInsertStatement.Entry firstEntry = ast.getEntries().get(0); | ||
if (firstEntry instanceof OracleMultiInsertStatement.InsertIntoClause) { | ||
OracleMultiInsertStatement.InsertIntoClause insertClause = | ||
(OracleMultiInsertStatement.InsertIntoClause) firstEntry; | ||
if (!CollectionUtils.isEmpty(insertClause.getColumns())) { | ||
List<SQLExpr> columnSQLExprs = insertClause.getColumns(); | ||
List<String> list = new ArrayList<>(columnSQLExprs.size()); | ||
for (SQLExpr expr : columnSQLExprs) { | ||
if (expr instanceof SQLIdentifierExpr) { | ||
list.add(((SQLIdentifierExpr) expr).getName()); | ||
} else { | ||
wrapSQLParsingException(expr); | ||
} | ||
} | ||
return list; | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) { | ||
List<List<Object>> allRows = new ArrayList<>(); | ||
|
||
if (!CollectionUtils.isEmpty(ast.getEntries())) { | ||
for (OracleMultiInsertStatement.Entry entry : ast.getEntries()) { | ||
if (entry instanceof OracleMultiInsertStatement.InsertIntoClause) { | ||
maple525866 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
OracleMultiInsertStatement.InsertIntoClause insertClause = | ||
(OracleMultiInsertStatement.InsertIntoClause) entry; | ||
|
||
if (!CollectionUtils.isEmpty(insertClause.getValuesList())) { | ||
for (SQLInsertStatement.ValuesClause valuesClause : insertClause.getValuesList()) { | ||
List<SQLExpr> exprs = valuesClause.getValues(); | ||
List<Object> row = new ArrayList<>(exprs.size()); | ||
allRows.add(row); | ||
|
||
for (int i = 0, len = exprs.size(); i < len; i++) { | ||
SQLExpr expr = exprs.get(i); | ||
if (expr instanceof SQLNullExpr) { | ||
row.add(Null.get()); | ||
} else if (expr instanceof SQLValuableExpr) { | ||
row.add(((SQLValuableExpr) expr).getValue()); | ||
} else if (expr instanceof SQLVariantRefExpr) { | ||
row.add(((SQLVariantRefExpr) expr).getName()); | ||
} else if (expr instanceof SQLMethodInvokeExpr) { | ||
row.add(SqlMethodExpr.get()); | ||
} else if (expr instanceof SQLSequenceExpr) { | ||
SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr; | ||
String sequence = sequenceExpr.getSequence().getSimpleName(); | ||
String function = sequenceExpr.getFunction().name; | ||
row.add(new SqlSequenceExpr(sequence, function)); | ||
} else { | ||
if (primaryKeyIndex.contains(i)) { | ||
wrapSQLParsingException(expr); | ||
} | ||
row.add(NotPlaceholderExpr.get()); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return allRows; | ||
} | ||
|
||
@Override | ||
public List<String> getInsertParamsValue() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public List<String> getDuplicateKeyUpdate() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public List<String> getInsertColumnsUnEscape() { | ||
List<String> insertColumns = getInsertColumns(); | ||
return ColumnUtils.delEscape(insertColumns, getDbType()); | ||
} | ||
|
||
@Override | ||
protected SQLStatement getAst() { | ||
return ast; | ||
} | ||
|
||
@Override | ||
public boolean isSqlSyntaxSupports() { | ||
return true; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.