YoWuwuuuw commented on code in PR #7675:
URL: https://github.com/apache/incubator-seata/pull/7675#discussion_r2390334634


##########
sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryImpl.java:
##########
@@ -72,6 +74,10 @@ public List<SQLRecognizer> create(String sql, String dbType) 
{
                 recognizer = recognizerHolder.getDeleteRecognizer(sql, 
sqlStatement);
             } else if (sqlStatement instanceof SQLSelectStatement) {
                 recognizer = 
recognizerHolder.getSelectForUpdateRecognizer(sql, sqlStatement);
+            } else if (sqlStatement instanceof OracleMultiInsertStatement) {
+                // Use specialized methods to handle Oracle bulk inserts
+                recognizer =
+                        ((OracleOperateRecognizerHolder) 
recognizerHolder).getMultiInsertRecognizer(sql, sqlStatement);

Review Comment:
   OracleMultiInsertStatement has two syntaxes: `Insert All` and `Insert 
First`. If your implementation class does not support `Insert First` syntax, 
you should throw NotSupportYetException in `isSqlSyntaxSupports()` of 
BaseOracleRecognizer.



##########
sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleMultiInsertRecognizer.java:
##########


Review Comment:
   By default, only the `insert all` syntax of Oracle Batch Insert and the same 
column situation is supported. The same effect can be achieved by adding 
multiple values ​​clauses to a normal insert. Are there plans to support more 
in the future?



##########
sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleMultiInsertRecognizer.java:
##########
@@ -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);
+            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);

Review Comment:
   Same as above.



##########
sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleMultiInsertRecognizer.java:
##########
@@ -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);

Review Comment:
   There may be different table names or aliases. If you directly use the first 
entry to get it, I think this will cause some problems.



##########
sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/oracle/OracleMultiInsertRecognizer.java:
##########
@@ -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);
+            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);
+            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) {

Review Comment:
   `OracleMultiInsertStatement.Entry` is divided into `ConditionalInsertClause` 
and `InsertIntoClause`. If it is the former, will some data be missed?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to