[#1157] Add extended SQL / JDBC tracing capabilities in addition to logging - draft API and implementation
This commit is contained in:
parent
332f556d01
commit
753b645389
@ -59,7 +59,6 @@ import org.jooq.Result;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.conf.Execution;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.impl.Factory;
|
||||
@ -315,8 +314,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
|
||||
Boolean bool3 = (derby ? bool1 : null);
|
||||
|
||||
Factory create = create(new Settings()
|
||||
.withExecution(new Execution()
|
||||
.withStatementType(StatementType.STATIC_STATEMENT)));
|
||||
.withStatementType(StatementType.STATIC_STATEMENT));
|
||||
|
||||
Object[] array1 = create.select(vals(s1, s2, s3, s4)).fetchOneArray();
|
||||
Object[] array2 = create.select(vals(b1, b2, sh1, sh2, i1, i2, l1, l2, bi1, bi2, bd1, bd2, db1, db2, f1, f2)).fetchOneArray();
|
||||
@ -347,8 +345,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
|
||||
Timestamp ts1 = Timestamp.valueOf("1981-07-10 12:01:15");
|
||||
|
||||
Factory create = create(new Settings()
|
||||
.withExecution(new Execution()
|
||||
.withStatementType(StatementType.STATIC_STATEMENT)));
|
||||
.withStatementType(StatementType.STATIC_STATEMENT));
|
||||
|
||||
DATE date = create.newRecord(TDates());
|
||||
date.setValue(TDates_ID(), 1);
|
||||
|
||||
@ -56,7 +56,6 @@ import org.jooq.UpdatableRecord;
|
||||
import org.jooq.conf.MappedSchema;
|
||||
import org.jooq.conf.MappedTable;
|
||||
import org.jooq.conf.RenderMapping;
|
||||
import org.jooq.conf.Rendering;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.impl.Factory;
|
||||
import org.jooq.test.BaseTest;
|
||||
@ -120,13 +119,12 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
|
||||
@Test
|
||||
public void testTableMapping() throws Exception {
|
||||
Settings settings = new Settings()
|
||||
.withRendering(new Rendering()
|
||||
.withRenderMapping(new RenderMapping()
|
||||
.withSchemata(new MappedSchema()
|
||||
.withInput(TAuthor().getSchema().getName())
|
||||
.withTables(
|
||||
new MappedTable().withInput(TAuthor().getName()).withOutput(VAuthor().getName()),
|
||||
new MappedTable().withInput(TBook().getName()).withOutput(VBook().getName())))));
|
||||
new MappedTable().withInput(TBook().getName()).withOutput(VBook().getName()))));
|
||||
|
||||
Select<Record> q =
|
||||
create(settings).select(TBook_TITLE())
|
||||
@ -160,14 +158,13 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
|
||||
// Map to self. This will work even for single-schema RDBMS
|
||||
// ---------------------------------------------------------------------
|
||||
Settings settings = new Settings()
|
||||
.withRendering(new Rendering()
|
||||
.withRenderMapping(new RenderMapping()
|
||||
.withSchemata(new MappedSchema()
|
||||
.withInput(TAuthor().getSchema().getName())
|
||||
.withOutput(TAuthor().getSchema().getName())
|
||||
.withTables(
|
||||
new MappedTable().withInput(TAuthor().getName()).withOutput(TAuthor().getName()),
|
||||
new MappedTable().withInput(TBook().getName()).withOutput(TBook().getName())))));
|
||||
new MappedTable().withInput(TBook().getName()).withOutput(TBook().getName()))));
|
||||
|
||||
Select<Record> query =
|
||||
create(settings).select(TBook_TITLE())
|
||||
@ -218,11 +215,10 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
|
||||
// Map to a second schema
|
||||
// ---------------------------------------------------------------------
|
||||
settings = new Settings()
|
||||
.withRendering(new Rendering()
|
||||
.withRenderMapping(new RenderMapping()
|
||||
.withSchemata(new MappedSchema()
|
||||
.withInput(TAuthor().getSchema().getName())
|
||||
.withOutput(TAuthor().getSchema().getName() + "2"))));
|
||||
.withOutput(TAuthor().getSchema().getName() + "2")));
|
||||
|
||||
Select<Record> q =
|
||||
create(settings).select(TBook_TITLE())
|
||||
@ -264,14 +260,13 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, D, T, U, I, IPK, T658, T725, T639
|
||||
// Map both schema AND tables
|
||||
// --------------------------
|
||||
settings = new Settings()
|
||||
.withRendering(new Rendering()
|
||||
.withRenderMapping(new RenderMapping()
|
||||
.withSchemata(new MappedSchema()
|
||||
.withInput(TAuthor().getSchema().getName())
|
||||
.withOutput(TAuthor().getSchema().getName() + "2")
|
||||
.withTables(
|
||||
new MappedTable().withInput(TAuthor().getName()).withOutput(VAuthor().getName()),
|
||||
new MappedTable().withInput(TBook().getName()).withOutput(VBook().getName())))));
|
||||
new MappedTable().withInput(TBook().getName()).withOutput(VBook().getName()))));
|
||||
|
||||
q =
|
||||
create(settings).select(TBook_TITLE())
|
||||
|
||||
@ -66,7 +66,6 @@ import org.jooq.UDTRecord;
|
||||
import org.jooq.UpdatableTable;
|
||||
import org.jooq.conf.MappedSchema;
|
||||
import org.jooq.conf.RenderMapping;
|
||||
import org.jooq.conf.Rendering;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.impl.Factory;
|
||||
import org.jooq.test.hsqldb.generatedclasses.Public;
|
||||
@ -117,11 +116,10 @@ public class jOOQHSQLDBTest2 extends jOOQAbstractTest<
|
||||
@Override
|
||||
protected Factory create(Settings settings) {
|
||||
settings = (settings != null) ? settings : new Settings();
|
||||
settings.withRendering(new Rendering()
|
||||
.withRenderMapping(new RenderMapping()
|
||||
settings.withRenderMapping(new RenderMapping()
|
||||
.withSchemata(new MappedSchema()
|
||||
.withInput(TAuthor().getSchema().getName())
|
||||
.withOutput(Public.PUBLIC.getName()))));
|
||||
.withOutput(Public.PUBLIC.getName())));
|
||||
return new PublicFactory(getConnection(), settings);
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,6 @@ package org.jooq.test;
|
||||
|
||||
import org.jooq.conf.MappedSchema;
|
||||
import org.jooq.conf.RenderMapping;
|
||||
import org.jooq.conf.Rendering;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.test.mysql.generatedclasses.TestFactory;
|
||||
|
||||
@ -63,11 +62,10 @@ public class jOOQMySQLTestSchemaMapping extends jOOQMySQLTest {
|
||||
@Override
|
||||
protected TestFactory create(Settings settings) {
|
||||
settings = (settings != null) ? settings : new Settings();
|
||||
settings.withRendering(new Rendering()
|
||||
.withRenderMapping(new RenderMapping()
|
||||
settings.withRenderMapping(new RenderMapping()
|
||||
.withSchemata(new MappedSchema()
|
||||
.withInput(TAuthor().getSchema().getName())
|
||||
.withOutput(TAuthor().getSchema().getName() + getSchemaSuffix()))));
|
||||
.withOutput(TAuthor().getSchema().getName() + getSchemaSuffix())));
|
||||
return new TestFactory(getConnection(), settings);
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@
|
||||
|
||||
package org.jooq.test;
|
||||
|
||||
import org.jooq.conf.Execution;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.test.oracle.generatedclasses.test.TestFactory;
|
||||
@ -50,8 +49,7 @@ public class jOOQOracleTestInline extends jOOQOracleTest {
|
||||
@Override
|
||||
protected TestFactory create(Settings settings) {
|
||||
settings = (settings != null) ? settings : new Settings();
|
||||
settings.withExecution(new Execution()
|
||||
.withStatementType(StatementType.STATIC_STATEMENT));
|
||||
settings.withStatementType(StatementType.STATIC_STATEMENT);
|
||||
return new TestFactory(getConnection(), settings);
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@
|
||||
|
||||
package org.jooq.test;
|
||||
|
||||
import org.jooq.conf.Execution;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.test.sqlserver.generatedclasses.DboFactory;
|
||||
@ -50,8 +49,7 @@ public class jOOQSQLServerTestInline extends jOOQSQLServerTest {
|
||||
@Override
|
||||
protected DboFactory create(Settings settings) {
|
||||
settings = (settings != null) ? settings : new Settings();
|
||||
settings.withExecution(new Execution()
|
||||
.withStatementType(StatementType.STATIC_STATEMENT));
|
||||
settings.withStatementType(StatementType.STATIC_STATEMENT);
|
||||
return new DboFactory(getConnection(), settings);
|
||||
}
|
||||
}
|
||||
@ -76,13 +76,13 @@ public interface Configuration extends Serializable {
|
||||
* <p>
|
||||
* This is custom data that was previously set to the configuration using
|
||||
* {@link #setData(String, Object)}. Use custom data if you want to pass
|
||||
* data to your custom {@link QueryPart} or {@link EventListener} objects to
|
||||
* data to your custom {@link QueryPart} or {@link ExecuteListener} objects to
|
||||
* be made available at render, bind, execution, fetch time.
|
||||
* <p>
|
||||
* See {@link EventListener} for more details.
|
||||
* See {@link ExecuteListener} for more details.
|
||||
*
|
||||
* @return The custom data. This is never <code>null</code>
|
||||
* @see EventListener
|
||||
* @see ExecuteListener
|
||||
*/
|
||||
Map<String, Object> getData();
|
||||
|
||||
@ -91,15 +91,15 @@ public interface Configuration extends Serializable {
|
||||
* <p>
|
||||
* This is custom data that was previously set to the configuration using
|
||||
* {@link #setData(String, Object)}. Use custom data if you want to pass
|
||||
* data to your custom {@link QueryPart} or {@link EventListener} objects to
|
||||
* data to your custom {@link QueryPart} or {@link ExecuteListener} objects to
|
||||
* be made available at render, bind, execution, fetch time.
|
||||
* <p>
|
||||
* See {@link EventListener} for more details.
|
||||
* See {@link ExecuteListener} for more details.
|
||||
*
|
||||
* @param key A key to identify the custom data
|
||||
* @return The custom data or <code>null</code> if no such data is contained
|
||||
* in this <code>Configuration</code>
|
||||
* @see EventListener
|
||||
* @see ExecuteListener
|
||||
*/
|
||||
Object getData(String key);
|
||||
|
||||
@ -108,21 +108,21 @@ public interface Configuration extends Serializable {
|
||||
* <p>
|
||||
* This is custom data that was previously set to the configuration using
|
||||
* {@link #setData(String, Object)}. Use custom data if you want to pass
|
||||
* data to your custom {@link QueryPart} or {@link EventListener} objects to
|
||||
* data to your custom {@link QueryPart} or {@link ExecuteListener} objects to
|
||||
* be made available at render, bind, execution, fetch time.
|
||||
* <p>
|
||||
* Be sure that your custom data implements {@link Serializable} if you want
|
||||
* to serialise this <code>Configuration</code> or objects referencing this
|
||||
* <code>Configuration</code>, e.g. your {@link Record} types.
|
||||
* <p>
|
||||
* See {@link EventListener} for more details.
|
||||
* See {@link ExecuteListener} for more details.
|
||||
*
|
||||
* @param key A key to identify the custom data
|
||||
* @param value The custom data or <code>null</code> to unset the custom
|
||||
* data
|
||||
* @return The previously set custom data or <code>null</code> if no data
|
||||
* was previously set for the given key
|
||||
* @see EventListener
|
||||
* @see ExecuteListener
|
||||
*/
|
||||
Object setData(String key, Object value);
|
||||
|
||||
|
||||
@ -37,7 +37,6 @@ package org.jooq;
|
||||
|
||||
import org.jooq.tools.JooqLogger;
|
||||
|
||||
|
||||
/**
|
||||
* A public static registry that can provide factories ({@link Configuration}'s)
|
||||
* to {@link Attachable}'s upon deserialisation. The registry acts as an
|
||||
@ -47,11 +46,14 @@ import org.jooq.tools.JooqLogger;
|
||||
* <p>
|
||||
* This functionality is experimental. It may change again in the future. Use it
|
||||
* at your own risk.
|
||||
*
|
||||
*
|
||||
* @author Lukas Eder
|
||||
* @see <a
|
||||
* href="http://groups.google.com/group/jooq-user/browse_thread/thread/d33e9a902707d111">http://groups.google.com/group/jooq-user/browse_thread/thread/d33e9a902707d111</a>
|
||||
* @deprecated - 2.0.5 - Use {@link ExecuteListener#init(ExecuteContext)}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ConfigurationRegistry {
|
||||
|
||||
private static JooqLogger log = JooqLogger.getLogger(ConfigurationRegistry.class);
|
||||
@ -95,6 +97,8 @@ public final class ConfigurationRegistry {
|
||||
* <code>null</code> to reset the provider.
|
||||
*/
|
||||
public static void setProvider(ConfigurationProvider provider) {
|
||||
log.warn("Deprecation", "org.jooq.ConfigurationRegistry is deprecated. Use org.jooq.ExecuteListener instead");
|
||||
|
||||
if (provider != null) {
|
||||
log.info("Registering provider", provider);
|
||||
}
|
||||
|
||||
@ -35,6 +35,53 @@
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
public interface EventListener {
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* A context object for {@link Query} execution passed to registered
|
||||
* {@link ExecuteListener}'s.
|
||||
* <p>
|
||||
* Expect most of this context's objects to be <code>nullable</code>!
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface ExecuteContext extends Configuration {
|
||||
|
||||
Configuration configuration();
|
||||
|
||||
// TODO Routines?
|
||||
// Nullable!
|
||||
Query query();
|
||||
|
||||
// Nullable!
|
||||
void sql(String sql);
|
||||
|
||||
String sql();
|
||||
|
||||
/**
|
||||
* Override the context's {@link PreparedStatement}
|
||||
* <p>
|
||||
* Use this to wrap the <code>PreparedStatement</code> executed by jOOQ with
|
||||
* your custom wrapper statement, logging bind variables and query
|
||||
* execution. Beware
|
||||
*/
|
||||
void statement(PreparedStatement statement);
|
||||
|
||||
PreparedStatement statement();
|
||||
|
||||
// Nullable!
|
||||
void resultSet(ResultSet resultSet);
|
||||
|
||||
ResultSet resultSet();
|
||||
|
||||
// Nullable
|
||||
void record(Record record);
|
||||
|
||||
Record record();
|
||||
|
||||
void result(Result<?> result);
|
||||
|
||||
Result<?> result();
|
||||
|
||||
}
|
||||
88
jOOQ/src/main/java/org/jooq/ExecuteListener.java
Normal file
88
jOOQ/src/main/java/org/jooq/ExecuteListener.java
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, 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;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.impl.Factory;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
|
||||
/**
|
||||
* An event listener for {@link Query} render, prepare, bind, execute, fetch
|
||||
* steps.
|
||||
* <p>
|
||||
* <code>EventListener</code> is a base type for loggers, debuggers, profilers,
|
||||
* data collectors that can be hooked into a jOOQ {@link Factory} using the
|
||||
* {@link Settings#getEventListeners()} property, passing <code>Settings</code>
|
||||
* to {@link Factory#Factory(java.sql.Connection, SQLDialect, Settings)}
|
||||
* <p>
|
||||
* Advanced <code>EventListeners</code> can also provide custom implementations
|
||||
* of {@link Connection}, {@link PreparedStatement} and {@link ResultSet} to
|
||||
* jOOQ in apropriate methods.
|
||||
* <p>
|
||||
* If nothing is specified, the default is to use {@link JooqLogger} as the only
|
||||
* event listener.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface ExecuteListener {
|
||||
|
||||
void init(ExecuteContext ctx);
|
||||
|
||||
void renderStart(ExecuteContext ctx);
|
||||
void renderEnd(ExecuteContext ctx);
|
||||
|
||||
void prepareStart(ExecuteContext ctx);
|
||||
void prepareEnd(ExecuteContext ctx);
|
||||
|
||||
void bindStart(ExecuteContext ctx);
|
||||
void bindEnd(ExecuteContext ctx);
|
||||
|
||||
void executeStart(ExecuteContext ctx);
|
||||
void executeEnd(ExecuteContext ctx);
|
||||
|
||||
void recordStart(ExecuteContext ctx);
|
||||
void recordEnd(ExecuteContext ctx);
|
||||
|
||||
void resultStart(ExecuteContext ctx);
|
||||
void resultEnd(ExecuteContext ctx);
|
||||
|
||||
void fetchStart(ExecuteContext ctx);
|
||||
void fetchEnd(ExecuteContext ctx);
|
||||
}
|
||||
@ -43,7 +43,6 @@ import java.util.Map.Entry;
|
||||
import org.jooq.conf.MappedSchema;
|
||||
import org.jooq.conf.MappedTable;
|
||||
import org.jooq.conf.RenderMapping;
|
||||
import org.jooq.conf.Rendering;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.impl.SchemaImpl;
|
||||
import org.jooq.impl.TableImpl;
|
||||
@ -319,22 +318,18 @@ public class SchemaMapping implements Serializable {
|
||||
SchemaMapping result = new SchemaMapping(false);
|
||||
|
||||
if (settings != null) {
|
||||
Rendering rendering = settings.getRendering();
|
||||
RenderMapping r = settings.getRenderMapping();
|
||||
|
||||
if (rendering != null) {
|
||||
RenderMapping r = rendering.getRenderMapping();
|
||||
if (r != null) {
|
||||
if (!StringUtils.isEmpty(r.getDefaultSchema())) {
|
||||
result.use(r.getDefaultSchema());
|
||||
}
|
||||
|
||||
if (r != null) {
|
||||
if (!StringUtils.isEmpty(r.getDefaultSchema())) {
|
||||
result.use(r.getDefaultSchema());
|
||||
}
|
||||
for (MappedSchema schema : r.getSchemata()) {
|
||||
result.add(schema.getInput(), schema.getOutput());
|
||||
|
||||
for (MappedSchema schema : r.getSchemata()) {
|
||||
result.add(schema.getInput(), schema.getOutput());
|
||||
|
||||
for (MappedTable table : schema.getTables()) {
|
||||
log.warn("TODO", "Re-implement table mapping for table " + table);
|
||||
}
|
||||
for (MappedTable table : schema.getTables()) {
|
||||
log.warn("TODO", "Re-implement table mapping for table " + table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs
|
||||
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
|
||||
// Any modifications to this file will be lost upon recompilation of the source schema.
|
||||
// Generated on: 2012.02.18 at 01:30:56 PM MEZ
|
||||
// Generated on: 2012.02.21 at 09:21:19 PM MEZ
|
||||
//
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs
|
||||
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
|
||||
// Any modifications to this file will be lost upon recompilation of the source schema.
|
||||
// Generated on: 2012.02.18 at 01:30:56 PM MEZ
|
||||
// Generated on: 2012.02.21 at 09:21:19 PM MEZ
|
||||
//
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs
|
||||
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
|
||||
// Any modifications to this file will be lost upon recompilation of the source schema.
|
||||
// Generated on: 2012.02.18 at 01:30:56 PM MEZ
|
||||
// Generated on: 2012.02.21 at 09:21:19 PM MEZ
|
||||
//
|
||||
|
||||
|
||||
|
||||
@ -2,15 +2,20 @@
|
||||
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs
|
||||
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
|
||||
// Any modifications to this file will be lost upon recompilation of the source schema.
|
||||
// Generated on: 2012.02.18 at 01:30:56 PM MEZ
|
||||
// Generated on: 2012.02.21 at 09:21:19 PM MEZ
|
||||
//
|
||||
|
||||
|
||||
package org.jooq.conf;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
@ -24,8 +29,10 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <all>
|
||||
* <element name="rendering" type="{http://www.jooq.org/xsd/jooq-runtime-2.0.5.xsd}Rendering" minOccurs="0"/>
|
||||
* <element name="execution" type="{http://www.jooq.org/xsd/jooq-runtime-2.0.5.xsd}Execution" minOccurs="0"/>
|
||||
* <element name="renderMapping" type="{http://www.jooq.org/xsd/jooq-runtime-2.0.5.xsd}RenderMapping" minOccurs="0"/>
|
||||
* <element name="statementType" type="{http://www.jooq.org/xsd/jooq-runtime-2.0.5.xsd}StatementType" minOccurs="0"/>
|
||||
* <element name="executeLogging" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
|
||||
* <element name="executeListeners" type="{http://www.jooq.org/xsd/jooq-runtime-2.0.5.xsd}ExecuteListeners" minOccurs="0"/>
|
||||
* </all>
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
@ -43,64 +50,122 @@ public class Settings
|
||||
{
|
||||
|
||||
private final static long serialVersionUID = 205L;
|
||||
protected Rendering rendering;
|
||||
protected Execution execution;
|
||||
protected RenderMapping renderMapping;
|
||||
@XmlElement(defaultValue = "PREPARED_STATEMENT")
|
||||
protected StatementType statementType = StatementType.PREPARED_STATEMENT;
|
||||
@XmlElement(defaultValue = "true")
|
||||
protected Boolean executeLogging = true;
|
||||
@XmlElementWrapper(name = "executeListeners")
|
||||
@XmlElement(name = "executeListener")
|
||||
protected List<String> executeListeners;
|
||||
|
||||
/**
|
||||
* Gets the value of the rendering property.
|
||||
* Gets the value of the renderMapping property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Rendering }
|
||||
* {@link RenderMapping }
|
||||
*
|
||||
*/
|
||||
public Rendering getRendering() {
|
||||
return rendering;
|
||||
public RenderMapping getRenderMapping() {
|
||||
return renderMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the rendering property.
|
||||
* Sets the value of the renderMapping property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Rendering }
|
||||
* {@link RenderMapping }
|
||||
*
|
||||
*/
|
||||
public void setRendering(Rendering value) {
|
||||
this.rendering = value;
|
||||
public void setRenderMapping(RenderMapping value) {
|
||||
this.renderMapping = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the execution property.
|
||||
* Gets the value of the statementType property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Execution }
|
||||
* {@link StatementType }
|
||||
*
|
||||
*/
|
||||
public Execution getExecution() {
|
||||
return execution;
|
||||
public StatementType getStatementType() {
|
||||
return statementType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the execution property.
|
||||
* Sets the value of the statementType property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Execution }
|
||||
* {@link StatementType }
|
||||
*
|
||||
*/
|
||||
public void setExecution(Execution value) {
|
||||
this.execution = value;
|
||||
public void setStatementType(StatementType value) {
|
||||
this.statementType = value;
|
||||
}
|
||||
|
||||
public Settings withRendering(Rendering value) {
|
||||
setRendering(value);
|
||||
/**
|
||||
* Gets the value of the executeLogging property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public Boolean isExecuteLogging() {
|
||||
return executeLogging;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the executeLogging property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link Boolean }
|
||||
*
|
||||
*/
|
||||
public void setExecuteLogging(Boolean value) {
|
||||
this.executeLogging = value;
|
||||
}
|
||||
|
||||
public List<String> getExecuteListeners() {
|
||||
if (executeListeners == null) {
|
||||
executeListeners = new ArrayList<String>();
|
||||
}
|
||||
return executeListeners;
|
||||
}
|
||||
|
||||
public Settings withRenderMapping(RenderMapping value) {
|
||||
setRenderMapping(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withExecution(Execution value) {
|
||||
setExecution(value);
|
||||
public Settings withStatementType(StatementType value) {
|
||||
setStatementType(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withExecuteLogging(Boolean value) {
|
||||
setExecuteLogging(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withExecuteListeners(String... values) {
|
||||
if (values!= null) {
|
||||
for (String value: values) {
|
||||
getExecuteListeners().add(value);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Settings withExecuteListeners(Collection<String> values) {
|
||||
if (values!= null) {
|
||||
getExecuteListeners().addAll(values);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@ -53,14 +53,10 @@ public final class SettingsTools {
|
||||
*/
|
||||
public static final StatementType getStatementType(Settings settings) {
|
||||
if (settings != null) {
|
||||
Execution execution = settings.getExecution();
|
||||
StatementType result = settings.getStatementType();
|
||||
|
||||
if (execution != null) {
|
||||
StatementType result = execution.getStatementType();
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs
|
||||
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
|
||||
// Any modifications to this file will be lost upon recompilation of the source schema.
|
||||
// Generated on: 2012.02.18 at 01:30:56 PM MEZ
|
||||
// Generated on: 2012.02.21 at 09:21:19 PM MEZ
|
||||
//
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.5-b02-fcs
|
||||
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
|
||||
// Any modifications to this file will be lost upon recompilation of the source schema.
|
||||
// Generated on: 2012.02.18 at 01:30:56 PM MEZ
|
||||
// Generated on: 2012.02.21 at 09:21:19 PM MEZ
|
||||
//
|
||||
|
||||
@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.jooq.org/xsd/jooq-runtime-2.0.5.xsd")
|
||||
|
||||
99
jOOQ/src/main/java/org/jooq/impl/AbstractConfiguration.java
Normal file
99
jOOQ/src/main/java/org/jooq/impl/AbstractConfiguration.java
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, 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.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.conf.Settings;
|
||||
|
||||
/**
|
||||
* A base class for all objects implementing {@link Configuration}, wrapping
|
||||
* another configuration.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
abstract class AbstractConfiguration implements Configuration {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -8527430313425232841L;
|
||||
|
||||
final Configuration configuration;
|
||||
|
||||
AbstractConfiguration(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SQLDialect getDialect() {
|
||||
return configuration.getDialect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Connection getConnection() {
|
||||
return configuration.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final org.jooq.SchemaMapping getSchemaMapping() {
|
||||
return configuration.getSchemaMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Settings getSettings() {
|
||||
return configuration.getSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String, Object> getData() {
|
||||
return configuration.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getData(String key) {
|
||||
return configuration.getData(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object setData(String key, Object value) {
|
||||
return configuration.setData(key, value);
|
||||
}
|
||||
}
|
||||
@ -35,36 +35,30 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.conf.Settings;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
abstract class AbstractContext<C extends Context<C>> implements Context<C> {
|
||||
abstract class AbstractContext<C extends Context<C>> extends AbstractConfiguration implements Context<C> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 4796952332163571043L;
|
||||
|
||||
final Configuration configuration;
|
||||
boolean declareFields;
|
||||
boolean declareTables;
|
||||
boolean subquery;
|
||||
int index;
|
||||
|
||||
AbstractContext(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
AbstractContext(Configuration configuration, boolean declareFields, boolean declareTables) {
|
||||
this.configuration = configuration;
|
||||
this(configuration);
|
||||
this.declareFields = declareFields;
|
||||
this.declareTables = declareTables;
|
||||
}
|
||||
@ -120,45 +114,9 @@ abstract class AbstractContext<C extends Context<C>> implements Context<C> {
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// XXX Configuration API
|
||||
// XXX Object API
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final SQLDialect getDialect() {
|
||||
return configuration.getDialect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Connection getConnection() {
|
||||
return configuration.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final org.jooq.SchemaMapping getSchemaMapping() {
|
||||
return configuration.getSchemaMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<String, Object> getData() {
|
||||
return configuration.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getData(String key) {
|
||||
return configuration.getData(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object setData(String key, Object value) {
|
||||
return configuration.setData(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Settings getSettings() {
|
||||
return configuration.getSettings();
|
||||
}
|
||||
|
||||
void toString(StringBuilder sb) {
|
||||
sb.append( "bind index [");
|
||||
sb.append(index);
|
||||
|
||||
@ -39,16 +39,15 @@ package org.jooq.impl;
|
||||
import static org.jooq.conf.SettingsTools.executePreparedStatements;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ConfigurationRegistry;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Param;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.exception.DetachedException;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.StopWatch;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
@ -102,13 +101,13 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public final int execute() {
|
||||
if (isExecutable()) {
|
||||
StopWatch watch = new StopWatch();
|
||||
|
||||
// Let listeners provide a configuration to this query
|
||||
Configuration configuration = ConfigurationRegistry.provideFor(getConfiguration());
|
||||
Configuration configuration = org.jooq.ConfigurationRegistry.provideFor(getConfiguration());
|
||||
if (configuration == null) {
|
||||
configuration = getConfiguration();
|
||||
}
|
||||
@ -118,50 +117,39 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
|
||||
throw new DetachedException("Cannot execute query. No Connection configured");
|
||||
}
|
||||
|
||||
ExecuteListener listener = new ExecuteListeners(configuration);
|
||||
ExecuteContext ctx = new DefaultExecuteContext(configuration, this);
|
||||
|
||||
// Ensure that all depending Attachables are attached
|
||||
attach(configuration);
|
||||
watch.splitTrace("Parts attached");
|
||||
|
||||
PreparedStatement statement = null;
|
||||
String sql = null;
|
||||
int result = 0;
|
||||
try {
|
||||
sql = getSQL();
|
||||
watch.splitTrace("SQL rendered");
|
||||
listener.renderStart(ctx);
|
||||
ctx.sql(getSQL());
|
||||
listener.renderEnd(ctx);
|
||||
|
||||
// [#1145] Depending on the configuration, a prepared statement
|
||||
// or an "ad-hoc" statement is used
|
||||
boolean usePreparedStatement = executePreparedStatements(getConfiguration().getSettings());
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Executing query", getSQL(true));
|
||||
if (log.isTraceEnabled() && usePreparedStatement)
|
||||
log.trace("Preparing statement", sql);
|
||||
|
||||
statement = prepare(configuration, sql);
|
||||
listener.prepareStart(ctx);
|
||||
prepare(ctx);
|
||||
listener.prepareEnd(ctx);
|
||||
|
||||
// [#1145] Bind variables only for true prepared statements
|
||||
if (usePreparedStatement) {
|
||||
watch.splitTrace("Statement prepared");
|
||||
|
||||
create(configuration).bind(this, statement);
|
||||
watch.splitTrace("Variables bound");
|
||||
if (executePreparedStatements(getConfiguration().getSettings())) {
|
||||
listener.bindStart(ctx);
|
||||
create(configuration).bind(this, ctx.statement());
|
||||
listener.bindEnd(ctx);
|
||||
}
|
||||
|
||||
result = execute(configuration, statement);
|
||||
watch.splitTrace("Statement executed");
|
||||
|
||||
result = execute(ctx, listener);
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("AbstractQuery.execute", sql, e);
|
||||
throw Util.translate("AbstractQuery.execute", ctx.sql(), e);
|
||||
}
|
||||
finally {
|
||||
if (!keepStatementOpen()) {
|
||||
Util.safeClose(statement);
|
||||
Util.safeClose(ctx);
|
||||
}
|
||||
|
||||
watch.splitDebug("Statement executed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -184,25 +172,23 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
|
||||
/**
|
||||
* Default implementation for preparing a statement. Subclasses may override
|
||||
* this method.
|
||||
*
|
||||
* @param configuration The configuration holding a connection
|
||||
* @param sql The generated SQL
|
||||
* @return The prepared statement
|
||||
*/
|
||||
protected PreparedStatement prepare(Configuration configuration, String sql) throws SQLException {
|
||||
return configuration.getConnection().prepareStatement(sql);
|
||||
protected void prepare(ExecuteContext ctx) throws SQLException {
|
||||
ctx.statement(ctx.getConnection().prepareStatement(ctx.sql()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation for query execution using a prepared statement.
|
||||
* Subclasses may override this method.
|
||||
*
|
||||
* @param configuration The configuration that is used for this query's
|
||||
* execution.
|
||||
* @param statement The statement to be executed.
|
||||
*/
|
||||
protected int execute(Configuration configuration, PreparedStatement statement) throws SQLException {
|
||||
return statement.executeUpdate();
|
||||
protected int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
|
||||
int result = 0;
|
||||
|
||||
listener.executeStart(ctx);
|
||||
result = ctx.statement().executeUpdate();
|
||||
listener.executeEnd(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -39,7 +39,6 @@ import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
@ -54,6 +53,8 @@ import java.util.concurrent.Future;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.FieldProvider;
|
||||
import org.jooq.FutureResult;
|
||||
@ -111,27 +112,25 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final PreparedStatement prepare(Configuration configuration, String sql) throws SQLException {
|
||||
PreparedStatement statement = super.prepare(configuration, sql);
|
||||
protected final void prepare(ExecuteContext ctx) throws SQLException {
|
||||
super.prepare(ctx);
|
||||
|
||||
if (size > 0) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Setting fetch size", size);
|
||||
|
||||
statement.setFetchSize(size);
|
||||
ctx.statement().setFetchSize(size);
|
||||
}
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final int execute(Configuration configuration, PreparedStatement statement) throws SQLException {
|
||||
Connection connection = configuration.getConnection();
|
||||
protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
|
||||
Connection connection = ctx.getConnection();
|
||||
boolean autoCommit = false;
|
||||
|
||||
// [#706] Postgres requires two separate queries running in the same
|
||||
// transaction to be executed when fetching refcursor types
|
||||
if (configuration.getDialect() == SQLDialect.POSTGRES && isSelectingRefCursor()) {
|
||||
if (ctx.getDialect() == SQLDialect.POSTGRES && isSelectingRefCursor()) {
|
||||
autoCommit = connection.getAutoCommit();
|
||||
|
||||
if (autoCommit) {
|
||||
@ -143,12 +142,15 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
}
|
||||
|
||||
try {
|
||||
ResultSet rs = statement.executeQuery();
|
||||
listener.executeStart(ctx);
|
||||
ctx.resultSet(ctx.statement().executeQuery());
|
||||
listener.executeEnd(ctx);
|
||||
|
||||
// Fetch a single result set
|
||||
if (!many) {
|
||||
FieldList fields = new FieldList(getFields(rs.getMetaData()));
|
||||
cursor = new CursorImpl<R>(configuration, fields, rs, statement, getRecordType());
|
||||
listener.fetchStart(ctx);
|
||||
FieldList fields = new FieldList(getFields(ctx.resultSet().getMetaData()));
|
||||
cursor = new CursorImpl<R>(ctx, listener, fields, getRecordType());
|
||||
|
||||
if (!lazy) {
|
||||
result = cursor.fetch();
|
||||
@ -161,20 +163,21 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
results = new ArrayList<Result<Record>>();
|
||||
|
||||
for (;;) {
|
||||
FieldProvider fields = new MetaDataFieldProvider(configuration, rs.getMetaData());
|
||||
Cursor<Record> c = new CursorImpl<Record>(configuration, fields, rs);
|
||||
listener.fetchStart(ctx);
|
||||
FieldProvider fields = new MetaDataFieldProvider(ctx, ctx.resultSet().getMetaData());
|
||||
Cursor<Record> c = new CursorImpl<Record>(ctx, listener, fields);
|
||||
results.add(c.fetch());
|
||||
|
||||
if (statement.getMoreResults()) {
|
||||
rs = statement.getResultSet();
|
||||
if (ctx.statement().getMoreResults()) {
|
||||
ctx.resultSet(ctx.statement().getResultSet());
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
statement.getMoreResults(Statement.CLOSE_ALL_RESULTS);
|
||||
statement.close();
|
||||
ctx.statement().getMoreResults(Statement.CLOSE_ALL_RESULTS);
|
||||
ctx.statement().close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
@ -54,6 +54,8 @@ import org.jooq.Attachable;
|
||||
import org.jooq.BindContext;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Package;
|
||||
import org.jooq.Parameter;
|
||||
@ -65,8 +67,6 @@ import org.jooq.Schema;
|
||||
import org.jooq.UDTField;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.tools.Convert;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.StopWatch;
|
||||
|
||||
/**
|
||||
* A common base class for stored procedures
|
||||
@ -81,7 +81,6 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 6330037113167106443L;
|
||||
private static final JooqLogger log = JooqLogger.getLogger(AbstractRoutine.class);
|
||||
|
||||
private final Package pkg;
|
||||
private final List<Parameter<?>> allParameters;
|
||||
@ -242,30 +241,25 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
}
|
||||
|
||||
private final int executeCallableStatement() {
|
||||
StopWatch watch = new StopWatch();
|
||||
|
||||
Configuration configuration = attachable.getConfiguration();
|
||||
CallableStatement statement = null;
|
||||
String sql = null;
|
||||
ExecuteListener listener = new ExecuteListeners(configuration);
|
||||
ExecuteContext ctx = new DefaultExecuteContext(configuration, null);
|
||||
|
||||
try {
|
||||
Connection connection = configuration.getConnection();
|
||||
|
||||
sql = create(configuration).render(this);
|
||||
watch.splitTrace("SQL rendered");
|
||||
listener.renderStart(ctx);
|
||||
ctx.sql(create(configuration).render(this));
|
||||
listener.renderEnd(ctx);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Executing routine", create(configuration).renderInlined(this));
|
||||
if (log.isTraceEnabled())
|
||||
log.trace("Preparing statement", sql);
|
||||
listener.prepareStart(ctx);
|
||||
ctx.statement(connection.prepareCall(ctx.sql()));
|
||||
listener.prepareEnd(ctx);
|
||||
|
||||
statement = connection.prepareCall(sql);
|
||||
watch.splitTrace("Statement prepared");
|
||||
|
||||
create(configuration).bind(this, statement);
|
||||
watch.splitTrace("Variables bound");
|
||||
|
||||
registerOutParameters(configuration, statement);
|
||||
watch.splitTrace("OUT params registered");
|
||||
listener.bindStart(ctx);
|
||||
create(configuration).bind(this, ctx.statement());
|
||||
registerOutParameters(configuration, (CallableStatement) ctx.statement());
|
||||
listener.bindEnd(ctx);
|
||||
|
||||
// Postgres requires two separate queries running in the same
|
||||
// transaction to be executed when fetching refcursor types
|
||||
@ -274,25 +268,22 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
connection.setAutoCommit(false);
|
||||
}
|
||||
|
||||
statement.execute();
|
||||
listener.executeStart(ctx);
|
||||
ctx.statement().execute();
|
||||
listener.executeEnd(ctx);
|
||||
|
||||
if (autoCommit && configuration.getDialect() == SQLDialect.POSTGRES) {
|
||||
connection.setAutoCommit(autoCommit);
|
||||
}
|
||||
|
||||
watch.splitTrace("Routine called");
|
||||
|
||||
fetchOutParameters(configuration, statement);
|
||||
watch.splitTrace("OUT params fetched");
|
||||
|
||||
fetchOutParameters(ctx);
|
||||
return 0;
|
||||
}
|
||||
catch (SQLException exc) {
|
||||
throw translate("AbstractRoutine.executeCallableStatement", sql, exc);
|
||||
catch (SQLException e) {
|
||||
throw translate("AbstractRoutine.executeCallableStatement", ctx.sql(), e);
|
||||
}
|
||||
finally {
|
||||
Util.safeClose(statement);
|
||||
watch.splitDebug("Routine executed");
|
||||
Util.safeClose(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,15 +369,14 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
context.literal(getName());
|
||||
}
|
||||
|
||||
private final void fetchOutParameters(Configuration configuration, CallableStatement statement) throws SQLException {
|
||||
private final void fetchOutParameters(ExecuteContext ctx) throws SQLException {
|
||||
for (Parameter<?> parameter : getParameters()) {
|
||||
int index = parameterIndexes.get(parameter);
|
||||
|
||||
if (parameter.equals(getReturnParameter()) ||
|
||||
getOutParameters().contains(parameter)) {
|
||||
|
||||
results.put(parameter, FieldTypeHelper.getFromStatement(
|
||||
configuration, statement, parameter.getType(), index));
|
||||
results.put(parameter, FieldTypeHelper.getFromStatement(ctx, parameter.getType(), index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
138
jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
Normal file
138
jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
Normal file
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, 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.impl;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
|
||||
/**
|
||||
* A default iplementation for the {@link ExecuteContext}
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
class DefaultExecuteContext extends AbstractConfiguration implements ExecuteContext {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -6653474082935089963L;
|
||||
|
||||
// Persistent attributes
|
||||
private final Query query;
|
||||
private String sql;
|
||||
|
||||
// Transient attributes
|
||||
private transient PreparedStatement statement;
|
||||
private transient ResultSet resultSet;
|
||||
private transient Record record;
|
||||
private transient Result<?> result;
|
||||
|
||||
DefaultExecuteContext(Configuration configuration) {
|
||||
this(configuration, null);
|
||||
}
|
||||
|
||||
DefaultExecuteContext(Configuration configuration, Query query) {
|
||||
super(configuration);
|
||||
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Query query() {
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void sql(String s) {
|
||||
this.sql = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String sql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void statement(PreparedStatement s) {
|
||||
this.statement = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PreparedStatement statement() {
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void resultSet(ResultSet rs) {
|
||||
this.resultSet = rs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultSet resultSet() {
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Configuration configuration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void record(Record r) {
|
||||
this.record = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Record record() {
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void result(Result<?> r) {
|
||||
this.result = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Result<?> result() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
161
jOOQ/src/main/java/org/jooq/impl/ExecuteListeners.java
Normal file
161
jOOQ/src/main/java/org/jooq/impl/ExecuteListeners.java
Normal file
@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, 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.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.conf.Settings;
|
||||
|
||||
/**
|
||||
* A queue implementation for several {@link ExecuteListener} objects as defined
|
||||
* in {@link Settings#getExecuteListeners()}
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
class ExecuteListeners implements ExecuteListener {
|
||||
|
||||
private final List<ExecuteListener> listeners;
|
||||
|
||||
ExecuteListeners(Configuration configuration) {
|
||||
listeners = Util.getListeners(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void init(ExecuteContext ctx) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void renderStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.renderStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void renderEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.renderEnd(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void prepareStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.prepareStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void prepareEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.prepareEnd(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bindStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.bindStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bindEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.bindEnd(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void executeStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.executeStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void executeEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.executeEnd(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fetchStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.fetchStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void fetchEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.fetchEnd(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void recordStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.recordStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void recordEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.recordEnd(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resultStart(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.resultStart(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resultEnd(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.resultEnd(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,11 +82,12 @@ import org.jooq.BindContext;
|
||||
import org.jooq.Case;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ConfigurationRegistry;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.DatePart;
|
||||
import org.jooq.DeleteQuery;
|
||||
import org.jooq.DeleteWhereStep;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.FactoryOperations;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.FieldProvider;
|
||||
@ -965,12 +966,18 @@ public class Factory implements FactoryOperations {
|
||||
*/
|
||||
@Override
|
||||
public final Result<Record> fetch(ResultSet rs) {
|
||||
ExecuteListener listener = new ExecuteListeners(this);
|
||||
ExecuteContext ctx = new DefaultExecuteContext(this, null);
|
||||
|
||||
try {
|
||||
FieldProvider fields = new MetaDataFieldProvider(this, rs.getMetaData());
|
||||
return new CursorImpl<Record>(this, fields, rs).fetch();
|
||||
|
||||
ctx.resultSet(rs);
|
||||
listener.fetchStart(ctx);
|
||||
return new CursorImpl<Record>(ctx, listener, fields).fetch();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("Factory.fetch", null, e);
|
||||
throw Util.translate("Factory.fetch", ctx.sql(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4721,6 +4728,7 @@ public class Factory implements FactoryOperations {
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
|
||||
@ -4728,7 +4736,7 @@ public class Factory implements FactoryOperations {
|
||||
log.debug("Deserialising", this);
|
||||
}
|
||||
|
||||
Configuration registered = ConfigurationRegistry.provideFor(this);
|
||||
Configuration registered = org.jooq.ConfigurationRegistry.provideFor(this);
|
||||
if (registered != null) {
|
||||
connection = registered.getConnection();
|
||||
}
|
||||
|
||||
@ -36,6 +36,8 @@
|
||||
|
||||
package org.jooq.impl;
|
||||
|
||||
import static org.jooq.impl.Factory.getNewFactory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Array;
|
||||
@ -58,13 +60,11 @@ import java.util.Map;
|
||||
|
||||
import org.jooq.ArrayRecord;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.EnumType;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.FieldProvider;
|
||||
import org.jooq.MasterDataType;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.UDTRecord;
|
||||
@ -280,17 +280,19 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T getFromResultSet(Configuration configuration, ResultSet rs, Field<T> field, int index)
|
||||
static <T> T getFromResultSet(ExecuteContext ctx, Field<T> field, int index)
|
||||
throws SQLException {
|
||||
|
||||
Class<? extends T> type = field.getType();
|
||||
return getFromResultSet(configuration, rs, type, index);
|
||||
return getFromResultSet(ctx, type, index);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T getFromResultSet(Configuration configuration, ResultSet rs, Class<? extends T> type, int index)
|
||||
private static <T> T getFromResultSet(ExecuteContext ctx, Class<? extends T> type, int index)
|
||||
throws SQLException {
|
||||
|
||||
ResultSet rs = ctx.resultSet();
|
||||
|
||||
if (type == Blob.class) {
|
||||
return (T) rs.getBlob(index);
|
||||
}
|
||||
@ -299,7 +301,7 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
else if (type == BigInteger.class) {
|
||||
// The SQLite JDBC driver doesn't support BigDecimals
|
||||
if (configuration.getDialect() == SQLDialect.SQLITE) {
|
||||
if (ctx.getDialect() == SQLDialect.SQLITE) {
|
||||
return Convert.convert(rs.getString(index), (Class<? extends T>) BigInteger.class);
|
||||
}
|
||||
else {
|
||||
@ -309,7 +311,7 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
else if (type == BigDecimal.class) {
|
||||
// The SQLite JDBC driver doesn't support BigDecimals
|
||||
if (configuration.getDialect() == SQLDialect.SQLITE) {
|
||||
if (ctx.getDialect() == SQLDialect.SQLITE) {
|
||||
return Convert.convert(rs.getString(index), (Class<? extends T>) BigDecimal.class);
|
||||
}
|
||||
else {
|
||||
@ -326,7 +328,7 @@ public final class FieldTypeHelper {
|
||||
return (T) rs.getClob(index);
|
||||
}
|
||||
else if (type == Date.class) {
|
||||
return (T) getDate(configuration.getDialect(), rs, index);
|
||||
return (T) getDate(ctx.getDialect(), rs, index);
|
||||
}
|
||||
else if (type == Double.class) {
|
||||
return (T) checkWasNull(rs, Double.valueOf(rs.getDouble(index)));
|
||||
@ -347,10 +349,10 @@ public final class FieldTypeHelper {
|
||||
return (T) rs.getString(index);
|
||||
}
|
||||
else if (type == Time.class) {
|
||||
return (T) getTime(configuration.getDialect(), rs, index);
|
||||
return (T) getTime(ctx.getDialect(), rs, index);
|
||||
}
|
||||
else if (type == Timestamp.class) {
|
||||
return (T) getTimestamp(configuration.getDialect(), rs, index);
|
||||
return (T) getTimestamp(ctx.getDialect(), rs, index);
|
||||
}
|
||||
else if (type == UByte.class) {
|
||||
String string = rs.getString(index);
|
||||
@ -371,19 +373,19 @@ public final class FieldTypeHelper {
|
||||
|
||||
// The type byte[] is handled earlier. byte[][] can be handled here
|
||||
else if (type.isArray()) {
|
||||
switch (configuration.getDialect()) {
|
||||
switch (ctx.getDialect()) {
|
||||
case POSTGRES: {
|
||||
return pgGetArray(configuration, rs, type, index);
|
||||
return pgGetArray(ctx, type, index);
|
||||
}
|
||||
|
||||
default:
|
||||
// Note: due to a HSQLDB bug, it is not recommended to call rs.getObject() here:
|
||||
// See https://sourceforge.net/tracker/?func=detail&aid=3181365&group_id=23316&atid=378131
|
||||
return (T) convertArray(rs.getArray(index), (Class<? extends Object[]> )type);
|
||||
return (T) convertArray(rs.getArray(index), (Class<? extends Object[]>) type);
|
||||
}
|
||||
}
|
||||
else if (ArrayRecord.class.isAssignableFrom(type)) {
|
||||
return (T) getArrayRecord(configuration, rs.getArray(index), (Class<? extends ArrayRecord<?>>) type);
|
||||
return (T) getArrayRecord(ctx, rs.getArray(index), (Class<? extends ArrayRecord<?>>) type);
|
||||
}
|
||||
else if (EnumType.class.isAssignableFrom(type)) {
|
||||
return getEnumType(type, rs.getString(index));
|
||||
@ -392,7 +394,7 @@ public final class FieldTypeHelper {
|
||||
return (T) getMasterDataType(type, rs.getObject(index));
|
||||
}
|
||||
else if (UDTRecord.class.isAssignableFrom(type)) {
|
||||
switch (configuration.getDialect()) {
|
||||
switch (ctx.getDialect()) {
|
||||
case POSTGRES:
|
||||
return (T) pgNewUDTRecord(type, rs.getObject(index));
|
||||
}
|
||||
@ -401,9 +403,7 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
else if (Result.class.isAssignableFrom(type)) {
|
||||
ResultSet nested = (ResultSet) rs.getObject(index);
|
||||
FieldProvider fields = new MetaDataFieldProvider(configuration, nested.getMetaData());
|
||||
Cursor<Record> cursor = new CursorImpl<Record>(configuration, fields, nested);
|
||||
return (T) cursor.fetch();
|
||||
return (T) getNewFactory(ctx).fetch(nested);
|
||||
}
|
||||
else {
|
||||
return (T) rs.getObject(index);
|
||||
@ -567,7 +567,9 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getFromStatement(Configuration configuration, CallableStatement stmt, Class<? extends T> type, int index) throws SQLException {
|
||||
public static <T> T getFromStatement(ExecuteContext ctx, Class<? extends T> type, int index) throws SQLException {
|
||||
CallableStatement stmt = (CallableStatement) ctx.statement();
|
||||
|
||||
if (type == Blob.class) {
|
||||
return (T) stmt.getBlob(index);
|
||||
}
|
||||
@ -639,7 +641,7 @@ public final class FieldTypeHelper {
|
||||
return (T) convertArray(stmt.getObject(index), (Class<? extends Object[]>)type);
|
||||
}
|
||||
else if (ArrayRecord.class.isAssignableFrom(type)) {
|
||||
return (T) getArrayRecord(configuration, stmt.getArray(index), (Class<? extends ArrayRecord<?>>) type);
|
||||
return (T) getArrayRecord(ctx, stmt.getArray(index), (Class<? extends ArrayRecord<?>>) type);
|
||||
}
|
||||
else if (EnumType.class.isAssignableFrom(type)) {
|
||||
return getEnumType(type, stmt.getString(index));
|
||||
@ -648,7 +650,7 @@ public final class FieldTypeHelper {
|
||||
return (T) getMasterDataType(type, stmt.getString(index));
|
||||
}
|
||||
else if (UDTRecord.class.isAssignableFrom(type)) {
|
||||
switch (configuration.getDialect()) {
|
||||
switch (ctx.getDialect()) {
|
||||
case POSTGRES:
|
||||
return (T) pgNewUDTRecord(type, stmt.getObject(index));
|
||||
}
|
||||
@ -657,9 +659,7 @@ public final class FieldTypeHelper {
|
||||
}
|
||||
else if (Result.class.isAssignableFrom(type)) {
|
||||
ResultSet nested = (ResultSet) stmt.getObject(index);
|
||||
FieldProvider fields = new MetaDataFieldProvider(configuration, nested.getMetaData());
|
||||
Cursor<Record> cursor = new CursorImpl<Record>(configuration, fields, nested);
|
||||
return (T) cursor.fetch();
|
||||
return (T) getNewFactory(ctx).fetch(nested);
|
||||
}
|
||||
else {
|
||||
return (T) stmt.getObject(index);
|
||||
@ -923,9 +923,11 @@ public final class FieldTypeHelper {
|
||||
* Workarounds for the unimplemented Postgres JDBC driver features
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T pgGetArray(Configuration configuration, ResultSet rs, Class<? extends T> type, int index)
|
||||
private static <T> T pgGetArray(ExecuteContext ctx, Class<? extends T> type, int index)
|
||||
throws SQLException {
|
||||
|
||||
ResultSet rs = ctx.resultSet();
|
||||
|
||||
// Get the JDBC Array and check for null. If null, that's OK
|
||||
Array array = rs.getArray(index);
|
||||
if (array == null) {
|
||||
@ -943,9 +945,9 @@ public final class FieldTypeHelper {
|
||||
|
||||
// Try fetching the array as a JDBC ResultSet
|
||||
try {
|
||||
ResultSet elements = array.getResultSet();
|
||||
while (elements.next()) {
|
||||
result.add(getFromResultSet(configuration, elements, type.getComponentType(), 2));
|
||||
ctx.resultSet(array.getResultSet());
|
||||
while (ctx.resultSet().next()) {
|
||||
result.add(getFromResultSet(ctx, type.getComponentType(), 2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -956,6 +958,10 @@ public final class FieldTypeHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
finally {
|
||||
ctx.resultSet(rs);
|
||||
}
|
||||
|
||||
return (T) convertArray(result.toArray(), (Class<? extends Object[]>) type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,6 @@ import static org.jooq.impl.Factory.val;
|
||||
import static org.jooq.util.sqlite.SQLiteFactory.rowid;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
@ -54,6 +53,8 @@ import org.jooq.Attachable;
|
||||
import org.jooq.BindContext;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Identity;
|
||||
import org.jooq.InsertQuery;
|
||||
@ -305,23 +306,25 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final PreparedStatement prepare(Configuration configuration, String sql) throws SQLException {
|
||||
Connection connection = configuration.getConnection();
|
||||
protected final void prepare(ExecuteContext ctx) throws SQLException {
|
||||
Connection connection = ctx.getConnection();
|
||||
|
||||
// Just in case, always set Sybase ASE statement mode to return
|
||||
// Generated keys if client code wants to SELECT @@identity afterwards
|
||||
if (configuration.getDialect() == SQLDialect.ASE) {
|
||||
return connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
if (ctx.getDialect() == SQLDialect.ASE) {
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), Statement.RETURN_GENERATED_KEYS));
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal statement preparing if no values should be returned
|
||||
else if (returning.isEmpty()) {
|
||||
return super.prepare(configuration, sql);
|
||||
super.prepare(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
// Values should be returned from the INSERT
|
||||
else {
|
||||
switch (configuration.getDialect()) {
|
||||
switch (ctx.getDialect()) {
|
||||
|
||||
// Postgres uses the RETURNING clause in SQL
|
||||
case POSTGRES:
|
||||
@ -329,7 +332,8 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
case SQLITE:
|
||||
// Sybase will select @@identity after the INSERT
|
||||
case SYBASE:
|
||||
return super.prepare(configuration, sql);
|
||||
super.prepare(ctx);
|
||||
return;
|
||||
|
||||
// Some dialects can only return AUTO_INCREMENT values
|
||||
// Other values have to be fetched in a second step
|
||||
@ -339,7 +343,8 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
case INGRES:
|
||||
case MYSQL:
|
||||
case SQLSERVER:
|
||||
return connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), Statement.RETURN_GENERATED_KEYS));
|
||||
return;
|
||||
|
||||
// The default is to return all requested fields directly
|
||||
default: {
|
||||
@ -349,28 +354,28 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
names.add(field.getName());
|
||||
}
|
||||
|
||||
return connection.prepareStatement(sql, names.toArray(new String[names.size()]));
|
||||
ctx.statement(connection.prepareStatement(ctx.sql(), names.toArray(new String[names.size()])));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final int execute(Configuration configuration, PreparedStatement statement) throws SQLException {
|
||||
protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
|
||||
if (returning.isEmpty()) {
|
||||
return super.execute(configuration, statement);
|
||||
return super.execute(ctx, listener);
|
||||
}
|
||||
else {
|
||||
int result = 1;
|
||||
ResultSet rs;
|
||||
|
||||
switch (configuration.getDialect()) {
|
||||
switch (ctx.getDialect()) {
|
||||
|
||||
// SQLite can select _rowid_ after the insert
|
||||
case SQLITE: {
|
||||
result = statement.executeUpdate();
|
||||
result = ctx.statement().executeUpdate();
|
||||
|
||||
SQLiteFactory create = new SQLiteFactory(configuration.getConnection());
|
||||
SQLiteFactory create = new SQLiteFactory(ctx.getConnection());
|
||||
returned =
|
||||
create.select(returning)
|
||||
.from(getInto())
|
||||
@ -385,8 +390,8 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
// Generated keys don't work with jconn3, but they seem to work
|
||||
// with jTDS (which is used for Sybase ASE integration)
|
||||
case SYBASE: {
|
||||
result = statement.executeUpdate();
|
||||
selectReturning(configuration, create(configuration).lastID());
|
||||
result = ctx.statement().executeUpdate();
|
||||
selectReturning(ctx.configuration(), create(ctx).lastID());
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -398,8 +403,8 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
case INGRES:
|
||||
case MYSQL:
|
||||
case SQLSERVER: {
|
||||
result = statement.executeUpdate();
|
||||
rs = statement.getGeneratedKeys();
|
||||
result = ctx.statement().executeUpdate();
|
||||
rs = ctx.statement().getGeneratedKeys();
|
||||
|
||||
try {
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
@ -407,7 +412,7 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
list.add(rs.getObject(1));
|
||||
}
|
||||
|
||||
selectReturning(configuration, list.toArray());
|
||||
selectReturning(ctx, list.toArray());
|
||||
return result;
|
||||
}
|
||||
finally {
|
||||
@ -418,7 +423,7 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
// Postgres can execute the INSERT .. RETURNING clause like
|
||||
// a select clause. JDBC support is not implemented
|
||||
case POSTGRES: {
|
||||
rs = statement.executeQuery();
|
||||
rs = ctx.statement().executeQuery();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -428,15 +433,19 @@ class InsertQueryImpl<R extends Record> extends AbstractStoreQuery<R> implements
|
||||
case HSQLDB:
|
||||
case ORACLE:
|
||||
default: {
|
||||
result = statement.executeUpdate();
|
||||
rs = statement.getGeneratedKeys();
|
||||
result = ctx.statement().executeUpdate();
|
||||
rs = ctx.statement().getGeneratedKeys();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CursorImpl<R> cursor = new CursorImpl<R>(configuration, returning, rs, statement, getInto().getRecordType());
|
||||
returned = cursor.fetch();
|
||||
ExecuteListener listener2 = new ExecuteListeners(ctx.configuration());
|
||||
ExecuteContext ctx2 = new DefaultExecuteContext(ctx.configuration(), null);
|
||||
|
||||
ctx2.resultSet(rs);
|
||||
listener2.fetchStart(ctx2);
|
||||
returned = new CursorImpl<R>(ctx2, listener2, returning, getInto().getRecordType()).fetch();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static java.lang.Integer.toOctalString;
|
||||
import static org.jooq.impl.Factory.getDataType;
|
||||
import static org.jooq.tools.StringUtils.leftPad;
|
||||
@ -60,6 +61,8 @@ import org.jooq.AttachableInternal;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.FieldProvider;
|
||||
import org.jooq.NamedQueryPart;
|
||||
@ -73,6 +76,8 @@ import org.jooq.Table;
|
||||
import org.jooq.Type;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.tools.Convert;
|
||||
import org.jooq.tools.LoggerListener;
|
||||
import org.jooq.tools.StopWatchListener;
|
||||
import org.jooq.tools.StringUtils;
|
||||
|
||||
/**
|
||||
@ -86,7 +91,7 @@ final class Util {
|
||||
* Indicating whether JPA (<code>javax.persistence</code>) is on the
|
||||
* classpath.
|
||||
*/
|
||||
private static Boolean isJPAAvailable;
|
||||
private static Boolean isJPAAvailable;
|
||||
|
||||
/**
|
||||
* Create a new Oracle-style VARRAY {@link ArrayRecord}
|
||||
@ -451,6 +456,14 @@ final class Util {
|
||||
return new DataAccessException(message, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely close a statement
|
||||
*/
|
||||
static final void safeClose(ExecuteContext ctx) {
|
||||
safeClose(ctx.resultSet());
|
||||
safeClose(ctx.statement());
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely close a statement
|
||||
*/
|
||||
@ -810,6 +823,27 @@ final class Util {
|
||||
}
|
||||
}
|
||||
|
||||
static final List<ExecuteListener> getListeners(Configuration configuration) {
|
||||
List<ExecuteListener> result = new ArrayList<ExecuteListener>();
|
||||
|
||||
if (!FALSE.equals(configuration.getSettings().isExecuteLogging())) {
|
||||
result.add(new StopWatchListener());
|
||||
result.add(new LoggerListener());
|
||||
}
|
||||
|
||||
for (String listener : configuration.getSettings().getExecuteListeners()) {
|
||||
try {
|
||||
// [#1170] TODO: Cache these classes?
|
||||
result.add((ExecuteListener) Class.forName(listener).newInstance());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a piece of SQL code in parentheses, if not wrapped already
|
||||
*/
|
||||
|
||||
128
jOOQ/src/main/java/org/jooq/tools/LoggerListener.java
Normal file
128
jOOQ/src/main/java/org/jooq/tools/LoggerListener.java
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, 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.tools;
|
||||
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
|
||||
/**
|
||||
* A default {@link ExecuteListener} that just logs events to java.util.logging,
|
||||
* log4j, or slf4j using the {@link JooqLogger}
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class LoggerListener implements ExecuteListener {
|
||||
|
||||
private static final JooqLogger log = JooqLogger.getLogger(LoggerListener.class);
|
||||
|
||||
@Override
|
||||
public void init(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderStart(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderEnd(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStart(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnd(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindStart(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindEnd(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeStart(ExecuteContext ctx) {
|
||||
if (log.isDebugEnabled()) {
|
||||
if (ctx.query() != null) {
|
||||
log.debug("Executing query", ctx.query().getSQL(true));
|
||||
}
|
||||
else if (!StringUtils.isBlank(ctx.sql())) {
|
||||
log.debug("Executing query", ctx.sql());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeEnd(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchStart(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchEnd(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordStart(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordEnd(ExecuteContext ctx) {
|
||||
if (log.isTraceEnabled() && ctx.record() != null)
|
||||
log.trace("Record fetched", ctx.record());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resultStart(ExecuteContext ctx) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resultEnd(ExecuteContext ctx) {
|
||||
if (log.isDebugEnabled() && ctx.result() != null) {
|
||||
String comment = "Fetched result";
|
||||
|
||||
for (String line : ctx.result().format(5).split("\n")) {
|
||||
log.debug(comment, line);
|
||||
comment = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
125
jOOQ/src/main/java/org/jooq/tools/StopWatchListener.java
Normal file
125
jOOQ/src/main/java/org/jooq/tools/StopWatchListener.java
Normal file
@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, 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.tools;
|
||||
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
|
||||
/**
|
||||
* A default {@link ExecuteListener} that just logs events to java.util.logging,
|
||||
* log4j, or slf4j using the {@link JooqLogger}
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class StopWatchListener implements ExecuteListener {
|
||||
|
||||
private final StopWatch watch = new StopWatch();
|
||||
|
||||
@Override
|
||||
public void init(ExecuteContext ctx) {
|
||||
watch.splitTrace("Initialising");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Rendering query");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderEnd(ExecuteContext ctx) {
|
||||
watch.splitTrace("Query rendered");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Preparing statement");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnd(ExecuteContext ctx) {
|
||||
watch.splitTrace("Statement prepared");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Binding variables");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindEnd(ExecuteContext ctx) {
|
||||
watch.splitTrace("Variables bound");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Executing query");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeEnd(ExecuteContext ctx) {
|
||||
watch.splitDebug("Query executed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Fetching results");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchEnd(ExecuteContext ctx) {
|
||||
watch.splitDebug("Results fetched");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Fetching record");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordEnd(ExecuteContext ctx) {
|
||||
watch.splitTrace("Record fetched");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resultStart(ExecuteContext ctx) {
|
||||
watch.splitTrace("Fetching result");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resultEnd(ExecuteContext ctx) {
|
||||
watch.splitTrace("Result fetched");
|
||||
}
|
||||
}
|
||||
@ -18,20 +18,19 @@
|
||||
<element name="settings" type="jooq-runtime:Settings"/>
|
||||
|
||||
<complexType name="Settings">
|
||||
<all>
|
||||
<!-- Configure query rendering properties -->
|
||||
<element name="rendering" type="jooq-runtime:Rendering" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<!-- Configure query execution properties -->
|
||||
<element name="execution" type="jooq-runtime:Execution" minOccurs="0" maxOccurs="1"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<complexType name="Rendering">
|
||||
<all>
|
||||
<!-- Configure render mapping for runtime schema / table rewriting in
|
||||
generated SQL -->
|
||||
<element name="renderMapping" type="jooq-runtime:RenderMapping" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<!-- 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"/>
|
||||
|
||||
<!-- The event listeners to be notified upon execution events -->
|
||||
<element name="executeListeners" type="jooq-runtime:ExecuteListeners" minOccurs="0" maxOccurs="1"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
@ -83,17 +82,24 @@
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<complexType name="Execution">
|
||||
<all>
|
||||
<!-- The type of statement that is to be executed -->
|
||||
<element name="statementType" type="jooq-runtime:StatementType" minOccurs="0" maxOccurs="1" default="PREPARED_STATEMENT"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<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>
|
||||
|
||||
<complexType name="ExecuteListeners">
|
||||
<sequence>
|
||||
|
||||
<!-- An event listener implementing org.jooq.ExecuteListener -->
|
||||
<element name="executeListener" type="string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</schema>
|
||||
Loading…
Reference in New Issue
Block a user