[#7153] Allow for configuring a locale to be used for upper/lower casing inside of jOOQ
This commit is contained in:
parent
0884090495
commit
d4da4946f8
115
jOOQ/src/main/java/org/jooq/conf/LocaleAdapter.java
Normal file
115
jOOQ/src/main/java/org/jooq/conf/LocaleAdapter.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq.conf;
|
||||
|
||||
import static org.jooq.tools.StringUtils.defaultIfNull;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class LocaleAdapter extends XmlAdapter<String, Locale> {
|
||||
|
||||
private static final Pattern SIMPLE_LANGUAGE_TAG = Pattern.compile("(\\w+)(?:-(\\w+)(?:-(\\w+))?)?");
|
||||
|
||||
@Override
|
||||
public Locale unmarshal(String v) throws Exception {
|
||||
Locale result = null;
|
||||
|
||||
if (v == null)
|
||||
return result;
|
||||
|
||||
|
||||
result = Locale.forLanguageTag(v);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String marshal(Locale v) throws Exception {
|
||||
String result = null;
|
||||
|
||||
if (v == null)
|
||||
return result;
|
||||
|
||||
|
||||
result = v.toLanguageTag();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -9,11 +9,13 @@
|
||||
package org.jooq.conf;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlSchemaType;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
|
||||
/**
|
||||
@ -46,6 +48,9 @@ public class Settings
|
||||
@XmlElement(defaultValue = "AS_IS")
|
||||
@XmlSchemaType(name = "string")
|
||||
protected RenderKeywordStyle renderKeywordStyle = RenderKeywordStyle.AS_IS;
|
||||
@XmlElement(type = String.class)
|
||||
@XmlJavaTypeAdapter(LocaleAdapter.class)
|
||||
protected Locale renderLocale;
|
||||
@XmlElement(defaultValue = "false")
|
||||
protected Boolean renderFormatted = false;
|
||||
protected RenderFormatting renderFormatting;
|
||||
@ -258,6 +263,30 @@ public class Settings
|
||||
this.renderKeywordStyle = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Locale to be used with any locale dependent logic (as e.g. transforming names to lower / uppper case).
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public Locale getRenderLocale() {
|
||||
return renderLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the renderLocale property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setRenderLocale(Locale value) {
|
||||
this.renderLocale = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether rendered SQL should be pretty-printed.
|
||||
*
|
||||
@ -1160,6 +1189,11 @@ public class Settings
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withRenderLocale(Locale value) {
|
||||
setRenderLocale(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withRenderFormatted(Boolean value) {
|
||||
setRenderFormatted(value);
|
||||
return this;
|
||||
@ -1363,6 +1397,11 @@ public class Settings
|
||||
sb.append(renderKeywordStyle);
|
||||
sb.append("</renderKeywordStyle>");
|
||||
}
|
||||
if (renderLocale!= null) {
|
||||
sb.append("<renderLocale>");
|
||||
sb.append(renderLocale);
|
||||
sb.append("</renderLocale>");
|
||||
}
|
||||
if (renderFormatted!= null) {
|
||||
sb.append("<renderFormatted>");
|
||||
sb.append(renderFormatted);
|
||||
@ -1598,6 +1637,15 @@ public class Settings
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (renderLocale == null) {
|
||||
if (other.renderLocale!= null) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!renderLocale.equals(other.renderLocale)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (renderFormatted == null) {
|
||||
if (other.renderFormatted!= null) {
|
||||
return false;
|
||||
@ -1925,6 +1973,7 @@ public class Settings
|
||||
result = ((prime*result)+((renderMapping == null)? 0 :renderMapping.hashCode()));
|
||||
result = ((prime*result)+((renderNameStyle == null)? 0 :renderNameStyle.hashCode()));
|
||||
result = ((prime*result)+((renderKeywordStyle == null)? 0 :renderKeywordStyle.hashCode()));
|
||||
result = ((prime*result)+((renderLocale == null)? 0 :renderLocale.hashCode()));
|
||||
result = ((prime*result)+((renderFormatted == null)? 0 :renderFormatted.hashCode()));
|
||||
result = ((prime*result)+((renderFormatting == null)? 0 :renderFormatting.hashCode()));
|
||||
result = ((prime*result)+((renderScalarSubqueriesForStoredFunctions == null)? 0 :renderScalarSubqueriesForStoredFunctions.hashCode()));
|
||||
|
||||
@ -47,6 +47,7 @@ import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Statement;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Convenience methods for jOOQ runtime settings.
|
||||
@ -161,6 +162,14 @@ public final class SettingsTools {
|
||||
return defaultIfNull(settings.isReflectionCaching(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The render locale that is applicable, or the default locale if no such
|
||||
* locale is configured.
|
||||
*/
|
||||
public static final Locale renderLocale(Settings settings) {
|
||||
return defaultIfNull(settings.getRenderLocale(), Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy access to {@link RenderMapping}.
|
||||
*/
|
||||
|
||||
@ -41,6 +41,7 @@ import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
import static org.jooq.XMLFormat.RecordFormat.COLUMN_NAME_ELEMENTS;
|
||||
import static org.jooq.XMLFormat.RecordFormat.VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE;
|
||||
import static org.jooq.conf.SettingsTools.renderLocale;
|
||||
import static org.jooq.impl.DSL.insertInto;
|
||||
import static org.jooq.impl.DSL.name;
|
||||
import static org.jooq.impl.DSL.table;
|
||||
@ -673,7 +674,7 @@ abstract class AbstractCursor<R extends Record> implements Formattable, Iterable
|
||||
if (format.format())
|
||||
writer.append(' ');
|
||||
|
||||
JSONValue.writeJSONString(field.getDataType().getTypeName().toUpperCase(), writer);
|
||||
JSONValue.writeJSONString(field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings())), writer);
|
||||
|
||||
if (format.format())
|
||||
writer.append(format.newline()).append(format.indentString(2));
|
||||
@ -886,7 +887,7 @@ abstract class AbstractCursor<R extends Record> implements Formattable, Iterable
|
||||
writer.append(escapeXML(field.getName()));
|
||||
writer.append("\"");
|
||||
writer.append(" type=\"");
|
||||
writer.append(field.getDataType().getTypeName().toUpperCase());
|
||||
writer.append(field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings())));
|
||||
writer.append("\"/>");
|
||||
}
|
||||
|
||||
@ -1310,7 +1311,7 @@ abstract class AbstractCursor<R extends Record> implements Formattable, Iterable
|
||||
}
|
||||
|
||||
eField.setAttribute("name", field.getName());
|
||||
eField.setAttribute("type", field.getDataType().getTypeName().toUpperCase());
|
||||
eField.setAttribute("type", field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings())));
|
||||
eFields.appendChild(eField);
|
||||
}
|
||||
|
||||
@ -1386,7 +1387,7 @@ abstract class AbstractCursor<R extends Record> implements Formattable, Iterable
|
||||
}
|
||||
|
||||
attrs.addAttribute("", "", "name", "CDATA", field.getName());
|
||||
attrs.addAttribute("", "", "type", "CDATA", field.getDataType().getTypeName().toUpperCase());
|
||||
attrs.addAttribute("", "", "type", "CDATA", field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings())));
|
||||
|
||||
handler.startElement("", "", "field", attrs);
|
||||
handler.endElement("", "", "field");
|
||||
|
||||
@ -47,6 +47,7 @@ import static org.jooq.SQLDialect.HSQLDB;
|
||||
// ...
|
||||
import static org.jooq.conf.RenderNameStyle.LOWER;
|
||||
import static org.jooq.conf.RenderNameStyle.UPPER;
|
||||
import static org.jooq.conf.SettingsTools.renderLocale;
|
||||
import static org.jooq.impl.DSL.select;
|
||||
import static org.jooq.impl.DSL.unquotedName;
|
||||
import static org.jooq.impl.Keywords.K_BEGIN;
|
||||
@ -589,9 +590,9 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractQuery {
|
||||
// and wants to query HSQLDB (default to upper case), they may choose
|
||||
// to overwrite casing using RenderKeywordStyle.
|
||||
if (style == UPPER)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toUpperCase();
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toUpperCase(renderLocale(configuration().settings()));
|
||||
else if (style == LOWER)
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toLowerCase();
|
||||
names[i] = returningResolvedAsterisks.get(i).getName().toLowerCase(renderLocale(configuration().settings()));
|
||||
else
|
||||
names[i] = returningResolvedAsterisks.get(i).getName();
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.conf.SettingsTools.renderLocale;
|
||||
import static org.jooq.impl.Tools.EMPTY_INT;
|
||||
import static org.jooq.impl.Tools.EMPTY_QUERY;
|
||||
import static org.jooq.impl.Tools.EMPTY_STRING;
|
||||
@ -555,33 +556,28 @@ class DefaultExecuteContext implements ExecuteContext {
|
||||
|
||||
// Analyse SQL in plain SQL queries:
|
||||
else {
|
||||
String s = query.getSQL().toLowerCase();
|
||||
String s = query.getSQL().toLowerCase(renderLocale(configuration().settings()));
|
||||
|
||||
// TODO: Use a simple lexer to parse SQL here. Potentially, the
|
||||
// SQL Console's SQL formatter could be used...?
|
||||
if (s.matches("^(with\\b.*?\\bselect|select|explain)\\b.*?")) {
|
||||
if (s.matches("^(with\\b.*?\\bselect|select|explain)\\b.*?"))
|
||||
return ExecuteType.READ;
|
||||
}
|
||||
|
||||
// These are sample DML statements. There may be many more
|
||||
else if (s.matches("^(insert|update|delete|merge|replace|upsert|lock)\\b.*?")) {
|
||||
else if (s.matches("^(insert|update|delete|merge|replace|upsert|lock)\\b.*?"))
|
||||
return ExecuteType.WRITE;
|
||||
}
|
||||
|
||||
// These are only sample DDL statements. There may be many more
|
||||
else if (s.matches("^(create|alter|drop|truncate|grant|revoke|analyze|comment|flashback|enable|disable)\\b.*?")) {
|
||||
else if (s.matches("^(create|alter|drop|truncate|grant|revoke|analyze|comment|flashback|enable|disable)\\b.*?"))
|
||||
return ExecuteType.DDL;
|
||||
}
|
||||
|
||||
// JDBC escape syntax for routines
|
||||
else if (s.matches("^\\s*\\{\\s*(\\?\\s*=\\s*)call.*?")) {
|
||||
else if (s.matches("^\\s*\\{\\s*(\\?\\s*=\\s*)call.*?"))
|
||||
return ExecuteType.ROUTINE;
|
||||
}
|
||||
|
||||
// Vendor-specific calling of routines / procedural blocks
|
||||
else if (s.matches("^(call|begin|declare)\\b.*?")) {
|
||||
else if (s.matches("^(call|begin|declare)\\b.*?"))
|
||||
return ExecuteType.ROUTINE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@ import static org.jooq.conf.ParamType.INLINED;
|
||||
import static org.jooq.conf.ParamType.NAMED;
|
||||
import static org.jooq.conf.RenderNameStyle.LOWER;
|
||||
import static org.jooq.conf.RenderNameStyle.UPPER;
|
||||
import static org.jooq.conf.SettingsTools.renderLocale;
|
||||
import static org.jooq.impl.Identifiers.QUOTES;
|
||||
import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER;
|
||||
import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER_ESCAPED;
|
||||
@ -459,7 +460,7 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
|
||||
||
|
||||
|
||||
// [#2367] ... yet, do quote when an identifier is a SQLite keyword
|
||||
(family == SQLITE && SQLITE_KEYWORDS.contains(literal.toUpperCase()))
|
||||
(family == SQLITE && SQLITE_KEYWORDS.contains(literal.toUpperCase(renderLocale(configuration().settings()))))
|
||||
|
||||
||
|
||||
|
||||
@ -468,9 +469,9 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
|
||||
|
||||
if (!needsQuote) {
|
||||
if (LOWER == cachedRenderNameStyle)
|
||||
literal = literal.toLowerCase();
|
||||
literal = literal.toLowerCase(renderLocale(configuration().settings()));
|
||||
else if (UPPER == cachedRenderNameStyle)
|
||||
literal = literal.toUpperCase();
|
||||
literal = literal.toUpperCase(renderLocale(configuration().settings()));
|
||||
|
||||
sql(literal, true);
|
||||
}
|
||||
|
||||
@ -3349,15 +3349,12 @@ final class Tools {
|
||||
static final String getPropertyName(String methodName) {
|
||||
String name = methodName;
|
||||
|
||||
if (name.startsWith("is") && name.length() > 2) {
|
||||
if (name.startsWith("is") && name.length() > 2)
|
||||
name = name.substring(2, 3).toLowerCase() + name.substring(3);
|
||||
}
|
||||
else if (name.startsWith("get") && name.length() > 3) {
|
||||
else if (name.startsWith("get") && name.length() > 3)
|
||||
name = name.substring(3, 4).toLowerCase() + name.substring(4);
|
||||
}
|
||||
else if (name.startsWith("set") && name.length() > 3) {
|
||||
else if (name.startsWith("set") && name.length() > 3)
|
||||
name = name.substring(3, 4).toLowerCase() + name.substring(4);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -20,6 +20,11 @@
|
||||
<xjc:javaType name="java.util.regex.Pattern" adapter="org.jooq.conf.RegexAdapter"/>
|
||||
</jaxb:bindings>
|
||||
|
||||
<!-- [#7153] Locales -->
|
||||
<jaxb:bindings schemaLocation="../../xsd/jooq-runtime-3.12.0.xsd" multiple="true" node="//xs:element[@name='renderLocale']">
|
||||
<xjc:javaType name="java.util.Locale" adapter="org.jooq.conf.LocaleAdapter"/>
|
||||
</jaxb:bindings>
|
||||
|
||||
<!-- Annotate the following classes with @SuppressWarnings -->
|
||||
<jaxb:bindings schemaLocation="../../xsd/jooq-runtime-3.12.0.xsd" multiple="true" node="//xs:complexType">
|
||||
<inheritance:extends>org.jooq.conf.SettingsBase</inheritance:extends>
|
||||
|
||||
@ -44,6 +44,10 @@ This is set to "QUOTED" by default for backwards-compatibility]]></jxb:javadoc><
|
||||
<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="renderLocale" type="string" minOccurs="0" maxOccurs="1">
|
||||
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The Locale to be used with any locale dependent logic (as e.g. transforming names to lower / uppper 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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user