[#2044] Add various TableRecord.fetchParent(...), fetchChild(...) and

fetchChildren(...) methods to follow foreign key relationships
This commit is contained in:
Lukas Eder 2012-12-22 20:39:49 +01:00
parent 49ee1f98f4
commit d756297151
27 changed files with 668 additions and 39 deletions

View File

@ -46,6 +46,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -62,6 +63,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.ase.generatedclasses.Keys;
import org.jooq.test.ase.generatedclasses.tables.TAuthor;
import org.jooq.test.ase.generatedclasses.tables.TBook;
import org.jooq.test.ase.generatedclasses.tables.TBookStore;
@ -215,6 +217,16 @@ public class ASETest extends jOOQAbstractTest<
return TBookToBookStore.STOCK;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<T_725LobTestRecord> T725() {
return T_725LobTest.T_725_LOB_TEST;

View File

@ -45,12 +45,17 @@ import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import junit.framework.Assert;
import org.jooq.ArrayRecord;
import org.jooq.DAO;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record2;
@ -466,6 +471,14 @@ public abstract class BaseTest<
return delegate.TBook_STATUS();
}
protected ForeignKey<B, A> FK_T_BOOK_AUTHOR_ID() {
return delegate.FK_T_BOOK_AUTHOR_ID();
}
protected ForeignKey<B, A> FK_T_BOOK_CO_AUTHOR_ID() {
return delegate.FK_T_BOOK_CO_AUTHOR_ID();
}
protected UpdatableTable<S> TBookStore() {
return delegate.TBookStore();
}
@ -844,4 +857,10 @@ public abstract class BaseTest<
// Dummy parameters for SQL Server
protected static Integer DUMMY_OUT_INT = new Integer(0);
protected static <E> void assertSame(Collection<E> expected, Collection<E> actual) {
if (!new HashSet<E>(expected).equals(new HashSet<E>(actual))) {
Assert.fail("Collections aren't the same : " + expected + " and " + actual);
}
}
}

View File

