[#1472] Move org.jooq.tools.debug API from jOOQ Console to core - Added

QueryExecutor.schemata(), .tables(Schema), .fields(Table) in order to
query for meta data
This commit is contained in:
Lukas Eder 2012-09-24 23:33:49 +02:00
parent 94225e8d5f
commit 20d9d02cdc
5 changed files with 253 additions and 7 deletions

View File

@ -36,6 +36,7 @@
package org.jooq.test._.testcases;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.jooq.impl.Factory.inline;
import static org.jooq.tools.debug.impl.DebuggerFactory.localDebugger;
@ -48,6 +49,8 @@ import java.util.List;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.TableRecord;
import org.jooq.UpdatableRecord;
import org.jooq.test.BaseTest;
@ -294,6 +297,31 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
@Override
public Step before(HitContext context) {
if (schema() != null) {
List<Schema> schemata = Arrays.asList(context.executor().schemata());
assertTrue(schemata.contains(schema()));
}
List<Table<?>> tables1 = Arrays.asList(context.executor().tables());
assertTrue(tables1.contains(TBook()));
assertTrue(tables1.contains(TAuthor()));
if (schema() != null) {
List<Table<?>> tables2 = Arrays.asList(context.executor().tables(schema()));
assertTrue(tables2.contains(TBook()));
assertTrue(tables2.contains(TAuthor()));
}
List<Field<?>> fields1 = Arrays.asList(context.executor().fields());
assertTrue(fields1.contains(TBook_ID()));
assertTrue(fields1.contains(TBook_TITLE()));
assertTrue(fields1.contains(TAuthor_ID()));
List<Field<?>> fields2 = Arrays.asList(context.executor().fields(TBook()));
assertTrue(fields2.contains(TBook_ID()));
assertTrue(fields2.contains(TBook_TITLE()));
assertFalse(fields2.contains(TAuthor_ID()));
Result<Record> result =
context.executor().fetch(create().selectCount().from(TAuthor()));

View File

@ -955,6 +955,31 @@ public class Factory implements FactoryOperations {
// XXX Plain SQL object factory
// -------------------------------------------------------------------------
/**
* Create a qualified schema, given its schema name
* <p>
* This constructs a schema reference given the schema's qualified name.
* jOOQ will render the schema name according to your
* {@link Settings#getRenderNameStyle()} settings. Choose
* {@link RenderNameStyle#QUOTED} to prevent syntax errors and/or SQL
* injection.
* <p>
* Example: <code><pre>
* // This schema...
* schemaByName("MY_SCHEMA");
*
* // ... will render this SQL on SQL Server with RenderNameStyle.QUOTED set
* [MY_SCHEMA]
* </pre></code>
*
* @param name The schema's reference name.
* @return A schema referenced by <code>name</code>
*/
@Support
public static Schema schemaByName(String name) {
return new SchemaImpl(name);
}
/**
* A custom SQL clause that can render arbitrary table expressions.
* <p>
@ -1066,7 +1091,7 @@ public class Factory implements FactoryOperations {
* <p>
* Example: <code><pre>
* // This table...
* tableName("MY_SCHEMA", "MY_TABLE");
* tableByName("MY_SCHEMA", "MY_TABLE");
*
* // ... will render this SQL on SQL Server with RenderNameStyle.QUOTED set
* [MY_SCHEMA].[MY_TABLE]
@ -1350,7 +1375,7 @@ public class Factory implements FactoryOperations {
* <p>
* Example: <code><pre>
* // This field...
* fieldName("MY_SCHEMA", "MY_TABLE", "MY_FIELD");
* fieldByName("MY_SCHEMA", "MY_TABLE", "MY_FIELD");
*
* // ... will render this SQL on SQL Server with RenderNameStyle.QUOTED set
* [MY_SCHEMA].[MY_TABLE].[MY_FIELD]
@ -1385,7 +1410,7 @@ public class Factory implements FactoryOperations {
* <p>
* Example: <code><pre>
* // This field...
* fieldName("MY_SCHEMA", "MY_TABLE", "MY_FIELD");
* fieldByName("MY_SCHEMA", "MY_TABLE", "MY_FIELD");
*
* // ... will render this SQL on SQL Server with RenderNameStyle.QUOTED set
* [MY_SCHEMA].[MY_TABLE].[MY_FIELD]
@ -1421,7 +1446,7 @@ public class Factory implements FactoryOperations {
* <p>
* Example: <code><pre>
* // This field...
* fieldName("MY_SCHEMA", "MY_TABLE", "MY_FIELD");
* fieldByName("MY_SCHEMA", "MY_TABLE", "MY_FIELD");
*
* // ... will render this SQL on SQL Server with RenderNameStyle.QUOTED set
* [MY_SCHEMA].[MY_TABLE].[MY_FIELD]

View File

@ -36,10 +36,13 @@
*/
package org.jooq.tools.debug;
import org.jooq.Field;
import org.jooq.Query;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.ResultQuery;
import org.jooq.Schema;
import org.jooq.Table;
/**
* A query executor allows to execute queries in any given context.
@ -49,6 +52,31 @@ import org.jooq.ResultQuery;
*/
public interface QueryExecutor {
/**
* Fetch all schemata
*
* @return A list of schemata
*/
Schema[] schemata();
/**
* Fetch all tables, given a list of schemata.
*
* @param schemata The list of schemata for which to fetch tables. If no
* schema is provided, all tables are fetched.
* @return A list of tables
*/
Table<?>[] tables(Schema... schemata);
/**
* Fetch all fields, given a list of tables.
*
* @param tables The list of tables for which to fetch fields. If no table
* is provided, all fields are fetched.
* @return A list of fields.
*/
Field<?>[] fields(Table<?>... tables);
/**
* Execute a query
*/

View File

@ -40,10 +40,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.jooq.Field;
import org.jooq.Query;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.ResultQuery;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.tools.debug.Breakpoint;
import org.jooq.tools.debug.BreakpointListener;
import org.jooq.tools.debug.Debugger;
@ -238,6 +241,21 @@ class ClientDebugger extends AbstractDebuggerObject implements Debugger {
if (executor == null) {
executor = new QueryExecutor() {
@Override
public Schema[] schemata() {
return context.getClientDebugger().getCommunicationInterface().syncSend(new CMC_schemata());
}
@Override
public Table<?>[] tables(Schema... schemata) {
return context.getClientDebugger().getCommunicationInterface().syncSend(new CMC_tables(schemata));
}
@Override
public Field<?>[] fields(Table<?>... tables) {
return context.getClientDebugger().getCommunicationInterface().syncSend(new CMC_fields(tables));
}
@Override
public <R extends Record> Result<R> fetch(ResultQuery<R> query) {
return context.getClientDebugger().getCommunicationInterface().syncSend(new CMC_fetch<R>(query));
@ -254,6 +272,60 @@ class ClientDebugger extends AbstractDebuggerObject implements Debugger {
}
}
static class CMC_schemata extends CommandMessage<Schema[]> {
/**
* Generated UID
*/
private static final long serialVersionUID = -9163573787750356644L;
CMC_schemata() {
}
@Override
public Schema[] run(MessageContext context) {
return DebugListener.BREAKPOINT_EXECUTORS.get().schemata();
}
}
static class CMC_tables extends CommandMessage<Table<?>[]> {
/**
* Generated UID
*/
private static final long serialVersionUID = -9163573787750356644L;
private final Schema[] schemata;
CMC_tables(Schema[] schemata) {
this.schemata = schemata;
}
@Override
public Table<?>[] run(MessageContext context) {
return DebugListener.BREAKPOINT_EXECUTORS.get().tables(schemata);
}
}
static class CMC_fields extends CommandMessage<Field<?>[]> {
/**
* Generated UID
*/
private static final long serialVersionUID = -9163573787750356644L;
private final Table<?>[] tables;
CMC_fields(Table<?>[] tables) {
this.tables = tables;
}
@Override
public Field<?>[] run(MessageContext context) {
return DebugListener.BREAKPOINT_EXECUTORS.get().fields(tables);
}
}
static class CMC_fetch<R extends Record> extends CommandMessage<Result<R>> {
/**

View File

@ -36,11 +36,24 @@
*/
package org.jooq.tools.debug.impl;
import static org.jooq.impl.Factory.fieldByName;
import static org.jooq.impl.Factory.schemaByName;
import static org.jooq.impl.Factory.tableByName;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.jooq.Configuration;
import org.jooq.Field;
import org.jooq.Query;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.ResultQuery;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.Factory;
import org.jooq.tools.debug.QueryExecutor;
@ -59,18 +72,98 @@ class QueryExecutorImpl implements QueryExecutor {
}
@Override
public int execute(Query query) {
public final Schema[] schemata() {
try {
DatabaseMetaData meta = meta();
String[] names = create().fetch(meta.getSchemas()).intoArray(0, String.class);
Schema[] result = new Schema[names.length];
for (int i = 0; i < names.length; i++) {
result[i] = schemaByName(names[i]);
}
return result;
}
catch (SQLException e) {
throw new DataAccessException("Cannot fetch schemata", e);
}
}
@Override
public final Table<?>[] tables(Schema... schemata) {
schemata = (schemata != null && schemata.length > 0) ? schemata : new Schema[] { null };
List<Table<?>> result = new ArrayList<Table<?>>();
try {
DatabaseMetaData meta = meta();
for (Schema schema : schemata) {
String schemaName = (schema != null) ? schema.getName() : null;
for (Record record : create().fetch(meta.getTables(null, schemaName, null, null))) {
result.add(tableByName(
record.getValue(1, String.class),
record.getValue(2, String.class)));
}
}
return result.toArray(new Table[result.size()]);
}
catch (SQLException e) {
throw new DataAccessException("Cannot fetch tables", e);
}
}
@Override
public final Field<?>[] fields(Table<?>... tables) {
tables = (tables != null && tables.length > 0) ? tables : new Table[] { null };
List<Field<?>> result = new ArrayList<Field<?>>();
try {
DatabaseMetaData meta = meta();
for (Table<?> table : tables) {
String schemaName = (table != null && table.getSchema() != null) ? table.getSchema().getName() : null;
String tableName = (table != null) ? table.getName() : null;
for (Record record : create().fetch(meta.getColumns(null, schemaName, tableName, null))) {
// Discover SQLDataType, here?
result.add(fieldByName(
record.getValue(1, String.class),
record.getValue(2, String.class),
record.getValue(3, String.class)));
}
}
return result.toArray(new Field[result.size()]);
}
catch (SQLException e) {
throw new DataAccessException("Cannot fetch fields", e);
}
}
@Override
public final int execute(Query query) {
create().attach(query);
return query.execute();
}
@Override
public <R extends Record> Result<R> fetch(ResultQuery<R> query) {
public final <R extends Record> Result<R> fetch(ResultQuery<R> query) {
create().attach(query);
return query.fetch();
}
private Factory create() {
private final DatabaseMetaData meta() {
try {
return create().getConnection().getMetaData();
}
catch (SQLException e) {
throw new DataAccessException("Cannot fetch meta data", e);
}
}
private final Factory create() {
return new Factory(configuration.getConnection(), configuration.getDialect(), configuration.getSettings());
}
}