From bbebda0e27febe641c01c68a9e8c19645ae53f31 Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Fri, 4 Nov 2022 10:03:33 -0400 Subject: [PATCH 01/13] MyBatis Long GC issue fixed in 3.5.6.1 --- pom.xml | 2 +- .../scripting/xmltags/XMLScriptBuilder.java | 100 ++++++++++-------- .../apache/ibatis/session/Configuration.java | 13 +++ 3 files changed, 70 insertions(+), 45 deletions(-) diff --git a/pom.xml b/pom.xml index 5d177eca669..2ae174317b6 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ mybatis - 3.5.6 + 3.5.6.1 jar mybatis diff --git a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java index 2d10d81e3e9..90e002a4687 100644 --- a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java +++ b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java @@ -1,11 +1,11 @@ -/** - * Copyright 2009-2019 the original author or authors. +/* + * Copyright 2009-2022 the original author or authors. * * Licensed 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 + * https://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, @@ -81,28 +81,47 @@ protected MixedSqlNode parseDynamicTags(XNode node) { XNode child = node.newXNode(children.item(i)); if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) { String data = child.getStringBody(""); - TextSqlNode textSqlNode = new TextSqlNode(data); - if (textSqlNode.isDynamic()) { - contents.add(textSqlNode); - isDynamic = true; - } else { - contents.add(new StaticTextSqlNode(data)); + if(configuration.containsSqlNode(data)) { + SqlNode sqlNode = configuration.getSqlNode(data); + if(sqlNode instanceof TextSqlNode) { + isDynamic = true; + } + contents.add(sqlNode); + }else { + TextSqlNode textSqlNode = new TextSqlNode(data); + if (textSqlNode.isDynamic()) { + contents.add(textSqlNode); + isDynamic = true; + configuration.addSqlNode(data, textSqlNode); + } else { + StaticTextSqlNode staticTextSqlNode = new StaticTextSqlNode(data); + contents.add(staticTextSqlNode); + configuration.addSqlNode(data, staticTextSqlNode); + } } } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 - String nodeName = child.getNode().getNodeName(); - NodeHandler handler = nodeHandlerMap.get(nodeName); - if (handler == null) { - throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); - } - handler.handleNode(child, contents); - isDynamic = true; - } + String str = child.toString(); + if(configuration.containsSqlNode(str)) { + contents.add(configuration.getSqlNode(str)); + isDynamic = true; + }else { + String nodeName = child.getNode().getNodeName(); + NodeHandler handler = nodeHandlerMap.get(nodeName); + if (handler == null) { + throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); + } + SqlNode sqlNode= handler.handleNode(child); + configuration.addSqlNode(str,sqlNode); + contents.add(sqlNode); + isDynamic = true; + } + } } return new MixedSqlNode(contents); } private interface NodeHandler { - void handleNode(XNode nodeToHandle, List targetContents); + SqlNode handleNode(XNode nodeToHandle); } private class BindHandler implements NodeHandler { @@ -111,11 +130,10 @@ public BindHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { final String name = nodeToHandle.getStringAttribute("name"); final String expression = nodeToHandle.getStringAttribute("value"); - final VarDeclSqlNode node = new VarDeclSqlNode(name, expression); - targetContents.add(node); + return new VarDeclSqlNode(name, expression); } } @@ -125,14 +143,13 @@ public TrimHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); String prefix = nodeToHandle.getStringAttribute("prefix"); String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides"); String suffix = nodeToHandle.getStringAttribute("suffix"); String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides"); - TrimSqlNode trim = new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides); - targetContents.add(trim); + return new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides); } } @@ -142,10 +159,9 @@ public WhereHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - WhereSqlNode where = new WhereSqlNode(configuration, mixedSqlNode); - targetContents.add(where); + return new WhereSqlNode(configuration, mixedSqlNode); } } @@ -155,10 +171,9 @@ public SetHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - SetSqlNode set = new SetSqlNode(configuration, mixedSqlNode); - targetContents.add(set); + return new SetSqlNode(configuration, mixedSqlNode); } } @@ -168,16 +183,16 @@ public ForEachHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); String collection = nodeToHandle.getStringAttribute("collection"); + Boolean nullable = nodeToHandle.getBooleanAttribute("nullable"); String item = nodeToHandle.getStringAttribute("item"); String index = nodeToHandle.getStringAttribute("index"); String open = nodeToHandle.getStringAttribute("open"); String close = nodeToHandle.getStringAttribute("close"); String separator = nodeToHandle.getStringAttribute("separator"); - ForEachSqlNode forEachSqlNode = new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator); - targetContents.add(forEachSqlNode); + return new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator); } } @@ -187,11 +202,10 @@ public IfHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); String test = nodeToHandle.getStringAttribute("test"); - IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test); - targetContents.add(ifSqlNode); + return new IfSqlNode(mixedSqlNode, test); } } @@ -201,9 +215,8 @@ public OtherwiseHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - targetContents.add(mixedSqlNode); + public SqlNode handleNode(XNode nodeToHandle) { + return parseDynamicTags(nodeToHandle); } } @@ -213,13 +226,12 @@ public ChooseHandler() { } @Override - public void handleNode(XNode nodeToHandle, List targetContents) { + public SqlNode handleNode(XNode nodeToHandle) { List whenSqlNodes = new ArrayList<>(); List otherwiseSqlNodes = new ArrayList<>(); handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes); SqlNode defaultSqlNode = getDefaultSqlNode(otherwiseSqlNodes); - ChooseSqlNode chooseSqlNode = new ChooseSqlNode(whenSqlNodes, defaultSqlNode); - targetContents.add(chooseSqlNode); + return new ChooseSqlNode(whenSqlNodes, defaultSqlNode); } private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNodes, List defaultSqlNodes) { @@ -228,9 +240,9 @@ private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNo String nodeName = child.getNode().getNodeName(); NodeHandler handler = nodeHandlerMap.get(nodeName); if (handler instanceof IfHandler) { - handler.handleNode(child, ifSqlNodes); + ifSqlNodes.add(handler.handleNode(child)); } else if (handler instanceof OtherwiseHandler) { - handler.handleNode(child, defaultSqlNodes); + defaultSqlNodes.add(handler.handleNode(child)); } } } diff --git a/src/main/java/org/apache/ibatis/session/Configuration.java b/src/main/java/org/apache/ibatis/session/Configuration.java index 32f93028c72..b31499c0937 100644 --- a/src/main/java/org/apache/ibatis/session/Configuration.java +++ b/src/main/java/org/apache/ibatis/session/Configuration.java @@ -86,6 +86,7 @@ import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.scripting.LanguageDriverRegistry; import org.apache.ibatis.scripting.defaults.RawLanguageDriver; +import org.apache.ibatis.scripting.xmltags.SqlNode; import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver; import org.apache.ibatis.transaction.Transaction; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; @@ -156,6 +157,7 @@ public class Configuration { .conflictMessageProducer((savedValue, targetValue) -> ". please check " + savedValue.getResource() + " and " + targetValue.getResource()); protected final Map caches = new StrictMap<>("Caches collection"); + protected final Map sqlNodes = new StrictMap<>("SqlNode collection"); protected final Map resultMaps = new StrictMap<>("Result Maps collection"); protected final Map parameterMaps = new StrictMap<>("Parameter Maps collection"); protected final Map keyGenerators = new StrictMap<>("Key Generators collection"); @@ -773,6 +775,17 @@ public Collection getMappedStatementNames() { return mappedStatements.keySet(); } + public void addSqlNode(String key, SqlNode sqlNode) { + sqlNodes.put(key, sqlNode); + } + + public boolean containsSqlNode(String key) { + return sqlNodes.containsKey(key); + } + + public SqlNode getSqlNode(String key) { + return sqlNodes.get(key); + } public Collection getMappedStatements() { buildAllStatements(); return mappedStatements.values(); From fea327bcc71558f77c4f9c28f5b0d5a3c796c85a Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Fri, 4 Nov 2022 12:57:14 -0400 Subject: [PATCH 02/13] Sqlnode footprint reduced --- .../scripting/xmltags/XMLScriptBuilder.java | 409 +++++++++--------- .../apache/ibatis/session/Configuration.java | 3 +- 2 files changed, 213 insertions(+), 199 deletions(-) diff --git a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java index 90e002a4687..13ae1589e54 100644 --- a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java +++ b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java @@ -15,6 +15,9 @@ */ package org.apache.ibatis.scripting.xmltags; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -34,228 +37,238 @@ */ public class XMLScriptBuilder extends BaseBuilder { - private final XNode context; - private boolean isDynamic; - private final Class parameterType; - private final Map nodeHandlerMap = new HashMap<>(); + private final XNode context; + private boolean isDynamic; + private final Class parameterType; + private final Map nodeHandlerMap = new HashMap<>(); - public XMLScriptBuilder(Configuration configuration, XNode context) { - this(configuration, context, null); - } + public XMLScriptBuilder(Configuration configuration, XNode context) { + this(configuration, context, null); + } - public XMLScriptBuilder(Configuration configuration, XNode context, Class parameterType) { - super(configuration); - this.context = context; - this.parameterType = parameterType; - initNodeHandlerMap(); - } + public XMLScriptBuilder(Configuration configuration, XNode context, Class parameterType) { + super(configuration); + this.context = context; + this.parameterType = parameterType; + initNodeHandlerMap(); + } + private void initNodeHandlerMap() { + nodeHandlerMap.put("trim", new TrimHandler()); + nodeHandlerMap.put("where", new WhereHandler()); + nodeHandlerMap.put("set", new SetHandler()); + nodeHandlerMap.put("foreach", new ForEachHandler()); + nodeHandlerMap.put("if", new IfHandler()); + nodeHandlerMap.put("choose", new ChooseHandler()); + nodeHandlerMap.put("when", new IfHandler()); + nodeHandlerMap.put("otherwise", new OtherwiseHandler()); + nodeHandlerMap.put("bind", new BindHandler()); + } - private void initNodeHandlerMap() { - nodeHandlerMap.put("trim", new TrimHandler()); - nodeHandlerMap.put("where", new WhereHandler()); - nodeHandlerMap.put("set", new SetHandler()); - nodeHandlerMap.put("foreach", new ForEachHandler()); - nodeHandlerMap.put("if", new IfHandler()); - nodeHandlerMap.put("choose", new ChooseHandler()); - nodeHandlerMap.put("when", new IfHandler()); - nodeHandlerMap.put("otherwise", new OtherwiseHandler()); - nodeHandlerMap.put("bind", new BindHandler()); - } + public SqlSource parseScriptNode() { + MixedSqlNode rootSqlNode = parseDynamicTags(context); + SqlSource sqlSource; + if (isDynamic) { + sqlSource = new DynamicSqlSource(configuration, rootSqlNode); + } else { + sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType); + } + return sqlSource; + } - public SqlSource parseScriptNode() { - MixedSqlNode rootSqlNode = parseDynamicTags(context); - SqlSource sqlSource; - if (isDynamic) { - sqlSource = new DynamicSqlSource(configuration, rootSqlNode); - } else { - sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType); - } - return sqlSource; - } - - protected MixedSqlNode parseDynamicTags(XNode node) { - List contents = new ArrayList<>(); - NodeList children = node.getNode().getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - XNode child = node.newXNode(children.item(i)); - if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) { - String data = child.getStringBody(""); - if(configuration.containsSqlNode(data)) { - SqlNode sqlNode = configuration.getSqlNode(data); - if(sqlNode instanceof TextSqlNode) { - isDynamic = true; - } - contents.add(sqlNode); - }else { - TextSqlNode textSqlNode = new TextSqlNode(data); - if (textSqlNode.isDynamic()) { - contents.add(textSqlNode); - isDynamic = true; - configuration.addSqlNode(data, textSqlNode); - } else { - StaticTextSqlNode staticTextSqlNode = new StaticTextSqlNode(data); - contents.add(staticTextSqlNode); - configuration.addSqlNode(data, staticTextSqlNode); + protected MixedSqlNode parseDynamicTags(XNode node) { + List contents = new ArrayList<>(); + NodeList children = node.getNode().getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + XNode child = node.newXNode(children.item(i)); + if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE + || child.getNode().getNodeType() == Node.TEXT_NODE) { + String data = child.getStringBody(""); + String key = getHash(child.getStringBody("")); + if (configuration.containsSqlNode(key)) { + SqlNode sqlNode = configuration.getSqlNode(key); + if (sqlNode instanceof TextSqlNode) { + isDynamic = true; + } + contents.add(sqlNode); + } else { + TextSqlNode textSqlNode = new TextSqlNode(data); + if (textSqlNode.isDynamic()) { + contents.add(textSqlNode); + isDynamic = true; + configuration.addSqlNode(key, textSqlNode); + } else { + StaticTextSqlNode staticTextSqlNode = new StaticTextSqlNode(data); + contents.add(staticTextSqlNode); + configuration.addSqlNode(key, staticTextSqlNode); + } + } + } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 + String key = getHash(child.toString()); + if (configuration.containsSqlNode(key)) { + contents.add(configuration.getSqlNode(key)); + isDynamic = true; + } else { + String nodeName = child.getNode().getNodeName(); + NodeHandler handler = nodeHandlerMap.get(nodeName); + if (handler == null) { + throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); + } + SqlNode sqlNode = handler.handleNode(child); + configuration.addSqlNode(key, sqlNode); + contents.add(sqlNode); + isDynamic = true; + } } - } - } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 - String str = child.toString(); - if(configuration.containsSqlNode(str)) { - contents.add(configuration.getSqlNode(str)); - isDynamic = true; - }else { - String nodeName = child.getNode().getNodeName(); - NodeHandler handler = nodeHandlerMap.get(nodeName); - if (handler == null) { - throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); - } - SqlNode sqlNode= handler.handleNode(child); - configuration.addSqlNode(str,sqlNode); - contents.add(sqlNode); - isDynamic = true; - } - } - } - return new MixedSqlNode(contents); - } + } + return new MixedSqlNode(contents); + } + + private String getHash(String str) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); + return new String(messageDigest.digest(str.getBytes(StandardCharsets.UTF_8))); + } catch (NoSuchAlgorithmException e) { + return str; + } + } - private interface NodeHandler { - SqlNode handleNode(XNode nodeToHandle); - } + private interface NodeHandler { + SqlNode handleNode(XNode nodeToHandle); + } - private class BindHandler implements NodeHandler { - public BindHandler() { - // Prevent Synthetic Access - } + private class BindHandler implements NodeHandler { + public BindHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - final String name = nodeToHandle.getStringAttribute("name"); - final String expression = nodeToHandle.getStringAttribute("value"); - return new VarDeclSqlNode(name, expression); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + final String name = nodeToHandle.getStringAttribute("name"); + final String expression = nodeToHandle.getStringAttribute("value"); + return new VarDeclSqlNode(name, expression); + } + } - private class TrimHandler implements NodeHandler { - public TrimHandler() { - // Prevent Synthetic Access - } + private class TrimHandler implements NodeHandler { + public TrimHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - String prefix = nodeToHandle.getStringAttribute("prefix"); - String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides"); - String suffix = nodeToHandle.getStringAttribute("suffix"); - String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides"); - return new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + String prefix = nodeToHandle.getStringAttribute("prefix"); + String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides"); + String suffix = nodeToHandle.getStringAttribute("suffix"); + String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides"); + return new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides); + } + } - private class WhereHandler implements NodeHandler { - public WhereHandler() { - // Prevent Synthetic Access - } + private class WhereHandler implements NodeHandler { + public WhereHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - return new WhereSqlNode(configuration, mixedSqlNode); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + return new WhereSqlNode(configuration, mixedSqlNode); + } + } - private class SetHandler implements NodeHandler { - public SetHandler() { - // Prevent Synthetic Access - } + private class SetHandler implements NodeHandler { + public SetHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - return new SetSqlNode(configuration, mixedSqlNode); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + return new SetSqlNode(configuration, mixedSqlNode); + } + } - private class ForEachHandler implements NodeHandler { - public ForEachHandler() { - // Prevent Synthetic Access - } + private class ForEachHandler implements NodeHandler { + public ForEachHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - String collection = nodeToHandle.getStringAttribute("collection"); - Boolean nullable = nodeToHandle.getBooleanAttribute("nullable"); - String item = nodeToHandle.getStringAttribute("item"); - String index = nodeToHandle.getStringAttribute("index"); - String open = nodeToHandle.getStringAttribute("open"); - String close = nodeToHandle.getStringAttribute("close"); - String separator = nodeToHandle.getStringAttribute("separator"); - return new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + String collection = nodeToHandle.getStringAttribute("collection"); + String item = nodeToHandle.getStringAttribute("item"); + String index = nodeToHandle.getStringAttribute("index"); + String open = nodeToHandle.getStringAttribute("open"); + String close = nodeToHandle.getStringAttribute("close"); + String separator = nodeToHandle.getStringAttribute("separator"); + return new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator); + } + } - private class IfHandler implements NodeHandler { - public IfHandler() { - // Prevent Synthetic Access - } + private class IfHandler implements NodeHandler { + public IfHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - String test = nodeToHandle.getStringAttribute("test"); - return new IfSqlNode(mixedSqlNode, test); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + String test = nodeToHandle.getStringAttribute("test"); + return new IfSqlNode(mixedSqlNode, test); + } + } - private class OtherwiseHandler implements NodeHandler { - public OtherwiseHandler() { - // Prevent Synthetic Access - } + private class OtherwiseHandler implements NodeHandler { + public OtherwiseHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - return parseDynamicTags(nodeToHandle); - } - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + return parseDynamicTags(nodeToHandle); + } + } - private class ChooseHandler implements NodeHandler { - public ChooseHandler() { - // Prevent Synthetic Access - } + private class ChooseHandler implements NodeHandler { + public ChooseHandler() { + // Prevent Synthetic Access + } - @Override - public SqlNode handleNode(XNode nodeToHandle) { - List whenSqlNodes = new ArrayList<>(); - List otherwiseSqlNodes = new ArrayList<>(); - handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes); - SqlNode defaultSqlNode = getDefaultSqlNode(otherwiseSqlNodes); - return new ChooseSqlNode(whenSqlNodes, defaultSqlNode); - } + @Override + public SqlNode handleNode(XNode nodeToHandle) { + List whenSqlNodes = new ArrayList<>(); + List otherwiseSqlNodes = new ArrayList<>(); + handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes); + SqlNode defaultSqlNode = getDefaultSqlNode(otherwiseSqlNodes); + return new ChooseSqlNode(whenSqlNodes, defaultSqlNode); + } - private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNodes, List defaultSqlNodes) { - List children = chooseSqlNode.getChildren(); - for (XNode child : children) { - String nodeName = child.getNode().getNodeName(); - NodeHandler handler = nodeHandlerMap.get(nodeName); - if (handler instanceof IfHandler) { - ifSqlNodes.add(handler.handleNode(child)); - } else if (handler instanceof OtherwiseHandler) { - defaultSqlNodes.add(handler.handleNode(child)); - } - } - } + private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNodes, + List defaultSqlNodes) { + List children = chooseSqlNode.getChildren(); + for (XNode child : children) { + String nodeName = child.getNode().getNodeName(); + NodeHandler handler = nodeHandlerMap.get(nodeName); + if (handler instanceof IfHandler) { + ifSqlNodes.add(handler.handleNode(child)); + } else if (handler instanceof OtherwiseHandler) { + defaultSqlNodes.add(handler.handleNode(child)); + } + } + } - private SqlNode getDefaultSqlNode(List defaultSqlNodes) { - SqlNode defaultSqlNode = null; - if (defaultSqlNodes.size() == 1) { - defaultSqlNode = defaultSqlNodes.get(0); - } else if (defaultSqlNodes.size() > 1) { - throw new BuilderException("Too many default (otherwise) elements in choose statement."); - } - return defaultSqlNode; - } - } + private SqlNode getDefaultSqlNode(List defaultSqlNodes) { + SqlNode defaultSqlNode = null; + if (defaultSqlNodes.size() == 1) { + defaultSqlNode = defaultSqlNodes.get(0); + } else if (defaultSqlNodes.size() > 1) { + throw new BuilderException("Too many default (otherwise) elements in choose statement."); + } + return defaultSqlNode; + } + } } diff --git a/src/main/java/org/apache/ibatis/session/Configuration.java b/src/main/java/org/apache/ibatis/session/Configuration.java index b31499c0937..3ea56299980 100644 --- a/src/main/java/org/apache/ibatis/session/Configuration.java +++ b/src/main/java/org/apache/ibatis/session/Configuration.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import org.apache.ibatis.binding.MapperRegistry; @@ -157,7 +158,7 @@ public class Configuration { .conflictMessageProducer((savedValue, targetValue) -> ". please check " + savedValue.getResource() + " and " + targetValue.getResource()); protected final Map caches = new StrictMap<>("Caches collection"); - protected final Map sqlNodes = new StrictMap<>("SqlNode collection"); + protected final Map sqlNodes = new HashMap<>(); protected final Map resultMaps = new StrictMap<>("Result Maps collection"); protected final Map parameterMaps = new StrictMap<>("Parameter Maps collection"); protected final Map keyGenerators = new StrictMap<>("Key Generators collection"); From 872cdd227dce94f098168761c791be0801df1c41 Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Fri, 4 Nov 2022 14:59:11 -0400 Subject: [PATCH 03/13] Unique String added --- .../ibatis/scripting/xmltags/XMLScriptBuilder.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java index 13ae1589e54..3af0c0b70f1 100644 --- a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java +++ b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java @@ -15,10 +15,12 @@ */ package org.apache.ibatis.scripting.xmltags; +import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -124,12 +126,13 @@ protected MixedSqlNode parseDynamicTags(XNode node) { return new MixedSqlNode(contents); } - private String getHash(String str) { + private String getHash(String key) { try { MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); - return new String(messageDigest.digest(str.getBytes(StandardCharsets.UTF_8))); + byte hashBytes[] = messageDigest.digest(key.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(hashBytes); } catch (NoSuchAlgorithmException e) { - return str; + return key; } } From aba43bc95d7b23548ff3b8a1623ecb58c6faf863 Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Mon, 7 Nov 2022 15:26:03 -0500 Subject: [PATCH 04/13] Mybatis Perf changes pushed --- .../java/org/apache/ibatis/parsing/XNode.java | 783 +++++++++--------- .../scripting/xmltags/XMLScriptBuilder.java | 9 +- 2 files changed, 403 insertions(+), 389 deletions(-) diff --git a/src/main/java/org/apache/ibatis/parsing/XNode.java b/src/main/java/org/apache/ibatis/parsing/XNode.java index 01cb80774f7..1b17837fdad 100644 --- a/src/main/java/org/apache/ibatis/parsing/XNode.java +++ b/src/main/java/org/apache/ibatis/parsing/XNode.java @@ -32,389 +32,404 @@ */ public class XNode { - private final Node node; - private final String name; - private final String body; - private final Properties attributes; - private final Properties variables; - private final XPathParser xpathParser; - - public XNode(XPathParser xpathParser, Node node, Properties variables) { - this.xpathParser = xpathParser; - this.node = node; - this.name = node.getNodeName(); - this.variables = variables; - this.attributes = parseAttributes(node); - this.body = parseBody(node); - } - - public XNode newXNode(Node node) { - return new XNode(xpathParser, node, variables); - } - - public XNode getParent() { - Node parent = node.getParentNode(); - if (!(parent instanceof Element)) { - return null; - } else { - return new XNode(xpathParser, parent, variables); - } - } - - public String getPath() { - StringBuilder builder = new StringBuilder(); - Node current = node; - while (current instanceof Element) { - if (current != node) { - builder.insert(0, "/"); - } - builder.insert(0, current.getNodeName()); - current = current.getParentNode(); - } - return builder.toString(); - } - - public String getValueBasedIdentifier() { - StringBuilder builder = new StringBuilder(); - XNode current = this; - while (current != null) { - if (current != this) { - builder.insert(0, "_"); - } - String value = current.getStringAttribute("id", - current.getStringAttribute("value", - current.getStringAttribute("property", (String) null))); - if (value != null) { - value = value.replace('.', '_'); - builder.insert(0, "]"); - builder.insert(0, - value); - builder.insert(0, "["); - } - builder.insert(0, current.getName()); - current = current.getParent(); - } - return builder.toString(); - } - - public String evalString(String expression) { - return xpathParser.evalString(node, expression); - } - - public Boolean evalBoolean(String expression) { - return xpathParser.evalBoolean(node, expression); - } - - public Double evalDouble(String expression) { - return xpathParser.evalDouble(node, expression); - } - - public List evalNodes(String expression) { - return xpathParser.evalNodes(node, expression); - } - - public XNode evalNode(String expression) { - return xpathParser.evalNode(node, expression); - } - - public Node getNode() { - return node; - } - - public String getName() { - return name; - } - - public String getStringBody() { - return getStringBody(null); - } - - public String getStringBody(String def) { - if (body == null) { - return def; - } else { - return body; - } - } - - public Boolean getBooleanBody() { - return getBooleanBody(null); - } - - public Boolean getBooleanBody(Boolean def) { - if (body == null) { - return def; - } else { - return Boolean.valueOf(body); - } - } - - public Integer getIntBody() { - return getIntBody(null); - } - - public Integer getIntBody(Integer def) { - if (body == null) { - return def; - } else { - return Integer.parseInt(body); - } - } - - public Long getLongBody() { - return getLongBody(null); - } - - public Long getLongBody(Long def) { - if (body == null) { - return def; - } else { - return Long.parseLong(body); - } - } - - public Double getDoubleBody() { - return getDoubleBody(null); - } - - public Double getDoubleBody(Double def) { - if (body == null) { - return def; - } else { - return Double.parseDouble(body); - } - } - - public Float getFloatBody() { - return getFloatBody(null); - } - - public Float getFloatBody(Float def) { - if (body == null) { - return def; - } else { - return Float.parseFloat(body); - } - } - - public > T getEnumAttribute(Class enumType, String name) { - return getEnumAttribute(enumType, name, null); - } - - public > T getEnumAttribute(Class enumType, String name, T def) { - String value = getStringAttribute(name); - if (value == null) { - return def; - } else { - return Enum.valueOf(enumType, value); - } - } - - /** - * Return a attribute value as String. - * - *

- * If attribute value is absent, return value that provided from supplier of default value. - * - * @param name - * attribute name - * @param defSupplier - * a supplier of default value - * @return the string attribute - * @since 3.5.4 - */ - public String getStringAttribute(String name, Supplier defSupplier) { - String value = attributes.getProperty(name); - return value == null ? defSupplier.get() : value; - } - - public String getStringAttribute(String name) { - return getStringAttribute(name, (String) null); - } - - public String getStringAttribute(String name, String def) { - String value = attributes.getProperty(name); - if (value == null) { - return def; - } else { - return value; - } - } - - public Boolean getBooleanAttribute(String name) { - return getBooleanAttribute(name, null); - } - - public Boolean getBooleanAttribute(String name, Boolean def) { - String value = attributes.getProperty(name); - if (value == null) { - return def; - } else { - return Boolean.valueOf(value); - } - } - - public Integer getIntAttribute(String name) { - return getIntAttribute(name, null); - } - - public Integer getIntAttribute(String name, Integer def) { - String value = attributes.getProperty(name); - if (value == null) { - return def; - } else { - return Integer.parseInt(value); - } - } - - public Long getLongAttribute(String name) { - return getLongAttribute(name, null); - } - - public Long getLongAttribute(String name, Long def) { - String value = attributes.getProperty(name); - if (value == null) { - return def; - } else { - return Long.parseLong(value); - } - } - - public Double getDoubleAttribute(String name) { - return getDoubleAttribute(name, null); - } - - public Double getDoubleAttribute(String name, Double def) { - String value = attributes.getProperty(name); - if (value == null) { - return def; - } else { - return Double.parseDouble(value); - } - } - - public Float getFloatAttribute(String name) { - return getFloatAttribute(name, null); - } - - public Float getFloatAttribute(String name, Float def) { - String value = attributes.getProperty(name); - if (value == null) { - return def; - } else { - return Float.parseFloat(value); - } - } - - public List getChildren() { - List children = new ArrayList<>(); - NodeList nodeList = node.getChildNodes(); - if (nodeList != null) { - for (int i = 0, n = nodeList.getLength(); i < n; i++) { - Node node = nodeList.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - children.add(new XNode(xpathParser, node, variables)); - } - } - } - return children; - } - - public Properties getChildrenAsProperties() { - Properties properties = new Properties(); - for (XNode child : getChildren()) { - String name = child.getStringAttribute("name"); - String value = child.getStringAttribute("value"); - if (name != null && value != null) { - properties.setProperty(name, value); - } - } - return properties; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - toString(builder, 0); - return builder.toString(); - } - - private void toString(StringBuilder builder, int level) { - builder.append("<"); - builder.append(name); - for (Map.Entry entry : attributes.entrySet()) { - builder.append(" "); - builder.append(entry.getKey()); - builder.append("=\""); - builder.append(entry.getValue()); - builder.append("\""); - } - List children = getChildren(); - if (!children.isEmpty()) { - builder.append(">\n"); - for (XNode child : children) { - indent(builder, level + 1); - child.toString(builder, level + 1); - } - indent(builder, level); - builder.append(""); - } else if (body != null) { - builder.append(">"); - builder.append(body); - builder.append(""); - } else { - builder.append("/>"); - indent(builder, level); - } - builder.append("\n"); - } - - private void indent(StringBuilder builder, int level) { - for (int i = 0; i < level; i++) { - builder.append(" "); - } - } - - private Properties parseAttributes(Node n) { - Properties attributes = new Properties(); - NamedNodeMap attributeNodes = n.getAttributes(); - if (attributeNodes != null) { - for (int i = 0; i < attributeNodes.getLength(); i++) { - Node attribute = attributeNodes.item(i); - String value = PropertyParser.parse(attribute.getNodeValue(), variables); - attributes.put(attribute.getNodeName(), value); - } - } - return attributes; - } - - private String parseBody(Node node) { - String data = getBodyData(node); - if (data == null) { - NodeList children = node.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - data = getBodyData(child); - if (data != null) { - break; - } - } - } - return data; - } - - private String getBodyData(Node child) { - if (child.getNodeType() == Node.CDATA_SECTION_NODE - || child.getNodeType() == Node.TEXT_NODE) { - String data = ((CharacterData) child).getData(); - data = PropertyParser.parse(data, variables); - return data; - } - return null; - } + private Node node; + private final String name; + private final String body; + private final Properties attributes; + private final Properties variables; + private final XPathParser xpathParser; + + public XNode(XPathParser xpathParser, Node node, Properties variables) { + this.xpathParser = xpathParser; + this.node = node; + this.name = node.getNodeName(); + this.variables = variables; + this.attributes = parseAttributes(node); + this.body = parseBody(node); + } + + public XNode newXNode(Node node) { + return new XNode(xpathParser, node, variables); + } + + public XNode getParent() { + Node parent = node.getParentNode(); + if (!(parent instanceof Element)) { + return null; + } else { + return new XNode(xpathParser, parent, variables); + } + } + + public String getPath() { + StringBuilder builder = new StringBuilder(); + Node current = node; + while (current instanceof Element) { + if (current != node) { + builder.insert(0, "/"); + } + builder.insert(0, current.getNodeName()); + current = current.getParentNode(); + } + return builder.toString(); + } + + public String getValueBasedIdentifier() { + StringBuilder builder = new StringBuilder(); + XNode current = this; + while (current != null) { + if (current != this) { + builder.insert(0, "_"); + } + String value = current.getStringAttribute("id", + current.getStringAttribute("value", current.getStringAttribute("property", (String) null))); + if (value != null) { + value = value.replace('.', '_'); + builder.insert(0, "]"); + builder.insert(0, value); + builder.insert(0, "["); + } + builder.insert(0, current.getName()); + current = current.getParent(); + } + return builder.toString(); + } + + public String evalString(String expression) { + return xpathParser.evalString(node, expression); + } + + public Boolean evalBoolean(String expression) { + return xpathParser.evalBoolean(node, expression); + } + + public Double evalDouble(String expression) { + return xpathParser.evalDouble(node, expression); + } + + public List evalNodes(String expression) { + return xpathParser.evalNodes(node, expression); + } + + public XNode evalNode(String expression) { + return xpathParser.evalNode(node, expression); + } + + public Node getNode() { + return node; + } + + public String getName() { + return name; + } + + public String getStringBody() { + return getStringBody(null); + } + + public String getStringBody(String def) { + if (body == null) { + return def; + } else { + return body; + } + } + + public Boolean getBooleanBody() { + return getBooleanBody(null); + } + + public Boolean getBooleanBody(Boolean def) { + if (body == null) { + return def; + } else { + return Boolean.valueOf(body); + } + } + + public Integer getIntBody() { + return getIntBody(null); + } + + public Integer getIntBody(Integer def) { + if (body == null) { + return def; + } else { + return Integer.parseInt(body); + } + } + + public Long getLongBody() { + return getLongBody(null); + } + + public Long getLongBody(Long def) { + if (body == null) { + return def; + } else { + return Long.parseLong(body); + } + } + + public Double getDoubleBody() { + return getDoubleBody(null); + } + + public Double getDoubleBody(Double def) { + if (body == null) { + return def; + } else { + return Double.parseDouble(body); + } + } + + public Float getFloatBody() { + return getFloatBody(null); + } + + public Float getFloatBody(Float def) { + if (body == null) { + return def; + } else { + return Float.parseFloat(body); + } + } + + public > T getEnumAttribute(Class enumType, String name) { + return getEnumAttribute(enumType, name, null); + } + + public > T getEnumAttribute(Class enumType, String name, T def) { + String value = getStringAttribute(name); + if (value == null) { + return def; + } else { + return Enum.valueOf(enumType, value); + } + } + + /** + * Return a attribute value as String. + * + *

+ * If attribute value is absent, return value that provided from supplier of + * default value. + * + * @param name attribute name + * @param defSupplier a supplier of default value + * @return the string attribute + * @since 3.5.4 + */ + public String getStringAttribute(String name, Supplier defSupplier) { + String value = attributes.getProperty(name); + return value == null ? defSupplier.get() : value; + } + + public String getStringAttribute(String name) { + return getStringAttribute(name, (String) null); + } + + public String getStringAttribute(String name, String def) { + String value = attributes.getProperty(name); + if (value == null) { + return def; + } else { + return value; + } + } + + public Boolean getBooleanAttribute(String name) { + return getBooleanAttribute(name, null); + } + + public Boolean getBooleanAttribute(String name, Boolean def) { + String value = attributes.getProperty(name); + if (value == null) { + return def; + } else { + return Boolean.valueOf(value); + } + } + + public Integer getIntAttribute(String name) { + return getIntAttribute(name, null); + } + + public Integer getIntAttribute(String name, Integer def) { + String value = attributes.getProperty(name); + if (value == null) { + return def; + } else { + return Integer.parseInt(value); + } + } + + public Long getLongAttribute(String name) { + return getLongAttribute(name, null); + } + + public Long getLongAttribute(String name, Long def) { + String value = attributes.getProperty(name); + if (value == null) { + return def; + } else { + return Long.parseLong(value); + } + } + + public Double getDoubleAttribute(String name) { + return getDoubleAttribute(name, null); + } + + public Double getDoubleAttribute(String name, Double def) { + String value = attributes.getProperty(name); + if (value == null) { + return def; + } else { + return Double.parseDouble(value); + } + } + + public Float getFloatAttribute(String name) { + return getFloatAttribute(name, null); + } + + public Float getFloatAttribute(String name, Float def) { + String value = attributes.getProperty(name); + if (value == null) { + return def; + } else { + return Float.parseFloat(value); + } + } + + public List getChildren() { + List children = new ArrayList<>(); + NodeList nodeList = node.getChildNodes(); + if (nodeList != null) { + for (int i = 0, n = nodeList.getLength(); i < n; i++) { + Node node = nodeList.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + children.add(new XNode(xpathParser, node, variables)); + } + } + } + return children; + } + + public Properties getChildrenAsProperties() { + Properties properties = new Properties(); + for (XNode child : getChildren()) { + String name = child.getStringAttribute("name"); + String value = child.getStringAttribute("value"); + if (name != null && value != null) { + properties.setProperty(name, value); + } + } + return properties; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + toString(builder, 0); + return builder.toString(); + } + + private void toString(StringBuilder builder, int level) { + builder.append("<"); + builder.append(name); + for (Map.Entry entry : attributes.entrySet()) { + builder.append(" "); + builder.append(entry.getKey()); + builder.append("=\""); + builder.append(entry.getValue()); + builder.append("\""); + } + List children = getChildren(); + if (!children.isEmpty()) { + builder.append(">\n"); + for (XNode child : children) { + indent(builder, level + 1); + child.toString(builder, level + 1); + } + indent(builder, level); + builder.append(""); + } else if (body != null) { + builder.append(">"); + builder.append(body); + builder.append(""); + } else { + builder.append("/>"); + indent(builder, level); + } + builder.append("\n"); + } + + public String toStringWithContent() { + StringBuilder builder = new StringBuilder(); + toStringWithContent(builder); + return builder.toString(); + } + + private void toStringWithContent(StringBuilder builder) { + builder.append("<"); + builder.append(name); + for (Map.Entry entry : attributes.entrySet()) { + builder.append(entry.getKey()); + builder.append(entry.getValue()); + } + Node clonedNode = getNode().cloneNode(true); + builder.append(clonedNode.getTextContent()); + builder.append(body); + builder.append(name); + } + + private void indent(StringBuilder builder, int level) { + for (int i = 0; i < level; i++) { + builder.append(" "); + } + } + + private Properties parseAttributes(Node n) { + Properties attributes = new Properties(); + NamedNodeMap attributeNodes = n.getAttributes(); + if (attributeNodes != null) { + for (int i = 0; i < attributeNodes.getLength(); i++) { + Node attribute = attributeNodes.item(i); + String value = PropertyParser.parse(attribute.getNodeValue(), variables); + attributes.put(attribute.getNodeName(), value); + } + } + return attributes; + } + + private String parseBody(Node node) { + String data = getBodyData(node); + if (data == null) { + NodeList children = node.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + data = getBodyData(child); + if (data != null) { + break; + } + } + } + return data; + } + + private String getBodyData(Node child) { + if (child.getNodeType() == Node.CDATA_SECTION_NODE || child.getNodeType() == Node.TEXT_NODE) { + String data = ((CharacterData) child).getData(); + data = PropertyParser.parse(data, variables); + return data; + } + return null; + } } diff --git a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java index 3af0c0b70f1..89ed90cd156 100644 --- a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java +++ b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java @@ -15,7 +15,6 @@ */ package org.apache.ibatis.scripting.xmltags; -import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -85,8 +84,7 @@ protected MixedSqlNode parseDynamicTags(XNode node) { XNode child = node.newXNode(children.item(i)); if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) { - String data = child.getStringBody(""); - String key = getHash(child.getStringBody("")); + String key = getHash(child.getStringBody("")); if (configuration.containsSqlNode(key)) { SqlNode sqlNode = configuration.getSqlNode(key); if (sqlNode instanceof TextSqlNode) { @@ -94,6 +92,7 @@ protected MixedSqlNode parseDynamicTags(XNode node) { } contents.add(sqlNode); } else { + String data = child.getStringBody(""); TextSqlNode textSqlNode = new TextSqlNode(data); if (textSqlNode.isDynamic()) { contents.add(textSqlNode); @@ -106,7 +105,7 @@ protected MixedSqlNode parseDynamicTags(XNode node) { } } } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 - String key = getHash(child.toString()); + String key = getHash(child.toStringWithContent()); if (configuration.containsSqlNode(key)) { contents.add(configuration.getSqlNode(key)); isDynamic = true; @@ -126,7 +125,7 @@ protected MixedSqlNode parseDynamicTags(XNode node) { return new MixedSqlNode(contents); } - private String getHash(String key) { + private String getHash(String key) { try { MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); byte hashBytes[] = messageDigest.digest(key.getBytes(StandardCharsets.UTF_8)); From 6c63e6e36c6da80f5010788c9f36510ea72e9126 Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Tue, 8 Nov 2022 14:42:36 -0500 Subject: [PATCH 05/13] Choose Node issue fixed --- pom.xml | 2 +- .../java/org/apache/ibatis/parsing/XNode.java | 6 +++++ .../scripting/xmltags/XMLScriptBuilder.java | 25 +++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 2ae174317b6..5073d93f99e 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ mybatis - 3.5.6.1 + 3.5.6.2 jar mybatis diff --git a/src/main/java/org/apache/ibatis/parsing/XNode.java b/src/main/java/org/apache/ibatis/parsing/XNode.java index 1b17837fdad..b705791daee 100644 --- a/src/main/java/org/apache/ibatis/parsing/XNode.java +++ b/src/main/java/org/apache/ibatis/parsing/XNode.java @@ -379,14 +379,20 @@ public String toStringWithContent() { private void toStringWithContent(StringBuilder builder) { builder.append("<"); builder.append(name); + builder.append("><"); for (Map.Entry entry : attributes.entrySet()) { builder.append(entry.getKey()); + builder.append("><"); builder.append(entry.getValue()); + builder.append("><"); } Node clonedNode = getNode().cloneNode(true); builder.append(clonedNode.getTextContent()); + builder.append("><"); builder.append(body); + builder.append("><"); builder.append(name); + builder.append("/>"); } private void indent(StringBuilder builder, int level) { diff --git a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java index 89ed90cd156..b0ccff2e46d 100644 --- a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java +++ b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java @@ -106,12 +106,12 @@ protected MixedSqlNode parseDynamicTags(XNode node) { } } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 String key = getHash(child.toStringWithContent()); - if (configuration.containsSqlNode(key)) { + String nodeName = child.getNode().getNodeName(); + NodeHandler handler = nodeHandlerMap.get(nodeName); + if (configuration.containsSqlNode(key) && !(handler instanceof ChooseHandler)) { contents.add(configuration.getSqlNode(key)); isDynamic = true; } else { - String nodeName = child.getNode().getNodeName(); - NodeHandler handler = nodeHandlerMap.get(nodeName); if (handler == null) { throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); } @@ -255,9 +255,24 @@ private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNo String nodeName = child.getNode().getNodeName(); NodeHandler handler = nodeHandlerMap.get(nodeName); if (handler instanceof IfHandler) { - ifSqlNodes.add(handler.handleNode(child)); + String key = getHash(child.toStringWithContent()); + if (configuration.containsSqlNode(key)) { + ifSqlNodes.add(configuration.getSqlNode(key)); + isDynamic = true; + } else { + SqlNode sqlNode = handler.handleNode(child); + ifSqlNodes.add(sqlNode); + configuration.addSqlNode(key, sqlNode); + } } else if (handler instanceof OtherwiseHandler) { - defaultSqlNodes.add(handler.handleNode(child)); + String key = getHash(child.toStringWithContent()); + if (configuration.containsSqlNode(key)) { + defaultSqlNodes.add(configuration.getSqlNode(key)); + } else { + SqlNode sqlNode = handler.handleNode(child); + defaultSqlNodes.add(sqlNode); + configuration.addSqlNode(key, sqlNode); + } } } } From 058968d3645ae34b88d3f39600ede6c318115361 Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Wed, 9 Nov 2022 09:16:34 -0500 Subject: [PATCH 06/13] Bind Handler issue fixed for 3.5.6.3 --- pom.xml | 2 +- .../java/org/apache/ibatis/parsing/XNode.java | 18 +-- .../scripting/xmltags/XMLScriptBuilder.java | 151 +++++++++--------- 3 files changed, 83 insertions(+), 88 deletions(-) diff --git a/pom.xml b/pom.xml index 5073d93f99e..b9fafad0673 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ mybatis - 3.5.6.2 + 3.5.6.3 jar mybatis diff --git a/src/main/java/org/apache/ibatis/parsing/XNode.java b/src/main/java/org/apache/ibatis/parsing/XNode.java index b705791daee..2e9a875f8e9 100644 --- a/src/main/java/org/apache/ibatis/parsing/XNode.java +++ b/src/main/java/org/apache/ibatis/parsing/XNode.java @@ -377,22 +377,14 @@ public String toStringWithContent() { } private void toStringWithContent(StringBuilder builder) { - builder.append("<"); - builder.append(name); - builder.append("><"); - for (Map.Entry entry : attributes.entrySet()) { - builder.append(entry.getKey()); - builder.append("><"); - builder.append(entry.getValue()); - builder.append("><"); - } + builder.append(toString()); Node clonedNode = getNode().cloneNode(true); + builder.append(""); builder.append(clonedNode.getTextContent()); - builder.append("><"); + builder.append(""); + builder.append(""); builder.append(body); - builder.append("><"); - builder.append(name); - builder.append("/>"); + builder.append(""); } private void indent(StringBuilder builder, int level) { diff --git a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java index b0ccff2e46d..bb0feefd41a 100644 --- a/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java +++ b/src/main/java/org/apache/ibatis/scripting/xmltags/XMLScriptBuilder.java @@ -92,39 +92,44 @@ protected MixedSqlNode parseDynamicTags(XNode node) { } contents.add(sqlNode); } else { - String data = child.getStringBody(""); - TextSqlNode textSqlNode = new TextSqlNode(data); - if (textSqlNode.isDynamic()) { - contents.add(textSqlNode); - isDynamic = true; - configuration.addSqlNode(key, textSqlNode); - } else { - StaticTextSqlNode staticTextSqlNode = new StaticTextSqlNode(data); - contents.add(staticTextSqlNode); - configuration.addSqlNode(key, staticTextSqlNode); + String data = child.getStringBody("").replaceAll("\t", " ").replaceAll("\n", " "); + if(data.trim().length()>0) { + TextSqlNode textSqlNode = new TextSqlNode(data); + if (textSqlNode.isDynamic()) { + contents.add(textSqlNode); + isDynamic = true; + configuration.addSqlNode(key, textSqlNode); + } else { + StaticTextSqlNode staticTextSqlNode = new StaticTextSqlNode(data); + contents.add(staticTextSqlNode); + configuration.addSqlNode(key, staticTextSqlNode); + } } } } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 - String key = getHash(child.toStringWithContent()); String nodeName = child.getNode().getNodeName(); - NodeHandler handler = nodeHandlerMap.get(nodeName); - if (configuration.containsSqlNode(key) && !(handler instanceof ChooseHandler)) { - contents.add(configuration.getSqlNode(key)); - isDynamic = true; - } else { - if (handler == null) { - throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); - } - SqlNode sqlNode = handler.handleNode(child); - configuration.addSqlNode(key, sqlNode); - contents.add(sqlNode); - isDynamic = true; - } + NodeHandler handler = nodeHandlerMap.get(nodeName); + if (handler == null) { + throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); + } + handler.handleNode(child, contents); + isDynamic = true; } } return new MixedSqlNode(contents); } + private MixedSqlNode getMixedNode(XNode nodeToHandle) { + String key = getHash(nodeToHandle.toStringWithContent()); + if (configuration.containsSqlNode(key)) { + return (MixedSqlNode)configuration.getSqlNode(key); + } else { + MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + configuration.addSqlNode(key, mixedSqlNode); + return mixedSqlNode; + } + } + private String getHash(String key) { try { MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); @@ -136,7 +141,7 @@ private String getHash(String key) { } private interface NodeHandler { - SqlNode handleNode(XNode nodeToHandle); + void handleNode(XNode nodeToHandle, List targetContents); } private class BindHandler implements NodeHandler { @@ -145,10 +150,17 @@ public BindHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { + public void handleNode(XNode nodeToHandle, List targetContents) { final String name = nodeToHandle.getStringAttribute("name"); final String expression = nodeToHandle.getStringAttribute("value"); - return new VarDeclSqlNode(name, expression); + String key = getHash(nodeToHandle.toStringWithContent()); + if (configuration.containsSqlNode(key)) { + targetContents.add(configuration.getSqlNode(key)); + } else { + SqlNode sqlNode = new VarDeclSqlNode(name, expression); + configuration.addSqlNode(key, sqlNode); + targetContents.add(sqlNode); + } } } @@ -158,13 +170,13 @@ public TrimHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + public void handleNode(XNode nodeToHandle, List targetContents) { + MixedSqlNode mixedSqlNode = getMixedNode(nodeToHandle); String prefix = nodeToHandle.getStringAttribute("prefix"); String prefixOverrides = nodeToHandle.getStringAttribute("prefixOverrides"); String suffix = nodeToHandle.getStringAttribute("suffix"); String suffixOverrides = nodeToHandle.getStringAttribute("suffixOverrides"); - return new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides); + targetContents.add(new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides)); } } @@ -174,9 +186,9 @@ public WhereHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - return new WhereSqlNode(configuration, mixedSqlNode); + public void handleNode(XNode nodeToHandle, List targetContents) { + MixedSqlNode mixedSqlNode = getMixedNode(nodeToHandle); + targetContents.add( new WhereSqlNode(configuration, mixedSqlNode)); } } @@ -186,9 +198,9 @@ public SetHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); - return new SetSqlNode(configuration, mixedSqlNode); + public void handleNode(XNode nodeToHandle, List targetContents) { + MixedSqlNode mixedSqlNode = getMixedNode(nodeToHandle); + targetContents.add(new SetSqlNode(configuration, mixedSqlNode)); } } @@ -198,15 +210,15 @@ public ForEachHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + public void handleNode(XNode nodeToHandle, List targetContents) { + MixedSqlNode mixedSqlNode = getMixedNode(nodeToHandle); String collection = nodeToHandle.getStringAttribute("collection"); String item = nodeToHandle.getStringAttribute("item"); String index = nodeToHandle.getStringAttribute("index"); String open = nodeToHandle.getStringAttribute("open"); String close = nodeToHandle.getStringAttribute("close"); String separator = nodeToHandle.getStringAttribute("separator"); - return new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator); + targetContents.add( new ForEachSqlNode(configuration, mixedSqlNode, collection, index, item, open, close, separator)); } } @@ -216,10 +228,10 @@ public IfHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { - MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); + public void handleNode(XNode nodeToHandle, List targetContents) { + MixedSqlNode mixedSqlNode = getMixedNode(nodeToHandle); String test = nodeToHandle.getStringAttribute("test"); - return new IfSqlNode(mixedSqlNode, test); + targetContents.add(new IfSqlNode(mixedSqlNode, test)); } } @@ -229,8 +241,15 @@ public OtherwiseHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { - return parseDynamicTags(nodeToHandle); + public void handleNode(XNode nodeToHandle, List targetContents) { + String key = getHash(nodeToHandle.toStringWithContent()); + if (configuration.containsSqlNode(key)) { + targetContents.add(configuration.getSqlNode(key)); + } else { + SqlNode sqlNode = parseDynamicTags(nodeToHandle); + configuration.addSqlNode(key, sqlNode); + targetContents.add(sqlNode); + } } } @@ -240,42 +259,26 @@ public ChooseHandler() { } @Override - public SqlNode handleNode(XNode nodeToHandle) { + public void handleNode(XNode nodeToHandle, List targetContents) { List whenSqlNodes = new ArrayList<>(); List otherwiseSqlNodes = new ArrayList<>(); handleWhenOtherwiseNodes(nodeToHandle, whenSqlNodes, otherwiseSqlNodes); SqlNode defaultSqlNode = getDefaultSqlNode(otherwiseSqlNodes); - return new ChooseSqlNode(whenSqlNodes, defaultSqlNode); + targetContents.add(new ChooseSqlNode(whenSqlNodes, defaultSqlNode)); } - private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNodes, - List defaultSqlNodes) { - List children = chooseSqlNode.getChildren(); - for (XNode child : children) { - String nodeName = child.getNode().getNodeName(); - NodeHandler handler = nodeHandlerMap.get(nodeName); - if (handler instanceof IfHandler) { - String key = getHash(child.toStringWithContent()); - if (configuration.containsSqlNode(key)) { - ifSqlNodes.add(configuration.getSqlNode(key)); - isDynamic = true; - } else { - SqlNode sqlNode = handler.handleNode(child); - ifSqlNodes.add(sqlNode); - configuration.addSqlNode(key, sqlNode); - } - } else if (handler instanceof OtherwiseHandler) { - String key = getHash(child.toStringWithContent()); - if (configuration.containsSqlNode(key)) { - defaultSqlNodes.add(configuration.getSqlNode(key)); - } else { - SqlNode sqlNode = handler.handleNode(child); - defaultSqlNodes.add(sqlNode); - configuration.addSqlNode(key, sqlNode); - } - } - } - } + private void handleWhenOtherwiseNodes(XNode chooseSqlNode, List ifSqlNodes, List defaultSqlNodes) { + List children = chooseSqlNode.getChildren(); + for (XNode child : children) { + String nodeName = child.getNode().getNodeName(); + NodeHandler handler = nodeHandlerMap.get(nodeName); + if (handler instanceof IfHandler) { + handler.handleNode(child,ifSqlNodes); + } else if (handler instanceof OtherwiseHandler) { + handler.handleNode(child,defaultSqlNodes); + } + } + } private SqlNode getDefaultSqlNode(List defaultSqlNodes) { SqlNode defaultSqlNode = null; From 59d53ddb68b17c616d1a4433812e42cb0d55f284 Mon Sep 17 00:00:00 2001 From: "Inampudi, Sivakiran (CORP)" Date: Fri, 26 May 2023 10:28:03 -0400 Subject: [PATCH 07/13] TXID changed appended --- pom.xml | 4 ++-- .../org/apache/ibatis/mapping/BoundSql.java | 13 +++++++++++-- .../apache/ibatis/util/MyBatisThreadInfo.java | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/apache/ibatis/util/MyBatisThreadInfo.java diff --git a/pom.xml b/pom.xml index 92a17c3ce84..7bab7018c71 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@