@ -47,6 +47,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -63,6 +64,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.cubrid.generatedclasses.Keys;
import org.jooq.test.cubrid.generatedclasses.Sequences;
import org.jooq.test.cubrid.generatedclasses.tables.TAuthor;
import org.jooq.test.cubrid.generatedclasses.tables.TBook;
@ -484,6 +486,16 @@ public class CUBRIDTest extends jOOQAbstractTest<
return TBook.STATUS;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -51,6 +51,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -67,6 +68,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.db2.generatedclasses.Keys;
import org.jooq.test.db2.generatedclasses.Routines;
import org.jooq.test.db2.generatedclasses.Sequences;
import org.jooq.test.db2.generatedclasses.tables.TAuthor;
@ -497,6 +499,16 @@ public class DB2Test extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -52,6 +52,7 @@ import java.sql.Timestamp;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -68,6 +69,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.derby.generatedclasses.Keys;
import org.jooq.test.derby.generatedclasses.Sequences;
import org.jooq.test.derby.generatedclasses.tables.TAuthor;
import org.jooq.test.derby.generatedclasses.tables.TBook;
@ -499,6 +501,16 @@ public class DerbyTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -57,6 +57,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -73,6 +74,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.firebird.generatedclasses.Keys;
import org.jooq.test.firebird.generatedclasses.Sequences;
import org.jooq.test.firebird.generatedclasses.tables.records.TAuthorRecord;
import org.jooq.test.firebird.generatedclasses.tables.records.TBookRecord;
@ -482,6 +484,16 @@ public class FirebirdTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -53,6 +53,7 @@ import org.jooq.ArrayRecord;
import org.jooq.DAO;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -69,6 +70,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.h2.generatedclasses.Keys;
import org.jooq.test.h2.generatedclasses.Routines;
import org.jooq.test.h2.generatedclasses.Sequences;
import org.jooq.test.h2.generatedclasses.tables.TArrays;
@ -514,6 +516,16 @@ public class H2Test extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -61,6 +61,7 @@ import java.sql.Timestamp;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -77,6 +78,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.hsqldb.generatedclasses.Keys;
import org.jooq.test.hsqldb.generatedclasses.Routines;
import org.jooq.test.hsqldb.generatedclasses.Sequences;
import org.jooq.test.hsqldb.generatedclasses.tables.records.TArraysRecord;
@ -498,6 +500,16 @@ public class HSQLDBTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -58,6 +58,7 @@ import java.util.List;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -77,6 +78,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.h2.generatedclasses.Keys;
import org.jooq.test.h2.generatedclasses.Routines;
import org.jooq.test.h2.generatedclasses.Sequences;
import org.jooq.test.h2.generatedclasses.tables.records.TArraysRecord;
@ -502,6 +504,16 @@ public class HSQLDBTest2 extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -51,6 +51,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -67,6 +68,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.ingres.generatedclasses.Keys;
import org.jooq.test.ingres.generatedclasses.Sequences;
import org.jooq.test.ingres.generatedclasses.tables.TAuthor;
import org.jooq.test.ingres.generatedclasses.tables.TBook;
@ -489,6 +491,16 @@ public class IngresTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -37,6 +37,7 @@
package org.jooq.test;
import static junit.framework.Assert.assertNull;
import static org.jooq.impl.Factory.md5;
import static org.jooq.impl.Factory.val;
import static org.jooq.test.mysql.generatedclasses.Tables.T_BOOK_TO_BOOK_STORE;
import static org.jooq.test.mysql.generatedclasses.Tables.T_BOOLEANS;
@ -52,7 +53,6 @@ import static org.jooq.util.mysql.MySQLFactory.decode;
import static org.jooq.util.mysql.MySQLFactory.desDecrypt;
import static org.jooq.util.mysql.MySQLFactory.desEncrypt;
import static org.jooq.util.mysql.MySQLFactory.encode;
import static org.jooq.util.mysql.MySQLFactory.md5;
import static org.jooq.util.mysql.MySQLFactory.password;
import static org.jooq.util.mysql.MySQLFactory.sha1;
import static org.jooq.util.mysql.MySQLFactory.sha2;
@ -70,6 +70,7 @@ import org.jooq.ArrayRecord;
import org.jooq.DAO;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -86,6 +87,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.mysql.generatedclasses.Keys;
import org.jooq.test.mysql.generatedclasses.Routines;
import org.jooq.test.mysql.generatedclasses.enums.TBookStatus;
import org.jooq.test.mysql.generatedclasses.enums.T_959JavaKeywords;
@ -520,6 +522,16 @@ public class MySQLTest extends jOOQAbstractTest<
return TBook.STATUS;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -59,6 +59,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -75,6 +76,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.mysql2.generatedclasses.Keys;
import org.jooq.test.mysql2.generatedclasses.Routines;
import org.jooq.test.mysql2.generatedclasses.tables.records.TAuthorRecord;
import org.jooq.test.mysql2.generatedclasses.tables.records.TBookRecord;
@ -490,6 +492,16 @@ public class MySQLTestSchemaRewrite extends jOOQAbstractTest<
return T_BOOK.STATUS;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -90,6 +90,7 @@ import org.jooq.ArrayRecord;
import org.jooq.DAO;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -107,6 +108,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.oracle.generatedclasses.multi_schema.tables.records.TBookSaleRecord;
import org.jooq.test.oracle.generatedclasses.test.Keys;
import org.jooq.test.oracle.generatedclasses.test.Routines;
import org.jooq.test.oracle.generatedclasses.test.Sequences;
import org.jooq.test.oracle.generatedclasses.test.packages.Library;
@ -571,6 +573,16 @@ public class OracleTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -63,6 +63,7 @@ import java.util.List;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -79,6 +80,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.postgres.generatedclasses.Keys;
import org.jooq.test.postgres.generatedclasses.Routines;
import org.jooq.test.postgres.generatedclasses.Sequences;
import org.jooq.test.postgres.generatedclasses.enums.U_959;
@ -496,6 +498,16 @@ public class PostgresTest extends jOOQAbstractTest<
return T_BOOK.STATUS;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -59,6 +59,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -75,6 +76,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.sqlserver.generatedclasses.Keys;
import org.jooq.test.sqlserver.generatedclasses.Routines;
import org.jooq.test.sqlserver.generatedclasses.tables.records.TAuthorRecord;
import org.jooq.test.sqlserver.generatedclasses.tables.records.TBookRecord;
@ -484,6 +486,16 @@ public class SQLServerTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -49,6 +49,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -65,6 +66,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.sqlite.generatedclasses.Keys;
import org.jooq.test.sqlite.generatedclasses.tables.TAuthor;
import org.jooq.test.sqlite.generatedclasses.tables.TBook;
import org.jooq.test.sqlite.generatedclasses.tables.TBookStore;
@ -483,6 +485,16 @@ public class SQLiteTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.FK_T_BOOK_T_AUTHOR_1;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.FK_T_BOOK_T_AUTHOR_2;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return VLibrary.V_LIBRARY;

