[#2414] [#2436] [#2437] Added ParamType

- [#2414] Add Setting to influence parameter rendering (indexed,
named, inlined)
- [#2436] Add Query.getSQL(ParamType) and deprecate
Query.getSQL(boolean)
- [#2437] Add RenderContext.paramType() and deprecate
RenderContext.inline() and .namedParams()
This commit is contained in:
Lukas Eder 2013-05-03 15:10:40 +02:00
parent 2b6c704ca7
commit aa74f02875
29 changed files with 557 additions and 110 deletions

View File

@ -35,6 +35,8 @@
*/
package org.jooq.test._;
import static org.jooq.conf.ParamType.INLINED;
import java.util.concurrent.atomic.AtomicInteger;
import org.jooq.DSLContext;
@ -84,7 +86,7 @@ public class PrettyPrinter extends DefaultExecuteListener {
System.out.println(normal.renderInlined(ctx.query()));
System.out.println();
System.out.println(pretty.renderContext()
.inline(true)
.paramType(INLINED)
.render(ctx.query()));
}
@ -93,7 +95,7 @@ public class PrettyPrinter extends DefaultExecuteListener {
System.out.println(normal.renderInlined(ctx.routine()));
System.out.println();
System.out.println(pretty.renderContext()
.inline(true)
.paramType(INLINED)
.render(ctx.routine()));
}

View File

@ -35,6 +35,8 @@
*/
package org.jooq.test._.testcases;
import static org.jooq.conf.ParamType.INDEXED;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -151,7 +153,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
}
private void testBenchmarkReuseSQLString(DSLContext create, int repetitions) throws Exception {
String sql = createSelect(create).getSQL(false);
String sql = createSelect(create).getSQL(INDEXED);
PreparedStatement pst = getConnection().prepareStatement(sql);
pst.setLong(1, 1);
pst.setString(2, RANDOM);

View File

@ -45,6 +45,7 @@ import static junit.framework.Assert.fail;
import static org.jooq.SQLDialect.H2;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.count;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.val;
@ -424,7 +425,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
create().update(TAuthor())
.set(TAuthor_FIRST_NAME(), "Hugo")
.where(TAuthor_ID().equal(100))
.getSQL(true));
.getSQL(INLINED));
assertNotNull(result);
assertEquals(0, result.size());
@ -434,7 +435,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
create().update(TAuthor())
.set(TAuthor_FIRST_NAME(), "Hugo")
.where(TAuthor_ID().equal(100))
.getSQL(true));
.getSQL(INLINED));
assertNotNull(result);
assertEquals(0, results.size());

View File

