[#5873] Add Setting.quoteEscaping to allow for alternative escaping of single quotes
This commit is contained in:
parent
8b501a9236
commit
eb3ee64587
47
jOOQ/src/main/java/org/jooq/conf/QuoteEscaping.java
Normal file
47
jOOQ/src/main/java/org/jooq/conf/QuoteEscaping.java
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
package org.jooq.conf;
|
||||
|
||||
import javax.xml.bind.annotation.XmlEnum;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for QuoteEscaping.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
* <pre>
|
||||
* <simpleType name="QuoteEscaping">
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}string">
|
||||
* <enumeration value="DEFAULT"/>
|
||||
* <enumeration value="QUOTE"/>
|
||||
* <enumeration value="ESCAPE"/>
|
||||
* </restriction>
|
||||
* </simpleType>
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
@XmlType(name = "QuoteEscaping")
|
||||
@XmlEnum
|
||||
public enum QuoteEscaping {
|
||||
|
||||
DEFAULT,
|
||||
QUOTE,
|
||||
BACKSLASH;
|
||||
|
||||
public String value() {
|
||||
return name();
|
||||
}
|
||||
|
||||
public static QuoteEscaping fromValue(String v) {
|
||||
return valueOf(v);
|
||||
}
|
||||
|
||||
}
|
||||
@ -54,6 +54,9 @@ public class Settings
|
||||
@XmlElement(defaultValue = "DEFAULT")
|
||||
@XmlSchemaType(name = "string")
|
||||
protected BackslashEscaping backslashEscaping = BackslashEscaping.DEFAULT;
|
||||
@XmlElement(defaultValue = "DEFAULT")
|
||||
@XmlSchemaType(name = "string")
|
||||
protected QuoteEscaping quoteEscaping = QuoteEscaping.DEFAULT;
|
||||
@XmlElement(defaultValue = "INDEXED")
|
||||
@XmlSchemaType(name = "string")
|
||||
protected ParamType paramType = ParamType.INDEXED;
|
||||
@ -347,6 +350,30 @@ public class Settings
|
||||
this.backslashEscaping = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether string literals should be escaped with backslash.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link QuoteEscaping }
|
||||
*
|
||||
*/
|
||||
public QuoteEscaping getQuoteEscaping() {
|
||||
return quoteEscaping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the quoteEscaping property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link QuoteEscaping }
|
||||
*
|
||||
*/
|
||||
public void setQuoteEscaping(QuoteEscaping value) {
|
||||
this.quoteEscaping = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify how bind variables are to be rendered.
|
||||
* <p>
|
||||
@ -1064,6 +1091,11 @@ public class Settings
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withQuoteEscaping(QuoteEscaping value) {
|
||||
setQuoteEscaping(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withParamType(ParamType value) {
|
||||
setParamType(value);
|
||||
return this;
|
||||
|
||||
@ -135,6 +135,20 @@ public final class SettingsTools {
|
||||
return BackslashEscaping.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value QuoteEscaping value.
|
||||
*/
|
||||
public static final QuoteEscaping getQuoteEscaping(Settings settings) {
|
||||
if (settings != null) {
|
||||
QuoteEscaping result = settings.getQuoteEscaping();
|
||||
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
return QuoteEscaping.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a {@link PreparedStatement} should be executed.
|
||||
*/
|
||||
|
||||
@ -87,6 +87,7 @@ import static org.jooq.impl.Tools.attachRecords;
|
||||
import static org.jooq.impl.Tools.convertBytesToHex;
|
||||
import static org.jooq.impl.Tools.getMappedUDTName;
|
||||
import static org.jooq.impl.Tools.needsBackslashEscaping;
|
||||
import static org.jooq.impl.Tools.quotesNeedsBackslashEscaping;
|
||||
import static org.jooq.tools.jdbc.JDBCUtils.safeClose;
|
||||
import static org.jooq.tools.jdbc.JDBCUtils.safeFree;
|
||||
import static org.jooq.tools.jdbc.JDBCUtils.wasNull;
|
||||
@ -711,7 +712,12 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
if (needsBackslashEscaping(context.configuration()))
|
||||
result = StringUtils.replace(result, "\\", "\\\\");
|
||||
|
||||
return StringUtils.replace(result, "'", "''");
|
||||
if (quotesNeedsBackslashEscaping(context.configuration()))
|
||||
result = StringUtils.replace(result, "'", "\\'");
|
||||
else
|
||||
result = StringUtils.replace(result, "'", "''");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -58,6 +58,7 @@ import static org.jooq.conf.ParamType.INLINED;
|
||||
import static org.jooq.conf.ParamType.NAMED;
|
||||
import static org.jooq.conf.ParamType.NAMED_OR_INLINED;
|
||||
import static org.jooq.conf.SettingsTools.getBackslashEscaping;
|
||||
import static org.jooq.conf.SettingsTools.getQuoteEscaping;
|
||||
import static org.jooq.conf.SettingsTools.reflectionCaching;
|
||||
import static org.jooq.conf.SettingsTools.updatablePrimaryKeys;
|
||||
import static org.jooq.conf.ThrowExceptions.THROW_FIRST;
|
||||
@ -226,6 +227,7 @@ import org.jooq.UDT;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.conf.BackslashEscaping;
|
||||
import org.jooq.conf.QuoteEscaping;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.ThrowExceptions;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
@ -570,6 +572,7 @@ final class Tools {
|
||||
private static final char[] TOKEN_MULTI_LINE_COMMENT_CLOSE = { '*', '/' };
|
||||
private static final char[] TOKEN_APOS = { '\'' };
|
||||
private static final char[] TOKEN_ESCAPED_APOS = { '\'', '\'' };
|
||||
private static final char[] TOKEN_BACKSLASH_ESCAPED_APOS = { '\\', '\'' };
|
||||
|
||||
/**
|
||||
* "Suffixes" that are placed behind a "?" character to form an operator,
|
||||
@ -1796,6 +1799,7 @@ final class Tools {
|
||||
|
||||
// [#3630] Depending on this setting, we need to consider backslashes as escape characters within string literals.
|
||||
boolean needsBackslashEscaping = needsBackslashEscaping(ctx.configuration());
|
||||
boolean quotesNeedsBackslashEscaping = quotesNeedsBackslashEscaping(ctx.configuration());
|
||||
|
||||
characterLoop:
|
||||
for (int i = 0; i < sqlChars.length; i++) {
|
||||
@ -1848,7 +1852,10 @@ final class Tools {
|
||||
render.sql(sqlChars[i++]);
|
||||
|
||||
// Consume an escaped apostrophe
|
||||
else if (peek(sqlChars, i, TOKEN_ESCAPED_APOS))
|
||||
else if (!quotesNeedsBackslashEscaping && peek(sqlChars, i, TOKEN_ESCAPED_APOS))
|
||||
render.sql(sqlChars[i++]);
|
||||
|
||||
else if (quotesNeedsBackslashEscaping && peek(sqlChars, i, TOKEN_BACKSLASH_ESCAPED_APOS))
|
||||
render.sql(sqlChars[i++]);
|
||||
|
||||
// Break on the terminal string literal delimiter
|
||||
@ -2071,6 +2078,14 @@ final class Tools {
|
||||
return escaping == ON || (escaping == DEFAULT && REQUIRES_BACKSLASH_ESCAPING.contains(configuration.family()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether quotes escaping with backslashes is needed.
|
||||
*/
|
||||
static final boolean quotesNeedsBackslashEscaping(Configuration configuration) {
|
||||
QuoteEscaping escaping = getQuoteEscaping(configuration.settings());
|
||||
return escaping == QuoteEscaping.BACKSLASH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek for a string at a given <code>index</code> of a <code>char[]</code>
|
||||
*
|
||||
|
||||
@ -63,6 +63,10 @@ set to true, users can automatically profit from this feature in all SQL stateme
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether string literals should be escaped with backslash.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="quoteEscaping" type="jooq-runtime:QuoteEscaping" minOccurs="0" maxOccurs="1" default="DEFAULT">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether quotes in strings literals should be escaped with quote repeating or backslash.]]></jxb:javadoc></jxb:property></appinfo></annotation>
|
||||
</element>
|
||||
|
||||
<element name="paramType" type="jooq-runtime:ParamType" minOccurs="0" maxOccurs="1" default="INDEXED">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Specify how bind variables are to be rendered.
|
||||
<p>
|
||||
@ -423,6 +427,20 @@ Either <input/> or <inputExpression/> must be provided]]></jxb:javadoc></j
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="QuoteEscaping">
|
||||
<restriction base="string">
|
||||
|
||||
<!-- Use the database's most sensible default value -->
|
||||
<enumeration value="DEFAULT"/>
|
||||
|
||||
<!-- Escape with quote repeat. -->
|
||||
<enumeration value="QUOTE"/>
|
||||
|
||||
<!-- Escape with backslash. -->
|
||||
<enumeration value="BACKSLASH"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="ThrowExceptions">
|
||||
<restriction base="string">
|
||||
|
||||
@ -470,4 +488,4 @@ Either <input/> or <inputExpression/> must be provided]]></jxb:javadoc></j
|
||||
<enumeration value="THROW_ON_FAILURE"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</schema>
|
||||
</schema>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user