View File

@ -54,6 +54,7 @@ import java.sql.Date;
import org.jooq.ArrayRecord;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
@ -70,6 +71,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_LC;
import org.jooq.test._.converters.Boolean_YES_NO_UC;
import org.jooq.test._.converters.Boolean_YN_LC;
import org.jooq.test._.converters.Boolean_YN_UC;
import org.jooq.test.sybase.generatedclasses.Keys;
import org.jooq.test.sybase.generatedclasses.Routines;
import org.jooq.test.sybase.generatedclasses.Sequences;
import org.jooq.test.sybase.generatedclasses.tables.records.TAuthorRecord;
@ -479,6 +481,16 @@ public class SybaseTest extends jOOQAbstractTest<
return null;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_AUTHOR_ID;
}
@Override
protected ForeignKey<TBookRecord, TAuthorRecord> FK_T_BOOK_CO_AUTHOR_ID() {
return Keys.T_BOOK__FK_T_BOOK_CO_AUTHOR_ID;
}
@Override
protected Table<VLibraryRecord> VLibrary() {
return V_LIBRARY;

View File

@ -0,0 +1,112 @@
/**
* 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.test._.testcases;
import static java.util.Arrays.asList;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import java.sql.Date;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.Record3;
import org.jooq.Record6;
import org.jooq.Result;
import org.jooq.TableRecord;
import org.jooq.UpdatableRecord;
import org.jooq.test.BaseTest;
import org.jooq.test.jOOQAbstractTest;
import org.junit.Test;
public class ReferentialTests<
A extends UpdatableRecord<A> & Record6<Integer, String, String, Date, Integer, ?>,
AP,
B extends UpdatableRecord<B>,
S extends UpdatableRecord<S> & Record1<String>,
B2S extends UpdatableRecord<B2S> & Record3<String, Integer, Integer>,
BS extends UpdatableRecord<BS>,
L extends TableRecord<L> & Record2<String, String>,
X extends TableRecord<X>,
DATE extends UpdatableRecord<DATE>,
BOOL extends UpdatableRecord<BOOL>,
D extends UpdatableRecord<D>,
T extends UpdatableRecord<T>,
U extends TableRecord<U>,
I extends TableRecord<I>,
IPK extends UpdatableRecord<IPK>,
T725 extends UpdatableRecord<T725>,
T639 extends UpdatableRecord<T639>,
T785 extends TableRecord<T785>>
extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T725, T639, T785> {
public ReferentialTests(jOOQAbstractTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T725, T639, T785> delegate) {
super(delegate);
}
@SuppressWarnings("unchecked")
@Test
public void testFetchParentAndChildren() throws Exception {
Result<A> authors = create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch();
Result<B> books = create().selectFrom(TBook()).orderBy(TBook_ID()).fetch();
A a1 = authors.get(0);
A a2 = authors.get(1);
B b1 = books.get(0);
B b2 = books.get(1);
B b3 = books.get(2);
B b4 = books.get(3);
// Fetching parents
assertEquals(a1, b1.fetchParent(FK_T_BOOK_AUTHOR_ID()));
assertEquals(a1, FK_T_BOOK_AUTHOR_ID().fetchParent(b1));
assertSame(asList(a1), FK_T_BOOK_AUTHOR_ID().fetchParents(b1, b2));
assertSame(asList(a1, a2), FK_T_BOOK_AUTHOR_ID().fetchParents(b1, b3));
assertSame(asList(a1, a2), FK_T_BOOK_AUTHOR_ID().fetchParents(b1, b2, b3, b4));
// Fetching children
assertSame(asList(b1, b2), a1.fetchChildren(FK_T_BOOK_AUTHOR_ID()));
assertSame(asList(b1, b2), FK_T_BOOK_AUTHOR_ID().fetchChildren(a1));
assertSame(asList(b3, b4), a2.fetchChildren(FK_T_BOOK_AUTHOR_ID()));
assertSame(asList(b3, b4), FK_T_BOOK_AUTHOR_ID().fetchChildren(a2));
assertSame(asList(b1, b2, b3, b4), FK_T_BOOK_AUTHOR_ID().fetchChildren(a1, a2));
// No co-authors available
assertNull(b1.fetchParent(FK_T_BOOK_CO_AUTHOR_ID()));
assertNull(a1.fetchChild(FK_T_BOOK_CO_AUTHOR_ID()));
}
}

View File

@ -65,6 +65,7 @@ import org.jooq.DAO;
import org.jooq.DataType;
import org.jooq.ExecuteType;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record2;
@ -117,6 +118,7 @@ import org.jooq.test._.testcases.OrderByTests;
import org.jooq.test._.testcases.PlainSQLTests;
import org.jooq.test._.testcases.PredicateTests;
import org.jooq.test._.testcases.RecordTests;
import org.jooq.test._.testcases.ReferentialTests;
import org.jooq.test._.testcases.RenderAndBindTests;
import org.jooq.test._.testcases.ResultTests;
import org.jooq.test._.testcases.RoutineAndUDTTests;
@ -656,6 +658,8 @@ public abstract class jOOQAbstractTest<
protected TableField<B, Timestamp> TBook_REC_TIMESTAMP() {
return null;
}
protected abstract ForeignKey<B, A> FK_T_BOOK_AUTHOR_ID();
protected abstract ForeignKey<B, A> FK_T_BOOK_CO_AUTHOR_ID();
protected abstract UpdatableTable<S> TBookStore();
protected abstract TableField<S, String> TBookStore_NAME();
@ -1088,6 +1092,11 @@ public abstract class jOOQAbstractTest<
new ResultTests(this).testResultSort();
}
@Test
public void testFetchParentAndChildren() throws Exception {
new ReferentialTests(this).testFetchParentAndChildren();
}
@Test
public void testFetch() throws Exception {
new FetchTests(this).testFetch();

View File

@ -35,18 +35,92 @@
*/
package org.jooq;
import java.util.Collection;
import org.jooq.exception.DataAccessException;
/**
* A <code>ForeignKey</code> is an object referencing a {@link UniqueKey}. It
* represents a <code>FOREIGN KEY</code> relationship between two tables.
*
*
* @param <R> The <code>FOREIGN KEY</code>'s owner table record
* @param <U> The referenced <code>KEY</code>'s owner table record
* @param <O> The referenced <code>KEY</code>'s owner table record
* @author Lukas Eder
*/
public interface ForeignKey<R extends Record, U extends Record> extends Key<R> {
public interface ForeignKey<R extends Record, O extends Record> extends Key<R> {
/**
* The referenced <code>Key</code>
*/
UniqueKey<U> getKey();
UniqueKey<O> getKey();
/**
* Fetch a parent record of a given record through this foreign key
* <p>
* This returns a parent record referenced by a given record through this
* foreign key. If no parent record was found, this returns
* <code>null</code>
*
* @throws DataAccessException if something went wrong executing the query
* @see TableRecord#fetchParent(ForeignKey)
*/
O fetchParent(R record) throws DataAccessException;
/**
* Fetch parent records of a given set of record through this foreign key
* <p>
* This returns parent records referenced by any record in a given set of
* records through this foreign key.
*
* @throws DataAccessException if something went wrong executing the query
* @see TableRecord#fetchParent(ForeignKey)
*/
Result<O> fetchParents(R... records) throws DataAccessException;
/**
* Fetch parent records of a given set of record through this foreign key
* <p>
* This returns parent records referenced by any record in a given set of
* records through this foreign key.
*
* @throws DataAccessException if something went wrong executing the query
* @see TableRecord#fetchParent(ForeignKey)
*/
Result<O> fetchParents(Collection<? extends R> records) throws DataAccessException;
/**
* Fetch child records of a given record through this foreign key
* <p>
* This returns childs record referencing a given record through this
* foreign key
*
* @throws DataAccessException if something went wrong executing the query
* @see UpdatableRecord#fetchChild(ForeignKey)
* @see UpdatableRecord#fetchChildren(ForeignKey)
*/
Result<R> fetchChildren(O record) throws DataAccessException;
/**
* Fetch child records of a given set of records through this foreign key
* <p>
* This returns childs record referencing any record in a given set of
* records through this foreign key
*
* @throws DataAccessException if something went wrong executing the query
* @see UpdatableRecord#fetchChild(ForeignKey)
* @see UpdatableRecord#fetchChildren(ForeignKey)
*/
Result<R> fetchChildren(O... records) throws DataAccessException;
/**
* Fetch child records of a given set of records through this foreign key
* <p>
* This returns childs record referencing any record in a given set of
* records through this foreign key
*
* @throws DataAccessException if something went wrong executing the query
* @see UpdatableRecord#fetchChild(ForeignKey)
* @see UpdatableRecord#fetchChildren(ForeignKey)
*/
Result<R> fetchChildren(Collection<? extends O> records) throws DataAccessException;
}

View File

@ -35,6 +35,7 @@
*/
package org.jooq;
import org.jooq.exception.DataAccessException;
/**
* A record originating from a single table
@ -54,4 +55,18 @@ public interface TableRecord<R extends TableRecord<R>> extends Record {
*/
@Override
R original();
/**
* Fetch a parent record of this record, given a foreign key
* <p>
* This returns a parent record referenced by this record through a given
* foreign key. If no parent record was found, this returns
* <code>null</code>
*
* @throws DataAccessException if something went wrong executing the query
* @see ForeignKey#fetchParent(Record)
* @see ForeignKey#fetchParents(java.util.Collection)
* @see ForeignKey#fetchParents(Record...)
*/
<O extends UpdatableRecord<O>> O fetchParent(ForeignKey<R, O> key) throws DataAccessException;
}

View File

@ -41,6 +41,7 @@ import java.sql.Statement;
import org.jooq.conf.Settings;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.DataChangedException;
import org.jooq.exception.InvalidResultException;
import org.jooq.impl.Executor;
/**
@ -304,7 +305,7 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable
* record does not exist anymore in the database</li>
* </ul>
*/
void refresh(Field<?>... fields);
void refresh(Field<?>... fields) throws DataAccessException;
/**
* Duplicate this record (in memory) and reset all fields from the primary
@ -314,4 +315,31 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable
* @return A new record, distinct from <code>this</code> record.
*/
R copy();
/**
* Fetch a child record of this record, given a foreign key
* <p>
* This returns a child record referencing this record through a given
* foreign key. If no child record was found, this returns <code>null</code>
*
* @throws DataAccessException if something went wrong executing the query
* @throws InvalidResultException if the query returned more than one record
* @see ForeignKey#fetchChildren(java.util.Collection)
* @see ForeignKey#fetchChildren(Record)
* @see ForeignKey#fetchChildren(Record...)
*/
<O extends TableRecord<O>> O fetchChild(ForeignKey<O, R> key) throws InvalidResultException, DataAccessException;
/**
* Fetch child records of this record, given a foreign key
* <p>
* This returns childs record referencing this record through a given
* foreign key.
*
* @throws DataAccessException if something went wrong executing the query
* @see ForeignKey#fetchChildren(java.util.Collection)
* @see ForeignKey#fetchChildren(Record)
* @see ForeignKey#fetchChildren(Record...)
*/
<O extends TableRecord<O>> Result<O> fetchChildren(ForeignKey<O, R> key) throws DataAccessException;
}

