[#6771] Add a Setting to prevent UPDATE and DELETE statements that lack a WHERE clause

This commit is contained in:
lukaseder 2017-11-01 12:10:00 +01:00
parent 8f56139a6a
commit 1b9fc64906
19 changed files with 648 additions and 34 deletions

View File

@ -65,7 +65,7 @@ public final class Constants {
/**
* The current jooq-runtime XSD file name.
*/
public static final String XSD_RUNTIME = "jooq-runtime-3.10.0.xsd";
public static final String XSD_RUNTIME = "jooq-runtime-3.11.0.xsd";
/**
* The current jooq-runtime XML namespace

View File

@ -0,0 +1,51 @@
package org.jooq.conf;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for ExecuteWithoutWhere.
*
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;simpleType name="ExecuteWithoutWhere"&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string"&gt;
* &lt;enumeration value="IGNORE"/&gt;
* &lt;enumeration value="LOG_DEBUG"/&gt;
* &lt;enumeration value="LOG_INFO"/&gt;
* &lt;enumeration value="LOG_WARN"/&gt;
* &lt;enumeration value="THROW"/&gt;
* &lt;/restriction&gt;
* &lt;/simpleType&gt;
* </pre>
*
*/
@XmlType(name = "ExecuteWithoutWhere")
@XmlEnum
public enum ExecuteWithoutWhere {
IGNORE,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
THROW;
public String value() {
return name();
}
public static ExecuteWithoutWhere fromValue(String v) {
return valueOf(v);
}
}

View File

@ -39,7 +39,7 @@ public class MappedSchema
implements Serializable, Cloneable
{
private final static long serialVersionUID = 31000L;
private final static long serialVersionUID = 31100L;
protected String input;
@XmlElement(type = String.class)
@XmlJavaTypeAdapter(RegexAdapter.class)

View File

@ -35,7 +35,7 @@ public class MappedTable
implements Serializable, Cloneable
{
private final static long serialVersionUID = 31000L;
private final static long serialVersionUID = 31100L;
protected String input;
@XmlElement(type = String.class)
@XmlJavaTypeAdapter(RegexAdapter.class)

View File

@ -31,7 +31,7 @@ import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
private final static QName _Settings_QNAME = new QName("http://www.jooq.org/xsd/jooq-runtime-3.9.0.xsd", "settings");
private final static QName _Settings_QNAME = new QName("http://www.jooq.org/xsd/jooq-runtime-3.11.0.xsd", "settings");
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.jooq.conf
@ -84,7 +84,7 @@ public class ObjectFactory {
* Create an instance of {@link JAXBElement }{@code <}{@link Settings }{@code >}}
*
*/
@XmlElementDecl(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.9.0.xsd", name = "settings")
@XmlElementDecl(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.11.0.xsd", name = "settings")
public JAXBElement<Settings> createSettings(Settings value) {
return new JAXBElement<Settings>(_Settings_QNAME, Settings.class, null, value);
}

View File

@ -33,7 +33,7 @@ public class RenderFormatting
implements Serializable, Cloneable
{
private final static long serialVersionUID = 31000L;
private final static long serialVersionUID = 31100L;
@XmlElement(defaultValue = "\n")
protected String newline = "\n";
@XmlElement(defaultValue = " ")

View File

@ -37,7 +37,7 @@ public class RenderMapping
implements Serializable, Cloneable
{
private final static long serialVersionUID = 31000L;
private final static long serialVersionUID = 31100L;
protected String defaultSchema;
@XmlElementWrapper(name = "schemata")
@XmlElement(name = "schema")

View File

@ -34,7 +34,7 @@ public class Settings
implements Serializable, Cloneable
{
private final static long serialVersionUID = 31000L;
private final static long serialVersionUID = 31100L;
@XmlElement(defaultValue = "true")
protected Boolean renderCatalog = true;
@XmlElement(defaultValue = "true")
@ -98,6 +98,12 @@ public class Settings
protected Boolean inListPadding = false;
@XmlElement(defaultValue = ";")
protected String delimiter = ";";
@XmlElement(defaultValue = "LOG_DEBUG")
@XmlSchemaType(name = "string")
protected ExecuteWithoutWhere executeUpdateWithoutWhere = ExecuteWithoutWhere.LOG_DEBUG;
@XmlElement(defaultValue = "LOG_DEBUG")
@XmlSchemaType(name = "string")
protected ExecuteWithoutWhere executeDeleteWithoutWhere = ExecuteWithoutWhere.LOG_DEBUG;
/**
* Whether any catalog name should be rendered at all.
@ -834,6 +840,54 @@ public class Settings
this.delimiter = value;
}
/**
* [#6771] Specifies whether UPDATE statements are allowed to be executed lacking a WHERE clause. This has no effect on rendering the statements SQL string.
*
* @return
* possible object is
* {@link ExecuteWithoutWhere }
*
*/
public ExecuteWithoutWhere getExecuteUpdateWithoutWhere() {
return executeUpdateWithoutWhere;
}
/**
* Sets the value of the executeUpdateWithoutWhere property.
*
* @param value
* allowed object is
* {@link ExecuteWithoutWhere }
*
*/
public void setExecuteUpdateWithoutWhere(ExecuteWithoutWhere value) {
this.executeUpdateWithoutWhere = value;
}
/**
* [#6771] Specifies whether DELETE statements are allowed to be executed lacking a WHERE clause. This has no effect on rendering the statements SQL string.
*
* @return
* possible object is
* {@link ExecuteWithoutWhere }
*
*/
public ExecuteWithoutWhere getExecuteDeleteWithoutWhere() {
return executeDeleteWithoutWhere;
}
/**
* Sets the value of the executeDeleteWithoutWhere property.
*
* @param value
* allowed object is
* {@link ExecuteWithoutWhere }
*
*/
public void setExecuteDeleteWithoutWhere(ExecuteWithoutWhere value) {
this.executeDeleteWithoutWhere = value;
}
public Settings withRenderCatalog(Boolean value) {
setRenderCatalog(value);
return this;
@ -979,4 +1033,14 @@ public class Settings
return this;
}
public Settings withExecuteUpdateWithoutWhere(ExecuteWithoutWhere value) {
setExecuteUpdateWithoutWhere(value);
return this;
}
public Settings withExecuteDeleteWithoutWhere(ExecuteWithoutWhere value) {
setExecuteDeleteWithoutWhere(value);
return this;
}
}

View File

@ -178,6 +178,22 @@ public final class SettingsTools {
return settings.getRenderMapping();
}
/**
* Lazy access to {@link Settings#getExecuteUpdateWithoutWhere()}.
*/
public static final ExecuteWithoutWhere getExecuteUpdateWithoutWhere(Settings settings) {
ExecuteWithoutWhere result = settings.getExecuteUpdateWithoutWhere();
return result == null ? ExecuteWithoutWhere.LOG_DEBUG : result;
}
/**
* Lazy access to {@link Settings#getExecuteDeleteWithoutWhere()}.
*/
public static final ExecuteWithoutWhere getExecuteDeleteWithoutWhere(Settings settings) {
ExecuteWithoutWhere result = settings.getExecuteDeleteWithoutWhere();
return result == null ? ExecuteWithoutWhere.LOG_DEBUG : result;
}
/**
* Retrieve the configured default settings.
* <p>
@ -214,7 +230,7 @@ public final class SettingsTools {
* Return <code>timeout</code> if it is not <code>0</code>, or the specified
* {@link Settings#getQueryTimeout()}.
*/
public static int getQueryTimeout(int timeout, Settings settings) {
public static final int getQueryTimeout(int timeout, Settings settings) {
return timeout != 0
? timeout
: settings.getQueryTimeout() != null
@ -226,7 +242,7 @@ public final class SettingsTools {
* Return <code>maxRows</code> if it is not <code>0</code>, or the specified
* {@link Settings#getMaxRows()}.
*/
public static int getMaxRows(int maxRows, Settings settings) {
public static final int getMaxRows(int maxRows, Settings settings) {
return maxRows != 0
? maxRows
: settings.getMaxRows() != null
@ -238,7 +254,7 @@ public final class SettingsTools {
* Return <code>fetchSize</code> if it is not <code>0</code>, or the specified
* {@link Settings#getFetchSize()}.
*/
public static int getFetchSize(int fetchSize, Settings settings) {
public static final int getFetchSize(int fetchSize, Settings settings) {
return fetchSize != 0
? fetchSize
: settings.getFetchSize() != null

View File

@ -5,5 +5,5 @@
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.9.0.xsd", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.11.0.xsd", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.jooq.conf;

View File

@ -90,8 +90,11 @@ import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.Table;
import org.jooq.UpdateQuery;
import org.jooq.conf.ExecuteWithoutWhere;
import org.jooq.conf.RenderNameStyle;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.Tools.DataKey;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.jdbc.JDBCUtils;
/**
@ -103,6 +106,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractQuery {
* Generated UID
*/
private static final long serialVersionUID = -7438014075226919192L;
private static final JooqLogger log = JooqLogger.getLogger(AbstractQuery.class);
@ -314,6 +318,29 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractQuery {
abstract void accept0(Context<?> ctx);
/**
* [#6771] Handle the case where a statement is executed without a WHERE clause.
*/
void executeWithoutWhere(String message, ExecuteWithoutWhere executeWithoutWhere) {
switch (executeWithoutWhere) {
case IGNORE:
break;
case LOG_DEBUG:
if (log.isDebugEnabled())
log.debug(message, "A statement is executed without WHERE clause");
break;
case LOG_INFO:
if (log.isInfoEnabled())
log.info(message, "A statement is executed without WHERE clause");
break;
case LOG_WARN:
log.warn(message, "A statement is executed without WHERE clause");
break;
case THROW:
throw new DataAccessException("A statement is executed without WHERE clause");
}
}
final void toSQLReturning(Context<?> ctx) {
if (!returning.isEmpty()) {
switch (ctx.family()) {

View File

@ -457,7 +457,7 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
* method.
*/
@Override
public boolean isExecutable() {
public /* non-final */ boolean isExecutable() {
return true;
}

View File

@ -64,7 +64,11 @@ final class ConditionProviderImpl extends AbstractQueryPart implements Condition
}
final Condition getWhere() {
return condition == null ? trueCondition() : condition;
return hasWhere() ? condition : trueCondition();
}
final boolean hasWhere() {
return condition != null;
}
// -------------------------------------------------------------------------
@ -88,10 +92,10 @@ final class ConditionProviderImpl extends AbstractQueryPart implements Condition
@Override
public final void addConditions(Operator operator, Condition conditions) {
if (getWhere() instanceof TrueCondition)
condition = conditions;
else
if (hasWhere())
condition = DSL.condition(operator, getWhere(), conditions);
else
condition = conditions;
}
@Override

View File

@ -41,6 +41,7 @@ import static org.jooq.Clause.DELETE_RETURNING;
import static org.jooq.Clause.DELETE_WHERE;
import static org.jooq.SQLDialect.MARIADB;
import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.conf.SettingsTools.getExecuteDeleteWithoutWhere;
import static org.jooq.impl.Keywords.K_DELETE;
import static org.jooq.impl.Keywords.K_FROM;
import static org.jooq.impl.Keywords.K_WHERE;
@ -79,6 +80,10 @@ final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implem
return condition.getWhere();
}
final boolean hasWhere() {
return condition.hasWhere();
}
@Override
public final void addConditions(Collection<? extends Condition> conditions) {
condition.addConditions(conditions);
@ -133,11 +138,10 @@ final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implem
.end(DELETE_DELETE)
.start(DELETE_WHERE);
if (!(getWhere() instanceof TrueCondition)) {
if (hasWhere())
ctx.formatSeparator()
.visit(K_WHERE).sql(' ')
.visit(getWhere());
}
ctx.end(DELETE_WHERE)
.start(DELETE_RETURNING);
@ -151,4 +155,14 @@ final class DeleteQueryImpl<R extends Record> extends AbstractDMLQuery<R> implem
public final Clause[] clauses(Context<?> ctx) {
return CLAUSES;
}
@Override
public final boolean isExecutable() {
// [#6771] Take action when DELETE query has no WHERE clause
if (!condition.hasWhere())
executeWithoutWhere("DELETE without WHERE", getExecuteDeleteWithoutWhere(configuration().settings()));
return super.isExecutable();
}
}

View File

@ -276,7 +276,7 @@ final class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
.visit(updateMap)
.formatIndentLockEnd();
if (!(condition.getWhere() instanceof TrueCondition))
if (condition.hasWhere())
ctx.formatSeparator()
.visit(K_WHERE)
.sql(' ')

View File

@ -1220,7 +1220,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// ------------
context.start(SELECT_WHERE);
if (getWhere().getWhere() instanceof TrueCondition && semiAntiJoinPredicates == null)
if (!getWhere().hasWhere() && semiAntiJoinPredicates == null)
;
else {
ConditionProviderImpl where = new ConditionProviderImpl();
@ -1228,7 +1228,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
if (semiAntiJoinPredicates != null)
where.addConditions(semiAntiJoinPredicates);
if (!(getWhere().getWhere() instanceof TrueCondition))
if (getWhere().hasWhere())
where.addConditions(getWhere());
context.formatSeparator()
@ -1247,23 +1247,21 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// syntax
context.start(SELECT_START_WITH);
if (!(getConnectByStartWith().getWhere() instanceof TrueCondition)) {
if (getConnectByStartWith().hasWhere())
context.formatSeparator()
.visit(K_START_WITH)
.sql(' ')
.visit(getConnectByStartWith());
}
context.end(SELECT_START_WITH);
context.start(SELECT_CONNECT_BY);
if (!(getConnectBy().getWhere() instanceof TrueCondition)) {
if (getConnectBy().hasWhere()) {
context.formatSeparator()
.visit(K_CONNECT_BY);
if (connectByNoCycle) {
if (connectByNoCycle)
context.sql(' ').visit(K_NOCYCLE);
}
context.sql(' ').visit(getConnectBy());
}
@ -1315,12 +1313,11 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// -------------
context.start(SELECT_HAVING);
if (!(getHaving().getWhere() instanceof TrueCondition)) {
if (getHaving().hasWhere())
context.formatSeparator()
.visit(K_HAVING)
.sql(' ')
.visit(getHaving());
}
context.end(SELECT_HAVING);

View File

@ -46,6 +46,7 @@ import static org.jooq.Clause.UPDATE_WHERE;
// ...
import static org.jooq.SQLDialect.POSTGRES_10;
// ...
import static org.jooq.conf.SettingsTools.getExecuteUpdateWithoutWhere;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.Keywords.K_FROM;
import static org.jooq.impl.Keywords.K_ROW;
@ -495,6 +496,10 @@ final class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
return condition.getWhere();
}
final boolean hasWhere() {
return condition.hasWhere();
}
@Override
final void accept0(Context<?> ctx) {
boolean declareTables = ctx.declareTables();
@ -616,11 +621,10 @@ final class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
ctx.start(UPDATE_WHERE);
if (!(getWhere() instanceof TrueCondition)) {
if (hasWhere())
ctx.formatSeparator()
.visit(K_WHERE).sql(' ')
.visit(getWhere());
}
ctx.end(UPDATE_WHERE)
.start(UPDATE_RETURNING);
@ -637,6 +641,11 @@ final class UpdateQueryImpl<R extends Record> extends AbstractStoreQuery<R> impl
@Override
public final boolean isExecutable() {
// [#6771] Take action when UPDATE query has no WHERE clause
if (!condition.hasWhere())
executeWithoutWhere("UPDATE without WHERE", getExecuteUpdateWithoutWhere(configuration().settings()));
return updateMap.size() > 0 || multiRow != null;
}
}

View File

@ -12,16 +12,16 @@
<jaxb:globalBindings>
<!-- Force all classes implements Serializable -->
<xjc:serializable uid="31000" />
<xjc:serializable uid="31100" />
</jaxb:globalBindings>
<!-- [#2928] Regular expressions -->
<jaxb:bindings schemaLocation="../../xsd/jooq-runtime-3.10.0.xsd" multiple="true" node="//xs:element[@name='inputExpression']">
<jaxb:bindings schemaLocation="../../xsd/jooq-runtime-3.11.0.xsd" multiple="true" node="//xs:element[@name='inputExpression']">
<xjc:javaType name="java.util.regex.Pattern" adapter="org.jooq.conf.RegexAdapter"/>
</jaxb:bindings>
<!-- Annotate the following classes with @SuppressWarnings -->
<jaxb:bindings schemaLocation="../../xsd/jooq-runtime-3.10.0.xsd" multiple="true" node="//xs:complexType">
<jaxb:bindings schemaLocation="../../xsd/jooq-runtime-3.11.0.xsd" multiple="true" node="//xs:complexType">
<inheritance:extends>org.jooq.conf.SettingsBase</inheritance:extends>
<inheritance:implements>java.lang.Cloneable</inheritance:implements>
<annox:annotate>

View File

@ -0,0 +1,432 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:jooq-runtime="http://www.jooq.org/xsd/jooq-runtime-3.11.0.xsd"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
targetNamespace="http://www.jooq.org/xsd/jooq-runtime-3.11.0.xsd"
elementFormDefault="qualified"
jxb:version="2.1">
<element name="settings" type="jooq-runtime:Settings"/>
<complexType name="Settings">
<annotation><appinfo><jxb:class><jxb:javadoc><![CDATA[Settings that influence the way jOOQ renders SQL code.]]></jxb:javadoc></jxb:class></appinfo></annotation>
<all>
<element name="renderCatalog" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether any catalog name should be rendered at all.
<p>
Use this for single-catalog environments, or when all objects are made
available using synonyms]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderSchema" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether any schema name should be rendered at all.
<p>
Setting this to false also implicitly sets "renderCatalog" to false.
<p>
Use this for single-schema environments, or when all objects are made
available using synonyms]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderMapping" type="jooq-runtime:RenderMapping" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Configure render mapping for runtime schema / table rewriting in
generated SQL.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderNameStyle" type="jooq-runtime:RenderNameStyle" minOccurs="0" maxOccurs="1" default="QUOTED">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether rendered schema, table, column names, etc should be quoted
in rendered SQL, or transformed in any other way.
<p>
This is set to "QUOTED" by default for backwards-compatibility]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderKeywordStyle" type="jooq-runtime:RenderKeywordStyle" minOccurs="0" maxOccurs="1" default="AS_IS">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether SQL keywords should be rendered with upper or lower case.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderFormatted" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether rendered SQL should be pretty-printed.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderFormatting" type="jooq-runtime:RenderFormatting" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[All sorts of formatting flags / settings.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderScalarSubqueriesForStoredFunctions" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether stored function calls should be wrapped in scalar subqueries.
<p>
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.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="backslashEscaping" type="jooq-runtime:BackslashEscaping" minOccurs="0" maxOccurs="1" default="DEFAULT">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether string literals should be escaped with 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>
Possibilities include:
- question marks
- named parameters
- named or inlined parameters
- inlined parameters
This value is overridden by statementType == STATIC_STATEMENT, in
case of which, this defaults to INLINED]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="paramCastMode" type="jooq-runtime:ParamCastMode" minOccurs="0" maxOccurs="1" default="DEFAULT">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether rendered bind values should be cast to their respective type.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="statementType" type="jooq-runtime:StatementType" minOccurs="0" maxOccurs="1" default="PREPARED_STATEMENT">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The type of statement that is to be executed.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="executeLogging" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[When set to true, this will add jOOQ's default logging ExecuteListeners.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="executeWithOptimisticLocking" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether store() and delete() methods should be executed with optimistic locking.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="executeWithOptimisticLockingExcludeUnversioned" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether store() and delete() methods should be executed with optimistic locking also on "unversioned" tables,
i.e. on tables that do not have a version and/or timestamp column.
<p>
This flag has no effect when "executeWithOptimisticLocking" is turned off.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="attachRecords" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether fetched records should be attached to the fetching configuration.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="updatablePrimaryKeys" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether primary key values are deemed to be "updatable" in jOOQ.
<p>
Setting this to "true" will allow for updating primary key values through
UpdatableRecord.store() and UpdatableRecord.update().]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="reflectionCaching" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether reflection information should be cached in the configuration.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="throwExceptions" type="jooq-runtime:ThrowExceptions" minOccurs="0" maxOccurs="1" default="THROW_ALL">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[A strategy defining how exceptions from the database / JDBC driver should be propagated]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="fetchWarnings" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether warnings should be fetched after each query execution.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="returnAllOnUpdatableRecord" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether calls to store(), insert() and update() should return all columns, not just identity columns.
<p>
Do note that only few databases support this feature. It is supported only in case the INSERT's or UPDATE's
RETURNING clause is fully supported, also for non-IDENTITY columns.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="returnRecordToPojo" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether calls to store(), insert(), update(), and delete() that are called on an UpdatableRecord
that is created from a POJO (e.g. in a DAO) should return all Record values to the POJO, including
IDENTITY values, and if <returnAllOnUpdatableRecord/> is active, also other values.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="mapJPAAnnotations" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether JPA annotations should be considered by the DefaultRecordMapper.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="queryTimeout" type="int" minOccurs="0" maxOccurs="1" default="0">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The default JDBC queryTimeout property that should be applied to all
jOOQ queries, for which no specific queryTimeout was specified.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="maxRows" type="int" minOccurs="0" maxOccurs="1" default="0">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The default JDBC maxRows property that should be applied to all
jOOQ queries, for which no specific maxRows value was specified.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="fetchSize" type="int" minOccurs="0" maxOccurs="1" default="0">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The default JDBC fetchSize property that should be applied to all
jOOQ queries, for which no specific fetchSize value was specified.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="debugInfoOnStackTrace" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[[#5570] Whether exception stack traces should be enhanced with additional debug information.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="inListPadding" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[[#5600] Whether IN lists in IN predicates should be padded to powers of 2.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="delimiter" type="string" minOccurs="0" maxOccurs="1" default=";">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[[#5826] The delimiter character to be used to delimit statements in batches.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="executeUpdateWithoutWhere" type="jooq-runtime:ExecuteWithoutWhere" minOccurs="0" maxOccurs="1" default="LOG_DEBUG">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[[#6771] Specifies whether UPDATE statements are allowed to be executed lacking a WHERE clause. This has no effect on rendering the statements SQL string.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="executeDeleteWithoutWhere" type="jooq-runtime:ExecuteWithoutWhere" minOccurs="0" maxOccurs="1" default="LOG_DEBUG">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[[#6771] Specifies whether DELETE statements are allowed to be executed lacking a WHERE clause. This has no effect on rendering the statements SQL string.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
</all>
</complexType>
<complexType name="RenderMapping">
<annotation><appinfo><jxb:class><jxb:javadoc><![CDATA[The runtime schema and table mapping.]]></jxb:javadoc></jxb:class></appinfo></annotation>
<all>
<element name="defaultSchema" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The default schema as defined in {@link org.jooq.Schema#getName()}.
<p>
This schema will be omitted in rendered SQL.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="schemata" type="jooq-runtime:MappedSchemata" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The mapped schemata configuration.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
</all>
</complexType>
<complexType name="MappedSchemata">
<sequence>
<element name="schema" type="jooq-runtime:MappedSchema" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="MappedSchema">
<annotation><appinfo><jxb:class><jxb:javadoc><![CDATA[A schema mapping configuration.]]></jxb:javadoc></jxb:class></appinfo></annotation>
<all>
<element name="input" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The input schema name as defined in {@link org.jooq.Schema#getName()}
<p>
Either &lt;input/> or &lt;inputExpression/> must be provided]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="inputExpression" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[A regular expression matching the input schema name as defined in {@link org.jooq.Schema#getName()}
Either &lt;input/> or &lt;inputExpression/> must be provided]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="output" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The output schema as it will be rendered in SQL.
<ul>
<li>When this is omitted, you can still apply table mapping.</li>
<li>When &lt;input/> is provided, &lt;output/> is a constant value.</li>
<li>When &lt;inputExpression/> is provided, &lt;output/> is a replacement expression</li>
</ul>]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="tables" type="jooq-runtime:MappedTables" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Configure table mapping for runtime table rewriting in generated SQL.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
</all>
</complexType>
<complexType name="MappedTables">
<sequence>
<element name="table" type="jooq-runtime:MappedTable" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="MappedTable">
<annotation><appinfo><jxb:class><jxb:javadoc><![CDATA[A table mapping configuration.]]></jxb:javadoc></jxb:class></appinfo></annotation>
<all>
<element name="input" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The input table as defined in {@link org.jooq.Table#getName()}
Either &lt;input/> or &lt;inputExpression/> must be provided.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="inputExpression" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[A regular expression matching the input table name as defined in {@link org.jooq.Table#getName()}
Either &lt;input/> or &lt;inputExpression/> must be provided]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="output" type="string" minOccurs="1" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The output table as it will be rendered in SQL.
<ul>
<li>When &lt;input/> is provided, &lt;output/> is a constant value.</li>
<li>When &lt;inputExpression/> is provided, &lt;output/> is a replacement expression.</li>
</ul>]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
</all>
</complexType>
<simpleType name="ParamType">
<restriction base="string">
<!-- Execute statements with indexed parameters, the way JDBC expects them -->
<enumeration value="INDEXED"/>
<!-- Execute statements with named parameters -->
<enumeration value="NAMED"/>
<!-- Execute statements with named parameters, if a name is given, or inlined parameters otherwise -->
<enumeration value="NAMED_OR_INLINED"/>
<!-- Execute statements with inlined parameters -->
<enumeration value="INLINED"/>
</restriction>
</simpleType>
<simpleType name="ParamCastMode">
<restriction base="string">
<!-- Bind values are always cast to their respective type. -->
<enumeration value="ALWAYS"/>
<!-- Bind values are cast to their respective type when needed.
Some databases are not able to delay bind value type inference until the execution of a statement.
They will either reject the value of unknown type, or assume a possibly inappropriate type. In these
cases, jOOQ will generate an explicit cast(? as datatype) expression around the bind value to help
the query parser do its job. The exact behaviour of this mode is undefined and subject to change. -->
<enumeration value="DEFAULT"/>
<!-- Bind values are never cast to their respective type. -->
<enumeration value="NEVER"/>
</restriction>
</simpleType>
<simpleType name="StatementType">
<restriction base="string">
<!-- Execute statements with inlined bind values, avoiding JDBC's
PreparedStatements -->
<enumeration value="STATIC_STATEMENT"/>
<!-- Execute statements with bind values, using JDBC's
PreparedStatements -->
<enumeration value="PREPARED_STATEMENT"/>
</restriction>
</simpleType>
<simpleType name="RenderNameStyle">
<restriction base="string">
<!-- Render object names quoted, as defined in the database. Use this
to stay on the safe side with case-sensitivity and special
characters. For instance:
Oracle : "SYS"."ALL_TAB_COLS"
MySQL : `information_schema`.`TABLES`
SQL Server: [INFORMATION_SCHEMA].[TABLES] -->
<enumeration value="QUOTED"/>
<!-- Render object names, as defined in the database. For instance:
Oracle : SYS.ALL_TAB_COLS
MySQL : information_schema.TABLES
SQL Server: INFORMATION_SCHEMA.TABLES -->
<enumeration value="AS_IS"/>
<!-- Force rendering object names in lower case. For instance:
Oracle : sys.all_tab_cols
MySQL : information_schema.tables
SQL Server: information_schema.tables -->
<enumeration value="LOWER"/>
<!-- Force rendering object names in upper case. For instance:
Oracle : SYS.ALL_TAB_COLS
MySQL : INFORMATION_SCHEMA.TABLES
SQL Server: INFORMATION_SCHEMA.TABLES -->
<enumeration value="UPPER"/>
</restriction>
</simpleType>
<simpleType name="RenderKeywordStyle">
<restriction base="string">
<!-- Keywords are rendered "as is", i.e. mostly in lower case. For instance:
select .. from .. where .. -->
<enumeration value="AS_IS"/>
<!-- Keywords are rendered in lower case. For instance:
select .. from .. where .. -->
<enumeration value="LOWER"/>
<!-- Keywords are rendered in upper case. For instance:
SELECT .. FROM .. WHERE .. -->
<enumeration value="UPPER"/>
</restriction>
</simpleType>
<complexType name="RenderFormatting">
<annotation><appinfo><jxb:class><jxb:javadoc><![CDATA[All sorts of formatting flags / settings.]]></jxb:javadoc></jxb:class></appinfo></annotation>
<all>
<element name="newline" type="string" minOccurs="0" maxOccurs="1" default="&#10;">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The character to be used for line breaks.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="indentation" type="string" minOccurs="0" maxOccurs="1" default=" ">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The characters to be used for indentation.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="printMargin" type="int" minOccurs="0" maxOccurs="1" default="80">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The print margin after which (some) formatted elements will break lines.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
</all>
</complexType>
<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"/>
-->
<!-- Use the database's most sensible default value for ON (MySQL, MariaDB) / OFF (all other databases) -->
<enumeration value="DEFAULT"/>
<!-- Always escape backslashes. -->
<enumeration value="ON"/>
<!-- Never escape backslashes. -->
<enumeration value="OFF"/>
</restriction>
</simpleType>
<simpleType name="ThrowExceptions">
<restriction base="string">
<!-- Collect all exceptions from a batch and throw them all together -->
<enumeration value="THROW_ALL"/>
<!-- Throw only the first exception from a batch -->
<enumeration value="THROW_FIRST"/>
<!-- Throw no exceptions, but collect them in ResultOrRows -->
<enumeration value="THROW_NONE"/>
</restriction>
</simpleType>
<simpleType name="ExecuteWithoutWhere">
<restriction base="string">
<!-- UPDATE and DELETE statements are allowed to lack a WHERE clause -->
<enumeration value="IGNORE"/>
<!-- UPDATE and DELETE statements are allowed to lack a WHERE clause, but this is logged as DEBUG level -->
<enumeration value="LOG_DEBUG"/>
<!-- UPDATE and DELETE statements are allowed to lack a WHERE clause, but this is logged as INFO level -->
<enumeration value="LOG_INFO"/>
<!-- UPDATE and DELETE statements are allowed to lack a WHERE clause, but this is logged as WARN level -->
<enumeration value="LOG_WARN"/>
<!-- UPDATE and DELETE statements are not allowed to lack a WHERE clause -->
<enumeration value="THROW"/>
</restriction>
</simpleType>
</schema>