Index: mapper2/src/com/ibatis/sqlmap/engine/builder/xml/sql-map-2.1.dtd =================================================================== --- mapper2/src/com/ibatis/sqlmap/engine/builder/xml/sql-map-2.1.dtd (revision 0) +++ mapper2/src/com/ibatis/sqlmap/engine/builder/xml/sql-map-2.1.dtd (revision 0) @@ -0,0 +1,537 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapClasspathEntityResolver.java =================================================================== --- mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapClasspathEntityResolver.java (revision 481308) +++ mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlMapClasspathEntityResolver.java (working copy) @@ -31,7 +31,8 @@ public class SqlMapClasspathEntityResolver implements EntityResolver { private static final String SQL_MAP_CONFIG_DTD = "com/ibatis/sqlmap/engine/builder/xml/sql-map-config-2.dtd"; - private static final String SQL_MAP_DTD = "com/ibatis/sqlmap/engine/builder/xml/sql-map-2.dtd"; + private static final String SQL_MAP_DTD_2 = "com/ibatis/sqlmap/engine/builder/xml/sql-map-2.dtd"; + private static final String SQL_MAP_DTD_2_1 = "com/ibatis/sqlmap/engine/builder/xml/sql-map-2.1.dtd"; private static final Map doctypeMap = new HashMap(); @@ -41,10 +42,15 @@ doctypeMap.put("-//iBATIS.com//DTD SQL Map Config 2.0//EN".toUpperCase(), SQL_MAP_CONFIG_DTD); doctypeMap.put("-//ibatis.apache.org//DTD SQL Map Config 2.0//EN".toUpperCase(), SQL_MAP_CONFIG_DTD); - doctypeMap.put("http://www.ibatis.com/dtd/sql-map-2.dtd".toUpperCase(), SQL_MAP_DTD); - doctypeMap.put("http://ibatis.apache.org/dtd/sql-map-2.dtd".toUpperCase(), SQL_MAP_DTD); - doctypeMap.put("-//iBATIS.com//DTD SQL Map 2.0//EN".toUpperCase(), SQL_MAP_DTD); - doctypeMap.put("-//ibatis.apache.org//DTD SQL Map 2.0//EN".toUpperCase(), SQL_MAP_DTD); + doctypeMap.put("http://www.ibatis.com/dtd/sql-map-2.dtd".toUpperCase(), SQL_MAP_DTD_2); + doctypeMap.put("http://ibatis.apache.org/dtd/sql-map-2.dtd".toUpperCase(), SQL_MAP_DTD_2); + doctypeMap.put("-//iBATIS.com//DTD SQL Map 2.0//EN".toUpperCase(), SQL_MAP_DTD_2); + doctypeMap.put("-//ibatis.apache.org//DTD SQL Map 2.0//EN".toUpperCase(), SQL_MAP_DTD_2); + + doctypeMap.put("http://www.ibatis.com/dtd/sql-map-2.1.dtd".toUpperCase(), SQL_MAP_DTD_2_1); + doctypeMap.put("http://ibatis.apache.org/dtd/sql-map-2.1.dtd".toUpperCase(), SQL_MAP_DTD_2_1); + doctypeMap.put("-//iBATIS.com//DTD SQL Map 2.1//EN".toUpperCase(), SQL_MAP_DTD_2_1); + doctypeMap.put("-//ibatis.apache.org//DTD SQL Map 2.1//EN".toUpperCase(), SQL_MAP_DTD_2_1); } Index: mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlStatementParser.java =================================================================== --- mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlStatementParser.java (revision 481308) +++ mapper2/src/com/ibatis/sqlmap/engine/builder/xml/SqlStatementParser.java (working copy) @@ -201,7 +201,7 @@ DynamicSql dynamic = new DynamicSql(vars.client.getDelegate()); StringBuffer sqlBuffer = new StringBuffer(); - isDynamic = parseDynamicTags(n, dynamic, sqlBuffer, isDynamic, false); + isDynamic = parseDynamicTags(n, dynamic, sqlBuffer, isDynamic, false, false); if (statement instanceof InsertStatement) { InsertStatement insertStatement = ((InsertStatement) statement); SelectKeyStatement selectKeyStatement = findAndParseSelectKeyStatement(n, statement); @@ -217,7 +217,7 @@ } - private boolean parseDynamicTags(Node node, DynamicParent dynamic, StringBuffer sqlBuffer, boolean isDynamic, boolean postParseRequired) { + private boolean parseDynamicTags(Node node, DynamicParent dynamic, StringBuffer sqlBuffer, boolean isDynamic, boolean postParseRequired, boolean deferSubstitutions) { vars.errorCtx.setActivity("parsing dynamic SQL tags"); NodeList children = node.getChildNodes(); @@ -232,13 +232,15 @@ SqlText sqlText; - if (postParseRequired) { + if (postParseRequired||deferSubstitutions) { sqlText = new SqlText(); sqlText.setPostParseRequired(postParseRequired); + sqlText.setDeferSubstitutions(deferSubstitutions); sqlText.setText(data); } else { sqlText = PARAM_PARSER.parseInlineParameterMap(vars.client.getDelegate().getTypeHandlerFactory(), data, null); sqlText.setPostParseRequired(postParseRequired); + sqlText.setDeferSubstitutions(deferSubstitutions); } dynamic.addChild(sqlText); @@ -255,7 +257,7 @@ throw new RuntimeException("Could not find SQL statement to include with refid '" + refid + "'"); } } - isDynamic = parseDynamicTags(includeNode, dynamic, sqlBuffer, isDynamic, false); + isDynamic = parseDynamicTags(includeNode, dynamic, sqlBuffer, isDynamic, false, false); } else { vars.errorCtx.setMoreInfo("Check the dynamic tags."); @@ -280,16 +282,20 @@ tag.setCompareValueAttr(attributes.getProperty("compareValue")); tag.setConjunctionAttr(attributes.getProperty("conjunction")); + tag.setDeferSubstitutions(NodeletUtils.getBooleanAttribute( attributes, "deferSubstitutions", false)); + // an iterate ancestor requires a post parse - if(dynamic instanceof SqlTag) { SqlTag parentSqlTag = (SqlTag)dynamic; + if( parentSqlTag.isDeferSubstitutions() ) { + tag.setDeferSubstitutions(true); + } if(parentSqlTag.isPostParseRequired() || tag.getHandler() instanceof IterateTagHandler) { tag.setPostParseRequired(true); } } else if (dynamic instanceof DynamicSql) { - if(tag.getHandler() instanceof IterateTagHandler) { + if( tag.getHandler() instanceof IterateTagHandler) { tag.setPostParseRequired(true); } } @@ -297,7 +303,7 @@ dynamic.addChild(tag); if (child.hasChildNodes()) { - isDynamic = parseDynamicTags(child, tag, sqlBuffer, isDynamic, tag.isPostParseRequired()); + isDynamic = parseDynamicTags(child, tag, sqlBuffer, isDynamic, tag.isPostParseRequired(), tag.isDeferSubstitutions()); } } } Index: mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/DynamicSql.java =================================================================== --- mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/DynamicSql.java (revision 481308) +++ mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/DynamicSql.java (working copy) @@ -107,7 +107,7 @@ String sqlStatement = sqlText.getText(); if (sqlText.isWhiteSpace()) { out.print(sqlStatement); - } else if (!sqlText.isPostParseRequired()) { + } else if (!sqlText.isPostParseRequired() && !sqlText.isDeferSubstitutions()) { // BODY OUT out.print(sqlStatement); @@ -136,6 +136,10 @@ sqlStatement = sqlStatementBuffer.toString(); } + if ( sqlText.isDeferSubstitutions() && SimpleDynamicSql.isSimpleDynamicSql(sqlStatement)) { + sqlStatement = new SimpleDynamicSql(delegate, sqlStatement).getSql(request, parameterObject); + } + sqlText = PARAM_PARSER.parseInlineParameterMap(delegate.getTypeHandlerFactory(), sqlStatement); ParameterMapping[] mappings = sqlText.getParameterMappings(); Index: mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/SqlTag.java =================================================================== --- mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/SqlTag.java (revision 481308) +++ mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/SqlTag.java (working copy) @@ -44,7 +44,8 @@ private List children = new ArrayList(); private boolean postParseRequired = false; - + private boolean deferSubstitutions = false; + public String getName() { return name; } @@ -170,4 +171,18 @@ public void setPostParseRequired(boolean iterateAncestor) { this.postParseRequired = iterateAncestor; } + + /** + * @return Returns the deferSubstitutions. + */ + public boolean isDeferSubstitutions() { + return deferSubstitutions; + } + + /** + * @param iterateAncestor The deferSubstitutions to set. + */ + public void setDeferSubstitutions(boolean deferSubstitutionsAttribute) { + this.deferSubstitutions = deferSubstitutionsAttribute; + } } Index: mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/SqlText.java =================================================================== --- mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/SqlText.java (revision 481308) +++ mapper2/src/com/ibatis/sqlmap/engine/mapping/sql/SqlText.java (working copy) @@ -22,6 +22,7 @@ private String text; private boolean isWhiteSpace; private boolean postParseRequired; + private boolean deferSubstitutions = false; private ParameterMapping[] parameterMappings; @@ -54,5 +55,19 @@ this.postParseRequired = postParseRequired; } + /** + * @return Returns the deferSubstitutions. + */ + public boolean isDeferSubstitutions() { + return deferSubstitutions; + } + + /** + * @param iterateAncestor The deferSubstitutions to set. + */ + public void setDeferSubstitutions(boolean deferSubstitutionsAttribute) { + this.deferSubstitutions = deferSubstitutionsAttribute; + } + }