@ -42,6 +42,8 @@ import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.SQLDialect.H2;
import static org.jooq.conf.ParamType.INDEXED;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.StatementType.STATIC_STATEMENT;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.fieldByName;
@ -60,8 +62,8 @@ import java.util.List;
import org.jooq.BindContext;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Cursor;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.FutureResult;
import org.jooq.QueryPart;
@ -427,7 +429,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
public void testPlainSQLResultQuery() throws Exception {
// [#1749] TODO Firebird renders CAST(? as VARCHAR(...)) bind values with sizes
// pre-calculated. Hence the param needs to have some min length...
String sql = create().select(param("p", "abc").as("p")).getSQL(false);
String sql = create().select(param("p", "abc").as("p")).getSQL(INDEXED);
ResultQuery<Record> q = create().resultQuery(sql, "10");
Result<Record> fetch1 = q.fetch();
@ -518,7 +520,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
public void toSQL(RenderContext context) {
context.configuration().data("Foo-Field", "Baz");
if (context.inline()) {
if (context.paramType() == INLINED) {
context.sql(TBook_ID().getName() + " * 2");
}
@ -553,7 +555,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
context.sql(IDx2);
context.sql(" > ");
if (context.inline()) {
if (context.paramType() == INLINED) {
context.sql("3");
}
else {

View File

@ -39,7 +39,7 @@
<schemaDirectory>src/main/resources/xsd</schemaDirectory>
<bindingDirectory>src/main/resources/xjb</bindingDirectory>
<schemaIncludes>
<include>jooq-runtime-3.0.0.xsd</include>
<include>jooq-runtime-3.1.0.xsd</include>
</schemaIncludes>
<generatePackage>org.jooq.conf</generatePackage>
<args>

View File

@ -146,7 +146,7 @@ public interface Context<C extends Context<C>> {
* must assure that calling {@link #nextIndex()} is followed by setting a
* bind value to {@link BindContext#statement()}</li>
* <li>When rendering unnamed bind variables with
* {@link RenderContext#namedParams()} being to <code>true</code></li>
* {@link RenderContext#paramType()} being to <code>NAMED</code></li>
* </ul>
*/
int nextIndex();

View File

@ -61,6 +61,7 @@ import java.util.Map;
import javax.annotation.Generated;
import org.jooq.conf.ParamType;
import org.jooq.conf.Settings;
import org.jooq.conf.StatementType;
import org.jooq.exception.DataAccessException;
@ -165,8 +166,7 @@ public interface DSLContext {
* <li> <code>{@link RenderContext#declareFields()} == false</code></li>
* <li> <code>{@link RenderContext#declareTables()} == false</code></li>
* <li> <code>{@link RenderContext#format()} == false</code></li>
* <li> <code>{@link RenderContext#inline()} == false</code></li>
* <li> <code>{@link RenderContext#namedParams()} == false</code></li>
* <li> <code>{@link RenderContext#paramType()} == {@link ParamType#INDEXED}</code></li>
* <li> <code>{@link RenderContext#qualify()} == true</code></li>
* <li> <code>{@link RenderContext#subquery()} == false</code></li>
* </ul>

View File

@ -41,6 +41,7 @@ import java.sql.Statement;
import java.util.List;
import java.util.Map;
import org.jooq.conf.ParamType;
import org.jooq.conf.Settings;
import org.jooq.conf.StatementType;
import org.jooq.exception.DataAccessException;
@ -139,9 +140,28 @@ public interface Query extends QueryPart, Attachable {
* @param inline Whether to inline bind variables. This overrides values in
* {@link Settings#getStatementType()}
* @return The generated SQL
* @deprecated - [#2414] - 3.1.0 - Use {@link #getSQL(ParamType)} instead
*/
@Deprecated
String getSQL(boolean inline);
/**
* Retrieve the SQL code rendered by this Query.
* <p>
* [#1520] Note that the query actually being executed might not contain any
* bind variables, in case the number of bind variables exceeds your SQL
* dialect's maximum number of supported bind variables. This is not
* reflected by this method, which will only use <code>paramType</code>
* argument to decide whether to render bind values.
* <p>
* See {@link #getSQL()} for more details.
*
* @param paramType How to render parameters. This overrides values in
* {@link Settings#getStatementType()}
* @return The generated SQL
*/
String getSQL(ParamType paramType);
/**
* Retrieve the bind values that will be bound by this Query. This
* <code>List</code> cannot be modified. To modify bind values, use

View File

@ -35,6 +35,7 @@
*/
package org.jooq;
import org.jooq.conf.ParamType;
import org.jooq.conf.RenderKeywordStyle;
import org.jooq.conf.Settings;
@ -50,7 +51,7 @@ import org.jooq.conf.Settings;
public interface RenderContext extends Context<RenderContext> {
/**
* Peek the next alias that will be generated by {@link #nextAlias()}
* Peek the next alias that will be generated by {@link #nextAlias()}.
*/
String peekAlias();
@ -62,7 +63,7 @@ public interface RenderContext extends Context<RenderContext> {
String nextAlias();
/**
* Render the context's underlying SQL statement
* Render the context's underlying SQL statement.
*/
String render();
@ -73,7 +74,7 @@ public interface RenderContext extends Context<RenderContext> {
String render(QueryPart part);
/**
* Append a SQL keyword to the context's contained {@link StringBuilder}
* Append a SQL keyword to the context's contained {@link StringBuilder}.
* <p>
* Use this to have your SQL keyword rendered in {@link RenderKeywordStyle}
* (upper or lower case)
@ -81,58 +82,58 @@ public interface RenderContext extends Context<RenderContext> {
RenderContext keyword(String keyword);
/**
* Append some SQL to the context's contained {@link StringBuilder}
* Append some SQL to the context's contained {@link StringBuilder}.
*/
RenderContext sql(String sql);
/**
* Append some SQL to the context's contained {@link StringBuilder}
* Append some SQL to the context's contained {@link StringBuilder}.
*/
RenderContext sql(char sql);
/**
* Append some SQL to the context's contained {@link StringBuilder}
* Append some SQL to the context's contained {@link StringBuilder}.
*/
RenderContext sql(int sql);
/**
* Recurse rendering
* Recurse rendering.
*/
RenderContext sql(QueryPart part);
/**
* Override the value of {@link Settings#isRenderFormatted()}
* Override the value of {@link Settings#isRenderFormatted()}.
*/
RenderContext format(boolean format);
/**
* The value of {@link Settings#isRenderFormatted()}
* The value of {@link Settings#isRenderFormatted()}.
*/
boolean format();
/**
* Render a new line character (only if {@link Settings#isRenderFormatted()}
* is set to <code>true</code>)
* is set to <code>true</code>).
*/
RenderContext formatNewLine();
/**
* Render a new line character (only if {@link Settings#isRenderFormatted()}
* is set to <code>true</code>, and the {@link #formatPrintMargin(int)} has
* been exceeded)
* been exceeded).
*/
RenderContext formatNewLineAfterPrintMargin();
/**
* Render a new line character (only if {@link Settings#isRenderFormatted()}
* is set to <code>true</code>), or a whitespace separator character
* otherwise
* otherwise.
*/
RenderContext formatSeparator();
/**
* Start indenting subsequent SQL by one level (two characters), if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
* <p>
* This is the same as calling {@link #formatIndentStart(int)} with a
* parameter of <code>2</code>
@ -141,19 +142,19 @@ public interface RenderContext extends Context<RenderContext> {
/**
* Start indenting subsequent SQL by a number of characters, if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
*/
RenderContext formatIndentStart(int indent);
/**
* Start indenting subsequent SQL at the same level as the current line, if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
*/
RenderContext formatIndentLockStart();
/**
* Stop indenting subsequent SQL by one level (two characters), if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
* <p>
* This is the same as calling {@link #formatIndentEnd(int)} with a
* parameter of <code>2</code>
@ -162,19 +163,19 @@ public interface RenderContext extends Context<RenderContext> {
/**
* Stop indenting subsequent SQL by a number of characters, if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
*/
RenderContext formatIndentEnd(int indent);
/**
* Stop indenting subsequent SQL at the same level as the current line, if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
*/
RenderContext formatIndentLockEnd();
/**
* Set a print margin that will be applied to formatted SQL, if
* {@link Settings#isRenderFormatted()} is set to <code>true</code>
* {@link Settings#isRenderFormatted()} is set to <code>true</code>.
* <p>
* The default print margin is <code>80</code>. Setting this to zero or a
* negative value means that no print margin will be applied.
@ -187,28 +188,36 @@ public interface RenderContext extends Context<RenderContext> {
/**
* Append some (quoted) literal to the context's contained
* {@link StringBuilder}
* {@link StringBuilder}.
*/
RenderContext literal(String literal);
/**
* Whether bind variables should be inlined, rather than rendered as
* <code>'?'</code>
* <code>'?'</code>.
*
* @deprecated - 3.1.0 - [#2414] - This method should no longer be used. Use
* {@link #paramType()} instead.
*/
@Deprecated
boolean inline();
/**
* Set the new context value for {@link #inline()}
* Set the new context value for {@link #inline()}.
*
* @deprecated - 3.1.0 - [#2414] - This method should no longer be used. Use
* {@link #paramType(ParamType)} instead.
*/
@Deprecated
RenderContext inline(boolean inline);
/**
* Whether query parts should render qualified names or not
* Whether query parts should render qualified names or not.
*/
boolean qualify();
/**
* Sett the new context value for {@link #qualify()}
* Sett the new context value for {@link #qualify()}.
*/
RenderContext qualify(boolean qualify);
@ -218,21 +227,48 @@ public interface RenderContext extends Context<RenderContext> {
* <p>
* or as JDBC bind variables <br/>
* <code>&#160; ?</code>
*
* @deprecated - 3.1.0 - [#2414] - This method should no longer be used. Use
* {@link #paramType()} instead.
*/
@Deprecated
boolean namedParams();
/**
* Set the new context value for {@link #namedParams()}
* Set the new context value for {@link #namedParams()}.
*
* @deprecated - 3.1.0 - [#2414] - This method should no longer be used. Use
* {@link #paramType(ParamType)} instead.
*/
@Deprecated
RenderContext namedParams(boolean renderNamedParams);
/**
* The currently applied cast mode for bind values
* Specify, how bind values should be rendered.
* <p>
* <ul>
* <li>As {@link ParamType#INDEXED} parameters: <br/>
* <code>&#160; ?, ?, ?</code></li>
* <li>As {@link ParamType#NAMED} parameters: <br/>
* <code>&#160; :1, :2, :custom_name</code></li>
* <li>As {@link ParamType#INLINED} parameters: <br/>
* <code>&#160; 1, 'A', null</code></li>
* </ul>
*/
ParamType paramType();
/**
* Set the new context value for {@link #paramType()}.
*/
RenderContext paramType(ParamType paramType);
/**
* The currently applied cast mode for bind values.
*/
CastMode castMode();
/**
* Set the new cast mode for {@link #castMode()}
* Set the new cast mode for {@link #castMode()}.
*/
RenderContext castMode(CastMode mode);
@ -264,7 +300,7 @@ public interface RenderContext extends Context<RenderContext> {
Boolean cast();
/**
* Set the new cast mode to {@link CastMode#SOME} for a list of dialects
* Set the new cast mode to {@link CastMode#SOME} for a list of dialects.
*/
RenderContext castModeSome(SQLDialect... dialects);
@ -276,24 +312,25 @@ public interface RenderContext extends Context<RenderContext> {
enum CastMode {
/**
* Cast all bind values to their respective type
* Cast all bind values to their respective type.
*/
ALWAYS,
/**
* Cast no bind values to their respective type
* Cast no bind values to their respective type.
*/
NEVER,
/**
* Cast bind values only in some dialects. The specified dialects assume
* {@link #ALWAYS} behaviour, all the other dialects assume
* {@link #NEVER}
* {@link #NEVER}.
*/
SOME,
/**
* Cast when needed. This is the default mode if not specified otherwise
* Cast when needed. This is the default mode if not specified
* otherwise.
*/
DEFAULT
}

View File

@ -35,6 +35,8 @@
*/
package org.jooq.conf;
import static org.jooq.conf.ParamType.INDEXED;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.StatementType.PREPARED_STATEMENT;
import static org.jooq.conf.StatementType.STATIC_STATEMENT;
@ -85,6 +87,28 @@ public final class SettingsTools {
DEFAULT_SETTINGS = settings;
}
/**
* Get the parameter type from the settings.
* <p>
* The {@link ParamType} can be overridden by the {@link StatementType}.
* If the latter is set to {@link StatementType#STATIC_STATEMENT}, then the
* former defaults to {@link ParamType#INLINED}.
*/
public static final ParamType getParamType(Settings settings) {
if (executeStaticStatements(settings)) {
return INLINED;
}
else if (settings != null) {
ParamType result = settings.getParamType();
if (result != null) {
return result;
}
}
return INDEXED;
}
/**
* Get the statement type from the settings.
*/

View File

@ -44,6 +44,7 @@ import org.jooq.Configuration;
import org.jooq.Param;
import org.jooq.Query;
import org.jooq.RenderContext;
import org.jooq.conf.ParamType;
/**
* @author Lukas Eder
@ -100,10 +101,16 @@ abstract class AbstractDelegatingQuery<Q extends Query> extends AbstractQueryPar
}
@Override
@Deprecated
public final String getSQL(boolean inline) {
return delegate.getSQL(inline);
}
@Override
public final String getSQL(ParamType paramType) {
return delegate.getSQL(paramType);
}
@Override
public final void attach(Configuration configuration) {
delegate.attach(configuration);

View File

@ -35,6 +35,8 @@
*/
package org.jooq.impl;
import static org.jooq.conf.ParamType.INLINED;
import org.jooq.DataType;
import org.jooq.Param;
import org.jooq.RenderContext;
@ -113,6 +115,6 @@ abstract class AbstractParam<T> extends AbstractField<T> implements Param<T> {
}
final boolean isInline(RenderContext context) {
return isInline() || context.inline();
return isInline() || context.paramType() == INLINED;
}
}

View File

@ -36,7 +36,10 @@
package org.jooq.impl;
import static org.jooq.conf.ParamType.INDEXED;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.SettingsTools.executePreparedStatements;
import static org.jooq.conf.SettingsTools.getParamType;
import static org.jooq.impl.Utils.DATA_COUNT_BIND_VALUES;
import static org.jooq.impl.Utils.DATA_FORCE_STATIC_STATEMENT;
@ -53,7 +56,7 @@ import org.jooq.ExecuteListener;
import org.jooq.Param;
import org.jooq.Query;
import org.jooq.RenderContext;
import org.jooq.conf.SettingsTools;
import org.jooq.conf.ParamType;
import org.jooq.conf.StatementType;
import org.jooq.exception.DetachedException;
import org.jooq.tools.JooqLogger;
@ -174,7 +177,7 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
// If all params are inlined, the previous statement always has to
// be closed
else if (SettingsTools.executeStaticStatements(configuration().settings())) {
else if (getParamType(configuration().settings()) == INLINED) {
close();
}
}
@ -239,8 +242,9 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
Configuration c = configuration();
// [#1191] The following triggers a start event on all listeners.
// This may be used to provide jOOQ with a JDBC connection, in case
// this Query / Configuration was previously deserialised
// This may be used to provide jOOQ with a JDBC connection,
// in case this Query / Configuration was previously
// deserialised
ExecuteContext ctx = new DefaultExecuteContext(c, this);
ExecuteListener listener = new ExecuteListeners(ctx);
@ -279,6 +283,8 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
if (
// [#1145] Bind variables only for true prepared statements
// [#2414] Even if parameters are inlined here, child
// QueryParts may override this behaviour!
executePreparedStatements(c.settings()) &&
// [#1520] Renderers may enforce static statements, too
@ -371,11 +377,11 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
}
catch (DefaultRenderContext.ForceInlineSignal e) {
ctx.data(DATA_FORCE_STATIC_STATEMENT, true);
return getSQL(true);
return getSQL(INLINED);
}
}
else {
return getSQL(true);
return getSQL(INLINED);
}
}
@ -384,24 +390,32 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query, Attacha
*/
@Override
public final String getSQL() {
if (executePreparedStatements(configuration().settings())) {
return getSQL(false);
}
else {
return getSQL(true);
}
return getSQL(getParamType(configuration().settings()));
}
/**
* {@inheritDoc}
*/
@Override
public final String getSQL(ParamType paramType) {
switch (paramType) {
case INDEXED:
return create().render(this);
case INLINED:
return create().renderInlined(this);
case NAMED:
return create().renderNamedParams(this);
}
throw new IllegalArgumentException("ParamType not supported: " + paramType);
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public final String getSQL(boolean inline) {
if (inline) {
return create().renderInlined(this);
}
else {
return create().render(this);
}
return getSQL(inline ? INLINED : INDEXED);
}
}

View File

@ -35,6 +35,7 @@
*/
package org.jooq.impl;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.val;
import org.jooq.ArrayRecord;
@ -59,7 +60,7 @@ class ArrayConstant<R extends ArrayRecord<?>> extends AbstractParam<R> {
@Override
public final void toSQL(RenderContext context) {
if (context.inline()) {
if (context.paramType() == INLINED) {
context.sql(array.getName());
context.sql("(");

View File

@ -35,6 +35,7 @@
*/
package org.jooq.impl;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.SettingsTools.executeStaticStatements;
import java.sql.Connection;
@ -172,7 +173,7 @@ class BatchSingle implements BatchBindStep {
query.bind(i + 1, bindValues[i]);
}
queries.add(create.query(query.getSQL(true)));
queries.add(create.query(query.getSQL(INLINED)));
}
return create.batch(queries).execute();

View File

@ -50,6 +50,8 @@ import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.SQLITE;
import static org.jooq.SQLDialect.SQLSERVER;
import static org.jooq.SQLDialect.SYBASE;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.ParamType.NAMED;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.fieldByName;
import static org.jooq.impl.DSL.trueCondition;
@ -296,12 +298,12 @@ class DSLContextImpl implements DSLContext, Serializable {
@Override
public final String renderNamedParams(QueryPart part) {
return renderContext().namedParams(true).render(part);
return renderContext().paramType(NAMED).render(part);
}
@Override
public final String renderInlined(QueryPart part) {
return renderContext().inline(true).render(part);
return renderContext().paramType(INLINED).render(part);
}
@Override

View File

@ -36,6 +36,9 @@
package org.jooq.impl;
import static java.util.Arrays.asList;
import static org.jooq.conf.ParamType.INDEXED;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.ParamType.NAMED;
import static org.jooq.impl.Utils.DATA_COUNT_BIND_VALUES;
import java.util.Arrays;
@ -50,6 +53,7 @@ import org.jooq.QueryPart;
import org.jooq.QueryPartInternal;
import org.jooq.RenderContext;
import org.jooq.SQLDialect;
import org.jooq.conf.ParamType;
import org.jooq.conf.RenderKeywordStyle;
import org.jooq.conf.RenderNameStyle;
import org.jooq.conf.Settings;
@ -69,9 +73,8 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
private static final Set<String> SQLITE_KEYWORDS;
private final StringBuilder sql;
private boolean inline;
private ParamType paramType;
private int params;
private boolean renderNamedParams;
private boolean qualify = true;
private int alias;
private CastMode castMode = CastMode.DEFAULT;
@ -99,8 +102,7 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
DefaultRenderContext(RenderContext context) {
this(context.configuration());
inline(context.inline());
namedParams(context.namedParams());
paramType(context.paramType());
qualify(context.qualify());
castMode(context.castMode());
declareFields(context.declareFields());
@ -374,7 +376,7 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
}
private final void checkForceInline(QueryPart part) throws ForceInlineSignal {
if (inline)
if (paramType == INLINED)
return;
if (part instanceof Param) {
@ -412,12 +414,24 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
@Override
public final boolean inline() {
return inline;
return paramType == INLINED;
}
@Override
@Deprecated
public final RenderContext inline(boolean i) {
this.inline = i;
this.paramType = i ? INLINED : INDEXED;
return this;
}
@Override
public final ParamType paramType() {
return paramType;
}
@Override
public final RenderContext paramType(ParamType p) {
paramType = p;
return this;
}
@ -434,12 +448,13 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
@Override
public final boolean namedParams() {
return renderNamedParams;
return paramType == NAMED;
}
@Override
@Deprecated
public final RenderContext namedParams(boolean r) {
this.renderNamedParams = r;
this.paramType = r ? NAMED : INDEXED;
return this;
}
@ -487,11 +502,8 @@ class DefaultRenderContext extends AbstractContext<RenderContext> implements Ren
sb.append("rendering [");
sb.append(render());
sb.append("]\n");
sb.append("inlining [");
sb.append(inline);
sb.append("]\n");
sb.append("named params [");
sb.append(renderNamedParams);
sb.append("parameters [");
sb.append(paramType);
sb.append("]\n");
toString(sb);

View File

@ -36,6 +36,7 @@
package org.jooq.impl;
import static org.jooq.RenderContext.CastMode.NEVER;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.val;
@ -44,6 +45,7 @@ import org.jooq.Field;
import org.jooq.Param;
import org.jooq.RenderContext;
import org.jooq.RenderContext.CastMode;
import org.jooq.conf.ParamType;
import org.jooq.exception.DataAccessException;
/**
@ -64,7 +66,7 @@ class Limit extends AbstractQueryPart {
@Override
public final void toSQL(RenderContext context) {
boolean inline = context.inline();
ParamType paramType = context.paramType();
CastMode castMode = context.castMode();
switch (context.configuration().dialect()) {
@ -134,14 +136,14 @@ class Limit extends AbstractQueryPart {
// INGRES doesn't allow bind variables in the
// OFFSET m FETCH FIRST n ROWS ONLY clause
context.inline(true)
context.paramType(INLINED)
.formatSeparator()
.keyword("offset ")
.sql(offsetOrZero)
.keyword(" fetch first ")
.sql(numberOfRows)
.keyword(" rows only")
.inline(inline);
.paramType(paramType);
break;
}
@ -149,12 +151,12 @@ class Limit extends AbstractQueryPart {
// Nice TOP .. START AT support
// ----------------------------
case SYBASE: {
context.inline(true)
context.paramType(INLINED)
.keyword("top ")
.sql(numberOfRows)
.keyword(" start at ")
.sql(offsetPlusOne)
.inline(inline);
.paramType(paramType);
break;
}
@ -168,12 +170,12 @@ class Limit extends AbstractQueryPart {
}
// DB2 doesn't allow bind variables here. Casting is not needed.
context.inline(true)
context.paramType(INLINED)
.formatSeparator()
.keyword("fetch first ")
.sql(numberOfRows)
.keyword(" rows only")
.inline(inline);
.paramType(paramType);
break;
}
@ -185,10 +187,10 @@ class Limit extends AbstractQueryPart {
}
// SQL Server and Sybase don't allow bind variables in the TOP n clause
context.inline(true)
context.paramType(INLINED)
.keyword("top ")
.sql(numberOfRows)
.inline(inline);
.paramType(paramType);
break;
}

View File

@ -35,6 +35,7 @@
*/
package org.jooq.impl;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.trueCondition;
import static org.jooq.impl.DSL.using;
@ -54,6 +55,7 @@ import org.jooq.RenderContext;
import org.jooq.Select;
import org.jooq.Support;
import org.jooq.Table;
import org.jooq.conf.ParamType;
import org.jooq.exception.DataAccessException;
/**
@ -222,7 +224,7 @@ implements
public void toSQL(RenderContext context) {
// Bind variables are not allowed inside of PIVOT clause
boolean inline = context.inline();
ParamType paramType = context.paramType();
boolean declareFields = context.declareFields();
boolean declareTables = context.declareTables();
@ -231,7 +233,7 @@ implements
.declareTables(declareTables)
.formatSeparator()
.keyword("pivot (")
.inline(true)
.paramType(INLINED)
.declareFields(true)
.formatIndentStart()
.sql(aggregateFunctions)
@ -242,7 +244,7 @@ implements
.keyword("in (")
.sql(in)
.declareFields(declareFields)
.inline(inline)
.paramType(paramType)
.sql(")")
.formatIndentEnd()
.formatNewLine()

View File

@ -47,6 +47,7 @@ import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.SQLITE;
import static org.jooq.SQLDialect.SQLSERVER;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.one;
@ -75,6 +76,7 @@ import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableLike;
import org.jooq.conf.ParamType;
import org.jooq.exception.DataAccessException;
import org.jooq.tools.StringUtils;
@ -490,14 +492,14 @@ class SelectQueryImpl<R extends Record> extends AbstractSelect<R> implements Sel
// toSQL()'s LIMIT .. OFFSET rendering and bind()'s "obliviousness"
// thereof. This should be improved by delegating to composed Select
// objects.
boolean inline = context.inline();
context.inline(true)
ParamType paramType = context.paramType();
context.paramType(INLINED)
.sql(",")
.formatIndentStart()
.formatSeparator()
.sql(limitOffsetRownumber)
.formatIndentEnd()
.inline(inline);
.paramType(paramType);
}
context.declareFields(false);

View File

@ -36,6 +36,7 @@
package org.jooq.impl;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.val;
import org.jooq.BindContext;
@ -64,7 +65,7 @@ class UDTConstant<R extends UDTRecord<R>> extends AbstractParam<R> {
// Oracle supports java.sql.SQLData, hence the record can be bound
// to the CallableStatement directly
case ORACLE: {
if (context.inline()) {
if (context.paramType() == INLINED) {
toSQLInline(context);
} else {
context.sql("?");

View File

@ -38,6 +38,7 @@ package org.jooq.impl;
import static java.lang.Boolean.FALSE;
import static org.jooq.SQLDialect.CUBRID;
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.escape;
import static org.jooq.impl.DSL.getDataType;
import static org.jooq.impl.DSL.nullSafe;
@ -833,7 +834,7 @@ final class Utils {
else if (sqlChars[i] == '?' && substituteIndex < substitutes.size()) {
QueryPart substitute = substitutes.get(substituteIndex++);
if (render.inline()) {
if (render.paramType() == INLINED) {
render.sql(substitute);
}
else {

View File

@ -51,6 +51,7 @@ import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.SQLITE;
import static org.jooq.SQLDialect.SQLSERVER;
import static org.jooq.SQLDialect.SYBASE;
import static org.jooq.conf.ParamType.NAMED;
import static org.jooq.tools.StringUtils.leftPad;
import java.math.BigDecimal;
@ -276,7 +277,7 @@ class Val<T> extends AbstractParam<T> {
* {@link RenderContext#namedParams()}
*/
private final String getBindVariable(RenderContext context) {
if (context.namedParams()) {
if (context.paramType() == NAMED) {
int index = context.nextIndex();
if (StringUtils.isBlank(getParamName())) {

View File

@ -35,6 +35,8 @@
*/
package org.jooq.tools;
import static org.jooq.conf.ParamType.INLINED;
import java.util.logging.Level;
import org.jooq.ExecuteContext;
@ -67,7 +69,7 @@ public class LoggerListener extends DefaultExecuteListener {
// [#1278] DEBUG log also SQL with inlined bind values, if
// that is not the same as the actual SQL passed to JDBC
String inlined = ctx.query().getSQL(true);
String inlined = ctx.query().getSQL(INLINED);
if (!ctx.sql().equals(inlined)) {
log.debug("-> with bind values", inlined);
}

View File

@ -12,12 +12,12 @@
<jaxb:globalBindings>
<!-- Force all classes implements Serializable -->
<xjc:serializable uid="300" />
<xjc:serializable uid="310" />
</jaxb:globalBindings>
<!-- Annotate the following classes with @SuppressWarnings -->
<jaxb:bindings schemaLocation="../xsd/jooq-runtime-3.0.0.xsd" multiple="true" node="//xs:complexType">
<jaxb:bindings schemaLocation="../xsd/jooq-runtime-3.1.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,175 @@
<?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.1.0.xsd"
targetNamespace="http://www.jooq.org/xsd/jooq-runtime-3.1.0.xsd"
elementFormDefault="qualified">
<element name="settings" type="jooq-runtime:Settings"/>
<complexType name="Settings">
<all>
<!-- Whether any schema name should be rendered at all.
Use this for single-schema environments, or when all objects are made
available using synonyms -->
<element name="renderSchema" type="boolean" minOccurs="0" maxOccurs="1" default="true"/>
<!-- Configure render mapping for runtime schema / table rewriting in
generated SQL -->
<element name="renderMapping" type="jooq-runtime:RenderMapping" minOccurs="0" maxOccurs="1"/>
<!-- Whether rendered schema, table, column names, etc should be quoted
in rendered SQL, or transformed in any other way.
This is set to "QUOTED" by default for backwards-compatibility -->
<element name="renderNameStyle" type="jooq-runtime:RenderNameStyle" minOccurs="0" maxOccurs="1" default="QUOTED"/>
<!-- Whether SQL keywords should be rendered with upper or lower case -->
<element name="renderKeywordStyle" type="jooq-runtime:RenderKeywordStyle" minOccurs="0" maxOccurs="1" default="LOWER"/>
<!-- Whether rendered SQL should be pretty-printed -->
<element name="renderFormatted" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
<!-- Whether rendered bind values should be rendered as:
- question marks
- named parameters
- inlined values
This value is overridden by statementType == STATIC_STATEMENT, in
case of which, this defaults to INLINED
-->
<element name="paramType" type="jooq-runtime:ParamType" minOccurs="0" maxOccurs="1" default="INDEXED"/>
<!-- The type of statement that is to be executed -->
<element name="statementType" type="jooq-runtime:StatementType" minOccurs="0" maxOccurs="1" default="PREPARED_STATEMENT"/>
<!-- When set to true, this will add jOOQ's default logging ExecuteListeners -->
<element name="executeLogging" type="boolean" minOccurs="0" maxOccurs="1" default="true"/>
<!-- Whether store() and delete() methods should be executed with optimistic locking -->
<element name="executeWithOptimisticLocking" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
<!-- Whether fetched records should be attached to the fetching configuration -->
<element name="attachRecords" type="boolean" minOccurs="0" maxOccurs="1" default="true"/>
</all>
</complexType>
<complexType name="RenderMapping">
<all>
<!-- The default schema as defined in org.jooq.Schema.getName()
This schema will be omitted in rendered SQL -->
<element name="defaultSchema" type="string" minOccurs="0" maxOccurs="1"/>
<!-- The mapped schemata configuration -->
<element name="schemata" type="jooq-runtime:MappedSchemata" minOccurs="0" maxOccurs="1"/>
</all>
</complexType>
<complexType name="MappedSchemata">
<sequence>
<element name="schema" type="jooq-runtime:MappedSchema" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="MappedSchema">
<all>
<!-- The input schema as defined in org.jooq.Schema.getName() -->
<element name="input" type="string" minOccurs="1" maxOccurs="1"/>
<!-- The output schema as it will be rendered in SQL
When this is omitted, you can still apply table mapping -->
<element name="output" type="string" minOccurs="0" maxOccurs="1"/>
<!-- Configure table mapping for runtime table rewriting in
generated SQL -->
<element name="tables" type="jooq-runtime:MappedTables" minOccurs="0" maxOccurs="1"/>
</all>
</complexType>
<complexType name="MappedTables">
<sequence>
<element name="table" type="jooq-runtime:MappedTable" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="MappedTable">
<all>
<!-- The input schema as defined in org.jooq.Table.getName() -->
<element name="input" type="string" minOccurs="1" maxOccurs="1"/>
<!-- The output schema as it will be rendered in SQL -->
<element name="output" type="string" minOccurs="1" maxOccurs="1"/>
</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 inlined parameters -->
<enumeration value="INLINED"/>
</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 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>
</schema>

View File

@ -35,6 +35,8 @@
*/
package org.jooq.test;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.ParamType.NAMED;
import static org.jooq.test.data.Table1.FIELD_ID1;
import static org.jooq.test.data.Table1.FIELD_NAME1;
import static org.jooq.test.data.Table1.TABLE1;
@ -144,23 +146,23 @@ public abstract class AbstractTest {
}
protected final RenderContext r_refI() {
return r_ref().inline(true);
return r_ref().paramType(INLINED);
}
protected final RenderContext r_decI() {
return r_dec().inline(true);
return r_dec().paramType(INLINED);
}
protected final RenderContext r_decIF() {
return r_decF().inline(true);
return r_decF().paramType(INLINED);
}
protected final RenderContext r_decIT() {
return r_decT().inline(true);
return r_decT().paramType(INLINED);
}
protected final RenderContext r_refP() {
return r_ref().namedParams(true);
return r_ref().paramType(NAMED);
}
protected final String zeroDate() {

View File

@ -38,6 +38,7 @@ package org.jooq.test;
import static junit.framework.Assert.assertEquals;
import static org.jooq.JoinType.LEFT_OUTER_JOIN;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.impl.DSL.any;
import static org.jooq.impl.DSL.avg;
import static org.jooq.impl.DSL.condition;
@ -957,7 +958,7 @@ public class BasicTest extends AbstractTest {
@Override
public void toSQL(RenderContext ctx) {
if (ctx.inline()) {
if (ctx.paramType() == INLINED) {
ctx.sql("1 = 1");
} else {
ctx.sql("? = ?");
@ -1050,7 +1051,7 @@ public class BasicTest extends AbstractTest {
@Override
public void toSQL(RenderContext ctx) {
if (ctx.inline()) {
if (ctx.paramType() == INLINED) {
ctx.sql("1");
} else {
ctx.sql("?");

View File

@ -0,0 +1,131 @@
/**
* Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com
* All rights reserved.
*
* This software is licensed to you under the Apache License, Version 2.0
* (the "License"); You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* . Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* . Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* . Neither the name "jOOQ" nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jooq.test;
import static org.jooq.conf.ParamType.INDEXED;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.ParamType.NAMED;
import static org.jooq.conf.StatementType.STATIC_STATEMENT;
import static org.jooq.impl.DSL.val;
import static org.junit.Assert.assertEquals;
import org.jooq.Query;
import org.jooq.SQLDialect;
import org.jooq.conf.Settings;
import org.jooq.impl.DSL;
import org.junit.Test;
/**
* Some common tests related to rendering.
*
* @author Lukas Eder
*/
public class RenderTest extends AbstractTest {
@SuppressWarnings("deprecation")
private void testGetSQL0(Query q, String defaultSQL) {
assertEquals(defaultSQL, q.getSQL());
assertEquals("select ?, ? from dual", q.getSQL(false));
assertEquals("select 1, 'A' from dual", q.getSQL(true));
assertEquals("select ?, ? from dual", q.getSQL(INDEXED));
assertEquals("select :1, :2 from dual", q.getSQL(NAMED));
assertEquals("select 1, 'A' from dual", q.getSQL(INLINED));
}
@Test
public void testGetSQL() {
Query q = create.select(val(1), val("A"));
testGetSQL0(q, "select ?, ? from dual");
}
@Test
public void testGetSQLWithParamTypeINDEXED() {
Query q =
DSL.using(SQLDialect.ORACLE, new Settings().withParamType(INDEXED))
.select(val(1), val("A"));
testGetSQL0(q, "select ?, ? from dual");
}
@Test
public void testGetSQLWithParamTypeINDEXEDandStatementTypeSTATIC() {
Query q =
DSL.using(SQLDialect.ORACLE, new Settings().withParamType(INDEXED)
.withStatementType(STATIC_STATEMENT))
.select(val(1), val("A"));
testGetSQL0(q, "select 1, 'A' from dual");
}
@Test
public void testGetSQLWithParamTypeNAMED() {
Query q =
DSL.using(SQLDialect.ORACLE, new Settings().withParamType(NAMED))
.select(val(1), val("A"));
testGetSQL0(q, "select :1, :2 from dual");
}
@Test
public void testGetSQLWithParamTypeNAMEDandStatementTypeSTATIC() {
Query q =
DSL.using(SQLDialect.ORACLE, new Settings().withParamType(NAMED)
.withStatementType(STATIC_STATEMENT))
.select(val(1), val("A"));
testGetSQL0(q, "select 1, 'A' from dual");
}
@Test
public void testGetSQLWithParamTypeINLINED() {
Query q =
DSL.using(SQLDialect.ORACLE, new Settings().withParamType(INLINED))
.select(val(1), val("A"));
testGetSQL0(q, "select 1, 'A' from dual");
}
@Test
public void testGetSQLWithParamTypeINLINEDandStatementTypeSTATIC() {
Query q =
DSL.using(SQLDialect.ORACLE, new Settings().withParamType(INLINED)
.withStatementType(STATIC_STATEMENT))
.select(val(1), val("A"));
testGetSQL0(q, "select 1, 'A' from dual");
}
}