[#3000] Add Setting to enable MySQL backslash escaping
This commit is contained in:
parent
64306e5596
commit
426255e6fa
@ -60,10 +60,12 @@ import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.conf.BackslashEscaping.ON;
|
||||
import static org.jooq.conf.ParamType.NAMED;
|
||||
import static org.jooq.conf.ParamType.NAMED_OR_INLINED;
|
||||
import static org.jooq.impl.DSL.name;
|
||||
import static org.jooq.impl.DSL.using;
|
||||
import static org.jooq.impl.Utils.settings;
|
||||
import static org.jooq.tools.StringUtils.leftPad;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -82,6 +84,7 @@ import org.jooq.RenderContext;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.conf.BackslashEscaping;
|
||||
import org.jooq.tools.StringUtils;
|
||||
import org.jooq.types.Interval;
|
||||
|
||||
@ -408,7 +411,7 @@ class Val<T> extends AbstractParam<T> {
|
||||
// Interval extends Number, so let Interval come first!
|
||||
else if (Interval.class.isAssignableFrom(type)) {
|
||||
context.sql("'")
|
||||
.sql(escape(val))
|
||||
.sql(escape(val, context))
|
||||
.sql("'");
|
||||
}
|
||||
|
||||
@ -423,7 +426,7 @@ class Val<T> extends AbstractParam<T> {
|
||||
// The SQLite JDBC driver does not implement the escape syntax
|
||||
// [#1253] SQL Server and Sybase do not implement date literals
|
||||
if (asList(SQLITE).contains(family)) {
|
||||
context.sql("'").sql(escape(val)).sql("'");
|
||||
context.sql("'").sql(escape(val, context)).sql("'");
|
||||
}
|
||||
|
||||
/* [pro] xx
|
||||
@ -432,23 +435,23 @@ class Val<T> extends AbstractParam<T> {
|
||||
x
|
||||
|
||||
xxxx xx xxxxxxx xx xxxxxxxxx x
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx xxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx xxxxxx
|
||||
x
|
||||
xx [/pro] */
|
||||
|
||||
// [#1253] Derby doesn't support the standard literal
|
||||
else if (family == DERBY) {
|
||||
context.keyword("date('").sql(escape(val)).sql("')");
|
||||
context.keyword("date('").sql(escape(val, context)).sql("')");
|
||||
}
|
||||
|
||||
// [#3648] Circumvent a MySQL bug related to date literals
|
||||
else if (family == MYSQL) {
|
||||
context.keyword("{d '").sql(val.toString()).sql("'}");
|
||||
context.keyword("{d '").sql(escape(val, context)).sql("'}");
|
||||
}
|
||||
|
||||
// Most dialects implement SQL standard date literals
|
||||
else {
|
||||
context.keyword("date '").sql(escape(val)).sql("'");
|
||||
context.keyword("date '").sql(escape(val, context)).sql("'");
|
||||
}
|
||||
}
|
||||
else if (type == Timestamp.class) {
|
||||
@ -456,7 +459,7 @@ class Val<T> extends AbstractParam<T> {
|
||||
// The SQLite JDBC driver does not implement the escape syntax
|
||||
// [#1253] SQL Server and Sybase do not implement timestamp literals
|
||||
if (asList(SQLITE).contains(family)) {
|
||||
context.sql("'").sql(escape(val)).sql("'");
|
||||
context.sql("'").sql(escape(val, context)).sql("'");
|
||||
}
|
||||
|
||||
/* [pro] xx
|
||||
@ -465,28 +468,28 @@ class Val<T> extends AbstractParam<T> {
|
||||
x
|
||||
|
||||
xxxx xx xxxxxxx xx xxxxxxxxx x
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx xxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx xxxxxxxxxxx
|
||||
x
|
||||
xx [/pro] */
|
||||
|
||||
// [#1253] Derby doesn't support the standard literal
|
||||
else if (family == DERBY) {
|
||||
context.keyword("timestamp('").sql(escape(val)).sql("')");
|
||||
context.keyword("timestamp('").sql(escape(val, context)).sql("')");
|
||||
}
|
||||
|
||||
// CUBRID timestamps have no fractional seconds
|
||||
else if (family == CUBRID) {
|
||||
context.keyword("datetime '").sql(escape(val)).sql("'");
|
||||
context.keyword("datetime '").sql(escape(val, context)).sql("'");
|
||||
}
|
||||
|
||||
// [#3648] Circumvent a MySQL bug related to date literals
|
||||
else if (family == MYSQL) {
|
||||
context.keyword("{ts '").sql(val.toString()).sql("'}");
|
||||
context.keyword("{ts '").sql(escape(val, context)).sql("'}");
|
||||
}
|
||||
|
||||
// Most dialects implement SQL standard timestamp literals
|
||||
else {
|
||||
context.keyword("timestamp '").sql(escape(val)).sql("'");
|
||||
context.keyword("timestamp '").sql(escape(val, context)).sql("'");
|
||||
}
|
||||
}
|
||||
else if (type == Time.class) {
|
||||
@ -499,33 +502,33 @@ class Val<T> extends AbstractParam<T> {
|
||||
|
||||
/* [pro] xx
|
||||
xxxx xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
|
||||
xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxx
|
||||
x
|
||||
|
||||
xxxx xx xxxxxxx xx xxxxxxxxx x
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx xxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx xxxxxxxxx
|
||||
x
|
||||
xx [/pro] */
|
||||
|
||||
// [#1253] Derby doesn't support the standard literal
|
||||
else if (family == DERBY) {
|
||||
context.keyword("time").sql("('").sql(escape(val)).sql("')");
|
||||
context.keyword("time").sql("('").sql(escape(val, context)).sql("')");
|
||||
}
|
||||
|
||||
// [#3648] Circumvent a MySQL bug related to date literals
|
||||
else if (family == MYSQL) {
|
||||
context.keyword("{t '").sql(val.toString()).sql("'}");
|
||||
context.keyword("{t '").sql(escape(val, context)).sql("'}");
|
||||
}
|
||||
/* [pro] xx
|
||||
xx xxxxxxx xxxxxx xxxxxxx xxxx xxxx xxxxxxxx
|
||||
xxxx xx xxxxxxx xx xxxxxxx x
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxx xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxx
|
||||
x
|
||||
|
||||
xx [/pro] */
|
||||
// Most dialects implement SQL standard time literals
|
||||
else {
|
||||
context.keyword("time").sql(" '").sql(escape(val)).sql("'");
|
||||
context.keyword("time").sql(" '").sql(escape(val, context)).sql("'");
|
||||
}
|
||||
}
|
||||
else if (type.isArray()) {
|
||||
@ -566,7 +569,7 @@ class Val<T> extends AbstractParam<T> {
|
||||
}
|
||||
/* [pro] xx
|
||||
xxxx xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxx
|
||||
xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxx xxxxxx
|
||||
x
|
||||
xx [/pro] */
|
||||
else if (EnumType.class.isAssignableFrom(type)) {
|
||||
@ -589,7 +592,7 @@ class Val<T> extends AbstractParam<T> {
|
||||
// - UUID
|
||||
else {
|
||||
context.sql("'")
|
||||
.sql(escape(val), true)
|
||||
.sql(escape(val, context), true)
|
||||
.sql("'");
|
||||
}
|
||||
}
|
||||
@ -636,10 +639,16 @@ class Val<T> extends AbstractParam<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string literal by replacing <code>'</code> by <code>''</code>
|
||||
* Escape a string literal by replacing <code>'</code> by <code>''</code>, and possibly also backslashes.
|
||||
*/
|
||||
private final String escape(Object val) {
|
||||
return val.toString().replace("'", "''");
|
||||
private final String escape(Object val, Context<?> context) {
|
||||
BackslashEscaping escaping = settings(context.configuration()).getBackslashEscaping();
|
||||
String result = val.toString();
|
||||
|
||||
if (escaping == ON)
|
||||
result = result.replace("\\", "\\\\");
|
||||
|
||||
return result.replace("'", "''");
|
||||
}
|
||||
|
||||
final void bind0(BindContext context) {
|
||||
|
||||
@ -33,6 +33,9 @@
|
||||
Oracle 11g (and potentially, other databases too) implements scalar subquery caching. With this flag
|
||||
set to true, users can automatically profit from this feature in all SQL statements. -->
|
||||
<element name="renderScalarSubqueriesForStoredFunctions" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
|
||||
|
||||
<!-- Whether string literals should be escaped with backslash. -->
|
||||
<element name="backslashEscaping" type="jooq-runtime:BackslashEscaping" minOccurs="0" maxOccurs="1" default="OFF"/>
|
||||
|
||||
<!-- Whether rendered bind values should be rendered as:
|
||||
|
||||
@ -194,4 +197,22 @@
|
||||
<enumeration value="UPPER"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="BackslashEscaping">
|
||||
<restriction base="string">
|
||||
|
||||
<!-- Use the JDBC connection's setting for backslash escaping. In most databases, this
|
||||
is the same as OFF. In MySQL and MariaDB, the actual setting is extracted.
|
||||
|
||||
This is not yet implemented, as the JDBC connection might not be available to the renderer
|
||||
<enumeration value="AUTO"/>
|
||||
-->
|
||||
|
||||
<!-- Always escape backslashes. -->
|
||||
<enumeration value="ON"/>
|
||||
|
||||
<!-- Never escape backslashes. -->
|
||||
<enumeration value="OFF"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</schema>
|
||||
Loading…
Reference in New Issue
Block a user