View File

@ -1154,7 +1154,7 @@ public class Executor implements Configuration {
*/
@Support
public final Record fetchOne(ResultSet rs) throws DataAccessException, InvalidResultException {
return filterOne(fetchLazy(rs).fetch());
return Utils.filterOne(fetchLazy(rs).fetch());
}
/**
@ -2417,7 +2417,7 @@ public class Executor implements Configuration {
*/
@Support
public final <R extends Record> R fetchOne(Table<R> table) throws DataAccessException, InvalidResultException {
return filterOne(fetch(table));
return Utils.filterOne(fetch(table));
}
/**
@ -2434,7 +2434,7 @@ public class Executor implements Configuration {
*/
@Support
public final <R extends Record> R fetchOne(Table<R> table, Condition condition) throws DataAccessException, InvalidResultException {
return filterOne(fetch(table, condition));
return Utils.filterOne(fetch(table, condition));
}
/**
@ -2450,7 +2450,7 @@ public class Executor implements Configuration {
*/
@Support
public final <R extends Record> R fetchAny(Table<R> table) throws DataAccessException {
return filterOne(selectFrom(table).limit(1).fetch());
return Utils.filterOne(selectFrom(table).limit(1).fetch());
}
/**
@ -2549,19 +2549,6 @@ public class Executor implements Configuration {
// XXX Internals
// -------------------------------------------------------------------------
private static <R extends Record> R filterOne(List<R> list) throws InvalidResultException {
int size = list.size();
if (size == 1) {
return list.get(0);
}
else if (size > 1) {
throw new InvalidResultException("Too many rows selected : " + size);
}
return null;
}
@Override
public String toString() {
return configuration.toString();

View File

@ -35,32 +35,163 @@
*/
package org.jooq.impl;
import static org.jooq.impl.Factory.row;
import static org.jooq.impl.Utils.filterOne;
import static org.jooq.impl.Utils.first;
import static org.jooq.impl.Utils.list;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jooq.AttachableInternal;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.RowN;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.exception.DetachedException;
/**
* @author Lukas Eder
*/
class ReferenceImpl<R extends Record, U extends Record> extends AbstractKey<R> implements ForeignKey<R, U> {
class ReferenceImpl<R extends Record, O extends Record> extends AbstractKey<R> implements ForeignKey<R, O> {
/**
* Generated UID
*/
private static final long serialVersionUID = 3636724364192618701L;
private final UniqueKey<U> key;
private final UniqueKey<O> key;
ReferenceImpl(UniqueKey<U> key, Table<R> table, TableField<R, ?>... fields) {
ReferenceImpl(UniqueKey<O> key, Table<R> table, TableField<R, ?>... fields) {
super(table, fields);
this.key = key;
}
@Override
public final UniqueKey<U> getKey() {
public final UniqueKey<O> getKey() {
return key;
}
@SuppressWarnings("unchecked")
@Override
public final O fetchParent(R record) {
return filterOne(fetchParents(record));
}
@Override
public final Result<O> fetchParents(R... records) {
return fetchParents(list(records));
}
@SuppressWarnings("unchecked")
@Override
public final Result<R> fetchChildren(O record) {
return fetchChildren(list(record));
}
@Override
public final Result<R> fetchChildren(O... records) {
return fetchChildren(list(records));
}
@Override
public final Result<O> fetchParents(Collection<? extends R> records) {
if (records == null || records.size() == 0) {
return new ResultImpl<O>(new DefaultConfiguration(), new FieldList(key.getFields()));
}
else {
return fetch(records, key.getTable(), key.getFieldsArray(), getFieldsArray());
}
}
@Override
public final Result<R> fetchChildren(Collection<? extends O> records) {
if (records == null || records.size() == 0) {
return new ResultImpl<R>(new DefaultConfiguration(), new FieldList(getFields()));
}
else {
return fetch(records, getTable(), getFieldsArray(), key.getFieldsArray());
}
}
/**
* Do the actual fetching
*/
@SuppressWarnings("unchecked")
private static <R1 extends Record, R2 extends Record> Result<R1> fetch(
Collection<? extends R2> records,
Table<R1> table,
TableField<R1, ?>[] fields1,
TableField<R2, ?>[] fields2) {
// Use regular predicates
if (fields1.length == 1) {
return extractExecutor(records)
.selectFrom(table)
.where(((Field<Object>) fields1[0]).in(extractValues(records, fields2[0])))
.fetch();
}
// Use row value expressions
else {
return extractExecutor(records)
.selectFrom(table)
.where(row(fields1).in(extractRows(records, fields2)))
.fetch();
}
}
/**
* Extract a list of values from a set of records given some fields
*/
private static <R extends Record> List<Object> extractValues(Collection<? extends R> records, TableField<R, ?> field2) {
List<Object> result = new ArrayList<Object>();
for (R record : records) {
result.add(record.getValue(field2));
}
return result;
}
/**
* Extract a list of row value expressions from a set of records given some fields
*/
private static <R extends Record> List<RowN> extractRows(Collection<? extends R> records, TableField<R, ?>[] fields) {
List<RowN> rows = new ArrayList<RowN>();
for (R record : records) {
Object[] values = new Object[fields.length];
for (int i = 0; i < fields.length; i++) {
values[i] = record.getValue(fields[i]);
}
rows.add(row(values));
}
return rows;
}
/**
* Extract a configuration from the first record of a collection of records
*/
private static <R extends Record> Executor extractExecutor(Collection<? extends R> records)
throws DetachedException {
R first = first(records);
if (first instanceof AttachableInternal) {
return new Executor(((AttachableInternal) first).getConfiguration());
}
else {
throw new DetachedException("Supply at least one attachable record");
}
}
}

View File

@ -35,8 +35,10 @@
*/
package org.jooq.impl;
import org.jooq.ForeignKey;
import org.jooq.Table;
import org.jooq.TableRecord;
import org.jooq.UpdatableRecord;
/**
* A record implementation for a record originating from a single table
@ -71,4 +73,10 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractRecord im
public final R original() {
return (R) super.original();
}
@SuppressWarnings("unchecked")
@Override
public final <O extends UpdatableRecord<O>> O fetchParent(ForeignKey<R, O> key) {
return key.fetchParent((R) this);
}
}

View File

@ -47,14 +47,17 @@ import java.util.List;
import org.jooq.Configuration;
import org.jooq.DeleteQuery;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.InsertQuery;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.SelectQuery;
import org.jooq.SimpleSelectQuery;
import org.jooq.StoreQuery;
import org.jooq.TableField;
import org.jooq.TableRecord;
import org.jooq.UniqueKey;
import org.jooq.UpdatableRecord;
import org.jooq.UpdatableTable;
@ -93,6 +96,17 @@ public class UpdatableRecordImpl<R extends UpdatableRecord<R>> extends TableReco
return result;
}
@Override
public final <O extends TableRecord<O>> O fetchChild(ForeignKey<O, R> key) {
return Utils.filterOne(fetchChildren(key));
}
@SuppressWarnings("unchecked")
@Override
public final <O extends TableRecord<O>> Result<O> fetchChildren(ForeignKey<O, R> key) {
return key.fetchChildren((R) this);
}
@Override
public final UpdatableTable<R> getTable() {
return (UpdatableTable<R>) super.getTable();

View File

@ -70,6 +70,7 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
@ -101,6 +102,7 @@ import org.jooq.UDTRecord;
import org.jooq.UpdatableRecord;
import org.jooq.conf.Settings;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.InvalidResultException;
import org.jooq.tools.Convert;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.LoggerListener;
@ -158,18 +160,6 @@ final class Utils {
*/
private static final Pattern JDBC_ESCAPE_PATTERN = Pattern.compile("\\{(fn|d|t|ts)\\b.*");
// ------------------------------------------------------------------------
// XXX: General utility methods
// ------------------------------------------------------------------------
/**
* Use this rather than {@link Arrays#asList(Object...)} for
* <code>null</code>-safety
*/
static final <T> List<T> list(T... array) {
return array == null ? Collections.<T>emptyList() : Arrays.asList(array);
}
// ------------------------------------------------------------------------
// XXX: Record constructors and related methods
// ------------------------------------------------------------------------
@ -388,6 +378,56 @@ final class Utils {
// XXX: General utility methods
// ------------------------------------------------------------------------
/**
* Use this rather than {@link Arrays#asList(Object...)} for
* <code>null</code>-safety
*/
static final <T> List<T> list(T... array) {
return array == null ? Collections.<T>emptyList() : Arrays.asList(array);
}
/**
* Extract the first item from an iterable or <code>null</code>, if there is
* no such item, or if iterable itself is <code>null</code>
*/
static final <T> T first(Iterable<? extends T> iterable) {
if (iterable == null) {
return null;
}
else {
Iterator<? extends T> iterator = iterable.iterator();
if (iterator.hasNext()) {
return iterator.next();
}
else {
return null;
}
}
}
/**
* Get the only element from a list or <code>null</code>, or throw an
* exception
*
* @param list The list
* @return The only element from the list or <code>null</code>
* @throws InvalidResultException Thrown if the list contains more than one
* element
*/
static <R extends Record> R filterOne(List<R> list) throws InvalidResultException {
int size = list.size();
if (size == 1) {
return list.get(0);
}
else if (size > 1) {
throw new InvalidResultException("Too many rows selected : " + size);
}
return null;
}
/**
* Render and bind a list of {@link QueryPart} to plain SQL
* <p>