[#1522] fetch().into(Table) doesn't initialise records correctly, such

that subsequent calls to store() will execute an INSERT, rather than an
UPDATE
This commit is contained in:
Lukas Eder 2012-07-06 13:27:25 +02:00
parent 7dc81a977c
commit 1700d832b7
6 changed files with 100 additions and 8 deletions

View File

@ -139,9 +139,11 @@ public abstract class BaseTest<
protected static final List<String> BOOK_TITLES = Arrays.asList("1984", "Animal Farm", "O Alquimista", "Brida");
protected static final List<String> BOOK_FIRST_NAMES = Arrays.asList("George", "George", "Paulo", "Paulo");
protected static final List<String> BOOK_LAST_NAMES = Arrays.asList("Orwell", "Orwell", "Coelho", "Coelho");
protected static final List<Object> BOOK_NULLS = Arrays.asList(null, null, null, null);
protected static final List<Integer> AUTHOR_IDS = Arrays.asList(1, 2);
protected static final List<String> AUTHOR_FIRST_NAMES = Arrays.asList("George", "Paulo");
protected static final List<String> AUTHOR_LAST_NAMES = Arrays.asList("Orwell", "Coelho");
protected static final List<Object> AUTHOR_NULLS = Arrays.asList(null, null);
protected static final JooqLogger log = JooqLogger.getLogger(jOOQAbstractTest.class);

View File

@ -819,6 +819,69 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
catch (MappingException expected) {}
}
@Test
public void testFetchIntoTable() throws Exception {
jOOQAbstractTest.reset = false;
// JOIN two tables into a generated UpdatableRecord
Result<B> result1 =
create().select(
TBook_ID(),
TBook_TITLE(),
TBook_AUTHOR_ID(),
TAuthor_FIRST_NAME(),
TAuthor_LAST_NAME())
.from(TBook())
.join(TAuthor())
.on(TBook_AUTHOR_ID().equal(TAuthor_ID()))
.orderBy(TBook_ID())
.fetch()
.into(TBook());
// Assure that only book-related fields are actually contained in Result
assertEquals(4, result1.size());
assertEquals(BOOK_IDS, result1.getValues(TBook_ID()));
assertEquals(BOOK_TITLES, result1.getValues(TBook_TITLE()));
assertEquals(BOOK_AUTHOR_IDS, result1.getValues(TBook_AUTHOR_ID()));
assertEquals(BOOK_NULLS, result1.getValues(TBook_PUBLISHED_IN()));
assertNull(result1.getField(TAuthor_FIRST_NAME()));
assertNull(result1.getField(TAuthor_LAST_NAME()));
// Ensure that books can be updated using store()
result1.get(0).setValue(TBook_TITLE(), "Changed");
assertEquals(1, result1.get(0).store());
Result<B> books1 = create().selectFrom(TBook()).orderBy(TBook_ID()).fetch();
assertEquals(4, books1.size());
assertEquals(BOOK_IDS, books1.getValues(TBook_ID()));
assertEquals(1, (int) books1.getValue(0, TBook_ID()));
assertEquals(1, (int) books1.getValue(0, TBook_AUTHOR_ID()));
assertEquals("Changed", books1.getValue(0, TBook_TITLE()));
// Without any fetched primary keys, the resulting records should be
// inserted using store()
B book =
create().select(
TBook_TITLE(),
TBook_AUTHOR_ID(),
TBook_PUBLISHED_IN(),
TBook_LANGUAGE_ID())
.from(TBook())
.where(TBook_ID().equal(2))
.fetchOne()
.into(TBook());
assertNotNull(book);
assertEquals("Animal Farm", book.getValue(TBook_TITLE()));
assertNull(book.getValue(TBook_ID()));
book.setValue(TBook_ID(), 5);
assertEquals(1, book.store());
Result<B> books2 = create().selectFrom(TBook()).orderBy(TBook_ID()).fetch();
assertEquals(5, books2.size());
assertEquals("Animal Farm", books2.getValue(4, TBook_TITLE()));
}
@Test
public void testFetchIntoCustomTable() throws Exception {

View File

@ -1015,6 +1015,11 @@ public abstract class jOOQAbstractTest<
new FetchTests(this).testReflectionWithImmutables();
}
@Test
public void testFetchIntoTable() throws Exception {
new FetchTests(this).testFetchIntoTable();
}
@Test
public void testFetchIntoCustomTable() throws Exception {
new FetchTests(this).testFetchIntoCustomTable();

View File

@ -212,6 +212,15 @@ abstract class AbstractRecord extends AbstractStore<Object> implements Record {
return null;
}
/**
* Reset all value flags' changed status
*/
final void setAllChanged(boolean changed) {
for (Value<?> value : getValues()) {
value.setChanged(changed);
}
}
@Override
public String toString() {
return getClass().getSimpleName() + " [values=" + Arrays.asList(getValues()) + "]";
@ -713,6 +722,25 @@ abstract class AbstractRecord extends AbstractStore<Object> implements Record {
}
}
// [#1522] If the primary key has been fully fetched, then changed
// flags should all be reset in order for the returned record to be
// updatable using store()
if (result instanceof AbstractRecord) {
UniqueKey<?> key = ((AbstractRecord) result).getMainKey();
if (key != null) {
boolean isKeySet = true;
for (Field<?> field : key.getFields()) {
isKeySet &= (getField(field) != null);
}
if (isKeySet) {
((AbstractRecord) result).setAllChanged(false);
}
}
}
return result;
}

View File

@ -203,8 +203,8 @@ class BatchStore implements Batch {
private void setAllUnchanged() {
for (UpdatableRecord<?> record : records) {
if (record instanceof TableRecordImpl) {
((TableRecordImpl<?>) record).setAllChanged(false);
if (record instanceof AbstractRecord) {
((AbstractRecord) record).setAllChanged(false);
}
}
}

View File

@ -110,12 +110,6 @@ public class TableRecordImpl<R extends TableRecord<R>> extends TypeRecord<Table<
return result;
}
void setAllChanged(boolean changed) {
for (Value<?> value : getValues()) {
value.setChanged(changed);
}
}
@SuppressWarnings("unchecked")
private final int storeInsert() {
InsertQuery<R> insert = create().insertQuery(getTable());