package com.j256.ormlite.dao;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;

import org.junit.Test;

import com.j256.ormlite.BaseJdbcTest;
import com.j256.ormlite.dao.Dao.CreateOrUpdateStatus;
import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.DatabaseFieldConfig;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.misc.BaseDaoEnabled;
import com.j256.ormlite.stmt.DeleteBuilder;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.SelectArg;
import com.j256.ormlite.stmt.UpdateBuilder;
import com.j256.ormlite.stmt.Where;
import com.j256.ormlite.support.DatabaseConnection;
import com.j256.ormlite.table.DatabaseTable;
import com.j256.ormlite.table.DatabaseTableConfig;
import com.j256.ormlite.table.TableUtils;

public class JdbcBaseDaoImplTest extends BaseJdbcTest {

	private static final boolean CLOSE_IS_NOOP = false;
	private static final boolean DELETE_ROWS_NO_WHERE_RETURNS_ZERO = false;
	private static final boolean AUTO_COMMIT_SUPPORTED = true;

	/* ======================================================================================== */

	private final static String DEFAULT_VALUE_STRING = "1314199";
	private final static int DEFAULT_VALUE = Integer.parseInt(DEFAULT_VALUE_STRING);
	private final static int ALL_TYPES_STRING_WIDTH = 4;
	protected final static String FOO_TABLE_NAME = "footable";
	private final static String ENUM_TABLE_NAME = "enumtable";

	private final static String NULL_BOOLEAN_TABLE_NAME = "nullbooltable";
	private final static String NULL_INT_TABLE_NAME = "nullinttable";

	private final static String DEFAULT_BOOLEAN_VALUE = "true";
	private final static String DEFAULT_STRING_VALUE = "foo";
	// this can't have non-zero milliseconds
	private final static String DEFAULT_DATE_VALUE = "2010-07-16 01:31:17.000000";
	private final static String DEFAULT_DATE_LONG_VALUE = "1282768620000";
	private final static String DEFAULT_DATE_STRING_FORMAT = "MM/dd/yyyy HH-mm-ss-SSSSSS";
	private final static String DEFAULT_DATE_STRING_VALUE = "07/16/2010 01-31-17-000000";
	private final static String DEFAULT_BYTE_VALUE = "1";
	private final static String DEFAULT_SHORT_VALUE = "2";
	private final static String DEFAULT_INT_VALUE = "3";
	private final static String DEFAULT_LONG_VALUE = "4";
	private final static String DEFAULT_FLOAT_VALUE = "5";
	private final static String DEFAULT_DOUBLE_VALUE = "6";
	private final static String DEFAULT_ENUM_VALUE = "FIRST";
	private final static String DEFAULT_ENUM_NUMBER_VALUE = "1";

	@Test
	public void testCreateDaoStatic() throws Exception {
		if (connectionSource == null) {
			return;
		}
		createTable(Foo.class, true);
		Dao<Foo, Integer> fooDao = DaoManager.createDao(connectionSource, Foo.class);
		String stuff = "stuff";
		Foo foo = new Foo();
		foo.stuff = stuff;
		assertEquals(1, fooDao.create(foo));

		// now we query for foo from the database to make sure it was persisted right
		Foo foo2 = fooDao.queryForId(foo.id);
		assertNotNull(foo2);
		assertEquals(foo.id, foo2.id);
		assertEquals(stuff, foo2.stuff);
	}

	@Test
	public void testCreateUpdateDelete() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		String s1 = "stuff";
		Foo foo1 = new Foo();
		foo1.stuff = s1;
		assertEquals(0, foo1.id);

		// persist foo to db through the dao and sends the id on foo because it was auto-generated by the db
		assertEquals(1, fooDao.create(foo1));
		assertTrue(foo1.id != 0);
		assertEquals(s1, foo1.stuff);

		// now we query for foo from the database to make sure it was persisted right
		Foo foo2 = fooDao.queryForId(foo1.id);
		assertNotNull(foo2);
		assertEquals(foo1.id, foo2.id);
		assertEquals(s1, foo2.stuff);

		String s2 = "stuff2";
		foo2.stuff = s2;

		// now we update 1 row in a the database after changing foo
		assertEquals(1, fooDao.update(foo2));

		// now we get it from the db again to make sure it was updated correctly
		Foo foo3 = fooDao.queryForId(foo1.id);
		assertEquals(s2, foo3.stuff);
		assertEquals(1, fooDao.delete(foo2));

		assertNull(fooDao.queryForId(foo1.id));
	}

	@Test
	public void testDoubleCreate() throws Exception {
		Dao<DoubleCreate, Object> doubleDao = createDao(DoubleCreate.class, true);
		int id = 313413123;
		DoubleCreate foo = new DoubleCreate();
		foo.id = id;
		assertEquals(1, doubleDao.create(foo));
		try {
			doubleDao.create(foo);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testIterateRemove() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		List<Foo> acctList = fooDao.queryForAll();
		int initialSize = acctList.size();

		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		Foo foo2 = new Foo();
		foo2.stuff = "s2";
		Foo foo3 = new Foo();
		foo3.stuff = "s3";
		fooDao.create(foo1);
		fooDao.create(foo2);
		fooDao.create(foo3);

		assertTrue(foo1.id != foo2.id);
		assertTrue(foo1.id != foo3.id);
		assertTrue(foo2.id != foo3.id);

		assertEquals(foo1, fooDao.queryForId(foo1.id));
		assertEquals(foo2, fooDao.queryForId(foo2.id));
		assertEquals(foo3, fooDao.queryForId(foo3.id));

		acctList = fooDao.queryForAll();
		assertEquals(initialSize + 3, acctList.size());
		assertEquals(foo1, acctList.get(acctList.size() - 3));
		assertEquals(foo2, acctList.get(acctList.size() - 2));
		assertEquals(foo3, acctList.get(acctList.size() - 1));
		int acctC = 0;
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			while (iterator.hasNext()) {
				Foo foo = iterator.next();
				if (acctC == acctList.size() - 3) {
					assertEquals(foo1, foo);
				} else if (acctC == acctList.size() - 2) {
					iterator.remove();
					assertEquals(foo2, foo);
				} else if (acctC == acctList.size() - 1) {
					assertEquals(foo3, foo);
				}
				acctC++;
			}
			assertEquals(initialSize + 3, acctC);
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testGeneratedField() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		assertEquals(0, foo1.id);
		assertEquals(1, fooDao.create(foo1));
		assertTrue(foo1.id != 0);
	}

	@Test
	public void testGeneratedIdNotNullField() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		assertEquals(0, foo1.id);
		assertEquals(1, fooDao.create(foo1));
		assertTrue(foo1.id != 0);
	}

	@Test
	public void testObjectToString() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		String stuff = "foo123231";
		Foo foo1 = new Foo();
		foo1.stuff = stuff;
		String objStr = fooDao.objectToString(foo1);
		assertTrue(objStr.contains(Integer.toString(foo1.id)));
		assertTrue(objStr.contains(stuff));
	}

	@Test
	public void testCreateNull() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		assertEquals(0, fooDao.create((Foo) null));
	}

	@Test
	public void testUpdateNull() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		assertEquals(0, fooDao.update((Foo) null));
	}

	@Test
	public void testUpdateIdNull() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		assertEquals(0, fooDao.updateId(null, null));
	}

	@Test
	public void testDeleteNull() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		assertEquals(0, fooDao.delete((Foo) null));
	}

	@Test
	public void testCloseInIterator() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		fooDao.create(foo1);
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			while (iterator.hasNext()) {
				iterator.next();
				closeConnectionSource();
			}
			if (!CLOSE_IS_NOOP) {
				fail("expected exception");
			}
		} catch (IllegalStateException e) {
			// expected
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testCloseIteratorBeforeNext() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		fooDao.create(foo1);
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			while (iterator.hasNext()) {
				closeConnectionSource();
				iterator.next();
			}
			if (!CLOSE_IS_NOOP) {
				fail("expected exception");
			}
		} catch (IllegalStateException e) {
			// expected
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testCloseIteratorBeforeRemove() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		fooDao.create(foo1);
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			while (iterator.hasNext()) {
				iterator.next();
				closeConnectionSource();
				iterator.remove();
			}
			if (!CLOSE_IS_NOOP) {
				fail("expected exception");
			}
		} catch (Exception e) {
			// expected
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testNoNextBeforeRemove() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.stuff = "s1";
		fooDao.create(foo1);
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			iterator.remove();
			fail("expected exception");
		} catch (IllegalStateException e) {
			// expected
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testIteratePageSize() throws Exception {
		final Dao<Foo, Integer> fooDao = createDao(Foo.class, true);

		int numItems = 1000;
		fooDao.callBatchTasks(new InsertCallable(numItems, fooDao));

		// now delete them with the iterator to test page-size
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			while (iterator.hasNext()) {
				iterator.next();
				iterator.remove();
			}
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testIteratorPreparedQuery() throws Exception {
		final Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		// do an insert of bunch of items
		final int numItems = 100;
		fooDao.callBatchTasks(new InsertCallable(numItems, fooDao));

		int lastX = 10;
		PreparedQuery<Foo> preparedQuery =
				fooDao.queryBuilder().where().ge(Foo.VAL_FIELD_NAME, numItems - lastX).prepare();

		// now delete them with the iterator to test page-size
		CloseableIterator<Foo> iterator = fooDao.iterator(preparedQuery);
		try {
			int itemC = 0;
			while (iterator.hasNext()) {
				iterator.next();
				itemC++;
			}
			assertEquals(lastX, itemC);
		} finally {
			iterator.close();
		}
	}

	private static class InsertCallable implements Callable<Void> {
		private int numItems;
		private Dao<Foo, Integer> fooDao;

		public InsertCallable(int numItems, Dao<Foo, Integer> fooDao) {
			this.numItems = numItems;
			this.fooDao = fooDao;
		}

		@Override
		public Void call() throws Exception {
			for (int i = 0; i < numItems; i++) {
				Foo foo = new Foo();
				foo.val = i;
				assertEquals(1, fooDao.create(foo));
			}
			return null;
		}
	}

	@Test
	public void testDeleteObjects() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		List<Foo> fooList = new ArrayList<Foo>();
		for (int i = 0; i < 100; i++) {
			Foo foo = new Foo();
			foo.stuff = Integer.toString(i);
			assertEquals(1, fooDao.create(foo));
			fooList.add(foo);
		}

		assertEquals(fooList.size(), fooDao.delete(fooList));
		assertEquals(0, fooDao.queryForAll().size());
	}

	@Test
	public void testDeleteObjectsNone() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		List<Foo> fooList = new ArrayList<Foo>();
		assertEquals(fooList.size(), fooDao.delete(fooList));
		assertEquals(0, fooDao.queryForAll().size());
	}

	@Test
	public void testDeleteIds() throws Exception {
		final Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		final List<Integer> fooIdList = new ArrayList<Integer>();
		fooDao.callBatchTasks(new Callable<Void>() {
			@Override
			public Void call() throws Exception {
				for (int i = 0; i < 100; i++) {
					Foo foo = new Foo();
					assertEquals(1, fooDao.create(foo));
					fooIdList.add(foo.id);
				}
				return null;
			}
		});

		assertEquals(fooIdList.size(), fooDao.deleteIds(fooIdList));
		assertEquals(0, fooDao.queryForAll().size());
	}

	@Test
	public void testDeleteIdsNone() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		List<Integer> fooIdList = new ArrayList<Integer>();
		assertEquals(fooIdList.size(), fooDao.deleteIds(fooIdList));
		assertEquals(0, fooDao.queryForAll().size());
	}

	@Test
	public void testDeletePreparedStmtIn() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		List<Integer> fooIdList = new ArrayList<Integer>();
		for (int i = 0; i < 100; i++) {
			Foo foo = new Foo();
			assertEquals(1, fooDao.create(foo));
			fooIdList.add(foo.id);
		}

		DeleteBuilder<Foo, Integer> stmtBuilder = fooDao.deleteBuilder();
		stmtBuilder.where().in(Foo.ID_FIELD_NAME, fooIdList);

		assertEquals(fooIdList.size(), fooDao.delete(stmtBuilder.prepare()));
		assertEquals(0, fooDao.queryForAll().size());
	}

	@Test
	public void testDeleteAllPreparedStmt() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		int fooN = 100;
		for (int i = 0; i < fooN; i++) {
			Foo foo = new Foo();
			assertEquals(1, fooDao.create(foo));
		}

		DeleteBuilder<Foo, Integer> stmtBuilder = fooDao.deleteBuilder();

		int deleted = fooDao.delete(stmtBuilder.prepare());
		if (DELETE_ROWS_NO_WHERE_RETURNS_ZERO) {
			assertEquals(0, deleted);
		} else {
			assertEquals(fooN, deleted);
		}
		assertEquals(0, fooDao.queryForAll().size());
	}

	@Test
	public void testHasNextAfterDone() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			while (iterator.hasNext()) {
			}
			assertFalse(iterator.hasNext());
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testNextWithoutHasNext() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		CloseableIterator<Foo> iterator = fooDao.iterator();
		try {
			iterator.next();
			fail("expected exception");
		} catch (Exception e) {
			// expected
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testRemoveAfterDone() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Iterator<Foo> iterator = fooDao.iterator();
		assertFalse(iterator.hasNext());
		try {
			iterator.remove();
			fail("expected exception");
		} catch (IllegalStateException e) {
			// expected
		}
	}

	@Test
	public void testIteratorNoResults() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Iterator<Foo> iterator = fooDao.iterator();
		assertFalse(iterator.hasNext());
	}

	@Test
	public void testCreateNoId() throws Exception {
		Dao<NoId, Object> whereDao = createDao(NoId.class, true);
		NoId noId = new NoId();
		assertEquals(0, whereDao.queryForAll().size());
		// this should work even though there is no id
		whereDao.create(noId);
		assertEquals(1, whereDao.queryForAll().size());
	}

	@Test
	public void testJustIdCreateQueryDelete() throws Exception {
		Dao<JustId, Object> justIdDao = createDao(JustId.class, true);
		String id = "just-id";
		JustId justId = new JustId();
		justId.id = id;
		assertEquals(1, justIdDao.create(justId));
		JustId justId2 = justIdDao.queryForId(id);
		assertNotNull(justId2);
		assertEquals(id, justId2.id);
		assertEquals(1, justIdDao.delete(justId));
		assertNull(justIdDao.queryForId(id));
		// update should fail during construction
	}

	@Test
	public void testJustIdUpdateId() throws Exception {
		Dao<JustId, Object> justIdDao = createDao(JustId.class, true);
		String id = "just-id-update-1";
		JustId justId = new JustId();
		justId.id = id;
		assertEquals(1, justIdDao.create(justId));
		JustId justId2 = justIdDao.queryForId(id);
		assertNotNull(justId2);
		assertEquals(id, justId2.id);
		String id2 = "just-id-update-2";
		// change the id
		assertEquals(1, justIdDao.updateId(justId2, id2));
		assertNull(justIdDao.queryForId(id));
		JustId justId3 = justIdDao.queryForId(id2);
		assertNotNull(justId3);
		assertEquals(id2, justId3.id);
		assertEquals(1, justIdDao.delete(justId3));
		assertNull(justIdDao.queryForId(id));
		assertNull(justIdDao.queryForId(id2));
	}

	@Test
	public void testJustIdRefresh() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		String stuff1 = "just-id-refresh-1";
		Foo foo1 = new Foo();
		foo1.stuff = stuff1;
		assertEquals(1, fooDao.create(foo1));
		int id = foo1.id;
		Foo foo2 = fooDao.queryForId(id);
		assertNotNull(foo2);
		assertEquals(id, foo2.id);
		assertEquals(stuff1, foo2.stuff);
		String stuff2 = "just-id-refresh-2";
		foo2.stuff = stuff2;

		// change the id in the db
		assertEquals(1, fooDao.update(foo2));
		Foo foo3 = fooDao.queryForId(id);
		assertNotNull(foo3);
		assertEquals(id, foo3.id);
		assertEquals(stuff2, foo3.stuff);

		assertEquals(stuff1, foo1.stuff);
		assertEquals(1, fooDao.refresh(foo1));
		assertEquals(stuff2, foo1.stuff);
	}

	@Test
	public void testSpringConstruction() throws Exception {
		if (connectionSource == null) {
			return;
		}
		createTable(Foo.class, true);
		BaseDaoImpl<Foo, Integer> fooDao = new BaseDaoImpl<Foo, Integer>(Foo.class) {
		};
		try {
			fooDao.create(new Foo());
			fail("expected exception");
		} catch (IllegalStateException e) {
			// expected
		}
		fooDao.setConnectionSource(connectionSource);
		fooDao.initialize();
		Foo foo = new Foo();
		assertEquals(1, fooDao.create(foo));
		assertEquals(1, fooDao.delete(foo));
	}

	@Test
	public void testForeignCreation() throws Exception {
		Dao<ForeignWrapper, Integer> wrapperDao = createDao(ForeignWrapper.class, true);
		Dao<AllTypes, Integer> foreignDao = createDao(AllTypes.class, true);

		AllTypes foreign = new AllTypes();
		String stuff1 = "stuff1";
		foreign.stringField = stuff1;
		// this sets the foreign id
		assertEquals(1, foreignDao.create(foreign));

		ForeignWrapper wrapper = new ForeignWrapper();
		wrapper.foreign = foreign;
		// this sets the wrapper id
		assertEquals(1, wrapperDao.create(wrapper));

		ForeignWrapper wrapper2 = wrapperDao.queryForId(wrapper.id);
		assertEquals(wrapper.id, wrapper2.id);
		assertEquals(wrapper.foreign.id, wrapper2.foreign.id);
		assertTrue(wrapperDao.objectsEqual(wrapper, wrapper2));
		// this won't be true because wrapper2.foreign is a shell
		assertFalse(foreignDao.objectsEqual(foreign, wrapper2.foreign));
		assertNull(wrapper2.foreign.stringField);
		assertEquals(1, foreignDao.refresh(wrapper2.foreign));
		// now it should be true
		assertTrue(foreignDao.objectsEqual(foreign, wrapper2.foreign));
		assertEquals(stuff1, wrapper2.foreign.stringField);

		// create a new foreign
		foreign = new AllTypes();
		String stuff2 = "stuff2";
		foreign.stringField = stuff2;
		// this sets the foreign id
		assertEquals(1, foreignDao.create(foreign));

		// change the foreign object
		wrapper.foreign = foreign;
		// update it
		assertEquals(1, wrapperDao.update(wrapper));

		wrapper2 = wrapperDao.queryForId(wrapper.id);
		assertEquals(wrapper.id, wrapper2.id);
		assertEquals(wrapper.foreign.id, wrapper2.foreign.id);
		assertTrue(wrapperDao.objectsEqual(wrapper, wrapper2));
		// this won't be true because wrapper2.foreign is a shell
		assertFalse(foreignDao.objectsEqual(foreign, wrapper2.foreign));
		assertNull(wrapper2.foreign.stringField);
		assertEquals(1, foreignDao.refresh(wrapper2.foreign));
		// now it should be true
		assertTrue(foreignDao.objectsEqual(foreign, wrapper2.foreign));
		assertEquals(stuff2, wrapper2.foreign.stringField);
	}

	@Test
	public void testForeignRefreshNoChange() throws Exception {
		Dao<ForeignWrapper, Integer> wrapperDao = createDao(ForeignWrapper.class, true);
		Dao<AllTypes, Integer> foreignDao = createDao(AllTypes.class, true);

		AllTypes foreign = new AllTypes();
		String stuff1 = "stuff1";
		foreign.stringField = stuff1;
		// this sets the foreign id
		assertEquals(1, foreignDao.create(foreign));

		ForeignWrapper wrapper = new ForeignWrapper();
		wrapper.foreign = foreign;
		// this sets the wrapper id
		assertEquals(1, wrapperDao.create(wrapper));

		ForeignWrapper wrapper2 = wrapperDao.queryForId(wrapper.id);
		assertEquals(1, foreignDao.refresh(wrapper2.foreign));
		AllTypes foreign2 = wrapper2.foreign;
		assertEquals(stuff1, foreign2.stringField);

		assertEquals(1, wrapperDao.refresh(wrapper2));
		assertSame(foreign2, wrapper2.foreign);
		assertEquals(stuff1, wrapper2.foreign.stringField);

		// now, in the background, we change the foreign
		ForeignWrapper wrapper3 = wrapperDao.queryForId(wrapper.id);
		AllTypes foreign3 = new AllTypes();
		String stuff3 = "stuff3";
		foreign3.stringField = stuff3;
		assertEquals(1, foreignDao.create(foreign3));
		wrapper3.foreign = foreign3;
		assertEquals(1, wrapperDao.update(wrapper3));

		assertEquals(1, wrapperDao.refresh(wrapper2));
		// now all of a sudden wrapper2 should not have the same foreign field
		assertNotSame(foreign2, wrapper2.foreign);
		assertNull(wrapper2.foreign.stringField);
	}

	@Test
	public void testMultipleForeignWrapper() throws Exception {
		Dao<MultipleForeignWrapper, Integer> multipleWrapperDao = createDao(MultipleForeignWrapper.class, true);
		Dao<ForeignWrapper, Integer> wrapperDao = createDao(ForeignWrapper.class, true);
		Dao<AllTypes, Integer> foreignDao = createDao(AllTypes.class, true);

		AllTypes foreign = new AllTypes();
		String stuff1 = "stuff1";
		foreign.stringField = stuff1;
		// this sets the foreign id
		assertEquals(1, foreignDao.create(foreign));

		ForeignWrapper wrapper = new ForeignWrapper();
		wrapper.foreign = foreign;
		// this sets the wrapper id
		assertEquals(1, wrapperDao.create(wrapper));

		MultipleForeignWrapper multiWrapper = new MultipleForeignWrapper();
		multiWrapper.foreign = foreign;
		multiWrapper.foreignWrapper = wrapper;
		// this sets the wrapper id
		assertEquals(1, multipleWrapperDao.create(multiWrapper));

		MultipleForeignWrapper multiWrapper2 = multipleWrapperDao.queryForId(multiWrapper.id);
		assertEquals(foreign.id, multiWrapper2.foreign.id);
		assertNull(multiWrapper2.foreign.stringField);
		assertEquals(wrapper.id, multiWrapper2.foreignWrapper.id);
		assertNull(multiWrapper2.foreignWrapper.foreign);

		assertEquals(1, foreignDao.refresh(multiWrapper2.foreign));
		assertEquals(stuff1, multiWrapper2.foreign.stringField);
		assertNull(multiWrapper2.foreignWrapper.foreign);

		assertEquals(1, wrapperDao.refresh(multiWrapper2.foreignWrapper));
		assertEquals(foreign.id, multiWrapper2.foreignWrapper.foreign.id);
		assertNull(multiWrapper2.foreignWrapper.foreign.stringField);

		assertEquals(1, foreignDao.refresh(multiWrapper2.foreignWrapper.foreign));
		assertEquals(stuff1, multiWrapper2.foreignWrapper.foreign.stringField);
	}

	@Test
	public void testRefreshNull() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		// this should be a noop
		assertEquals(0, fooDao.refresh(null));
	}

	@Test
	public void testGetSet() throws Exception {
		Dao<GetSet, Integer> getSetDao = createDao(GetSet.class, true);
		GetSet getSet = new GetSet();
		String stuff = "ewfewfewfew343u42f";
		getSet.setStuff(stuff);
		assertEquals(1, getSetDao.create(getSet));
		GetSet getSet2 = getSetDao.queryForId(getSet.id);
		assertEquals(stuff, getSet2.stuff);
	}

	@Test
	public void testQueryForFirst() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);

		String stuff = "ewf4334234u42f";

		QueryBuilder<Foo, Integer> qb = fooDao.queryBuilder();
		qb.where().eq(Foo.STUFF_FIELD_NAME, stuff);

		assertNull(fooDao.queryForFirst(qb.prepare()));

		Foo foo1 = new Foo();
		foo1.stuff = stuff;
		assertEquals(1, fooDao.create(foo1));

		// should still get foo1
		Foo foo2 = fooDao.queryForFirst(qb.prepare());
		assertEquals(foo1.id, foo2.id);
		assertEquals(stuff, foo2.stuff);

		// create another with same stuff
		Foo foo3 = new Foo();
		String stuff2 = "ewf43342wefwffwefwe34u42f";
		foo3.stuff = stuff2;
		assertEquals(1, fooDao.create(foo3));

		foo2 = fooDao.queryForFirst(qb.prepare());
		assertEquals(foo1.id, foo2.id);
		assertEquals(stuff, foo2.stuff);
	}

	@Test
	public void testFieldConfig() throws Exception {
		List<DatabaseFieldConfig> fieldConfigs = new ArrayList<DatabaseFieldConfig>();
		fieldConfigs.add(new DatabaseFieldConfig("id", "id2", DataType.UNKNOWN, null, 0, false, false, true, null,
				false, null, false, null, false, null, false, null, null, false, -1, 0));
		fieldConfigs.add(new DatabaseFieldConfig("stuff", "stuffy", DataType.UNKNOWN, null, 0, false, false, false,
				null, false, null, false, null, false, null, false, null, null, false, -1, 0));
		DatabaseTableConfig<NoAnno> tableConfig = new DatabaseTableConfig<NoAnno>(NoAnno.class, "noanno", fieldConfigs);
		Dao<NoAnno, Integer> noAnnotaionDao = createDao(tableConfig, true);
		NoAnno noa = new NoAnno();
		String stuff = "qpoqwpjoqwp12";
		noa.stuff = stuff;
		assertEquals(1, noAnnotaionDao.create(noa));
		NoAnno noa2 = noAnnotaionDao.queryForId(noa.id);
		assertEquals(noa.id, noa2.id);
		assertEquals(stuff, noa2.stuff);
	}

	@Test
	public void testFieldConfigForeign() throws Exception {
		List<DatabaseFieldConfig> noAnnotationsFieldConfigs = new ArrayList<DatabaseFieldConfig>();
		DatabaseFieldConfig field1 = new DatabaseFieldConfig("id");
		field1.setColumnName("idthingie");
		field1.setGeneratedId(true);
		noAnnotationsFieldConfigs.add(field1);
		DatabaseFieldConfig field2 = new DatabaseFieldConfig("stuff");
		field2.setColumnName("stuffy");
		noAnnotationsFieldConfigs.add(field2);
		DatabaseTableConfig<NoAnno> noAnnotationsTableConfig =
				new DatabaseTableConfig<NoAnno>(databaseType, NoAnno.class, noAnnotationsFieldConfigs);
		Dao<NoAnno, Integer> noAnnotationDao = createDao(noAnnotationsTableConfig, true);
		NoAnno noa = new NoAnno();
		String stuff = "qpoqwpjoqwp12";
		noa.stuff = stuff;
		assertEquals(1, noAnnotationDao.create(noa));
		assertNotNull(noAnnotationDao.queryForId(noa.id));

		List<DatabaseFieldConfig> noAnnotationsForiegnFieldConfigs = new ArrayList<DatabaseFieldConfig>();
		DatabaseFieldConfig field3 = new DatabaseFieldConfig("id");
		field3.setColumnName("anotherid");
		field3.setGeneratedId(true);
		noAnnotationsForiegnFieldConfigs.add(field3);
		DatabaseFieldConfig field4 = new DatabaseFieldConfig("foreign");
		field4.setColumnName("foreignThingie");
		field4.setForeign(true);
		field4.setForeignTableConfig(noAnnotationsTableConfig);
		noAnnotationsForiegnFieldConfigs.add(field4);
		DatabaseTableConfig<NoAnnoFor> noAnnotationsForiegnTableConfig =
				new DatabaseTableConfig<NoAnnoFor>(databaseType, NoAnnoFor.class, noAnnotationsForiegnFieldConfigs);

		Dao<NoAnnoFor, Integer> noAnnotaionForeignDao = createDao(noAnnotationsForiegnTableConfig, true);
		NoAnnoFor noaf = new NoAnnoFor();
		noaf.foreign = noa;
		assertEquals(1, noAnnotaionForeignDao.create(noaf));

		NoAnnoFor noaf2 = noAnnotaionForeignDao.queryForId(noaf.id);
		assertNotNull(noaf2);
		assertEquals(noaf.id, noaf2.id);
		assertEquals(noa.id, noaf2.foreign.id);
		assertNull(noaf2.foreign.stuff);
		assertEquals(1, noAnnotationDao.refresh(noaf2.foreign));
		assertEquals(stuff, noaf2.foreign.stuff);
	}

	@Test
	public void testGeneratedIdNotNull() throws Exception {
		// we saw an error with the not null before the generated id stuff under hsqldb
		Dao<GeneratedIdNotNull, Integer> dao = createDao(GeneratedIdNotNull.class, true);
		assertEquals(1, dao.create(new GeneratedIdNotNull()));
	}

	@Test
	public void testBasicStuff() throws Exception {
		Dao<Basic, String> fooDao = createDao(Basic.class, true);

		String string = "s1";
		Basic foo1 = new Basic();
		foo1.id = string;
		assertEquals(1, fooDao.create(foo1));

		Basic foo2 = fooDao.queryForId(string);
		assertTrue(fooDao.objectsEqual(foo1, foo2));

		List<Basic> fooList = fooDao.queryForAll();
		assertEquals(1, fooList.size());
		assertTrue(fooDao.objectsEqual(foo1, fooList.get(0)));
		int i = 0;
		for (Basic foo3 : fooDao) {
			assertTrue(fooDao.objectsEqual(foo1, foo3));
			i++;
		}
		assertEquals(1, i);

		assertEquals(1, fooDao.delete(foo2));
		assertNull(fooDao.queryForId(string));
		fooList = fooDao.queryForAll();
		assertEquals(0, fooList.size());
		i = 0;
		for (Basic foo3 : fooDao) {
			assertTrue(fooDao.objectsEqual(foo1, foo3));
			i++;
		}
		assertEquals(0, i);
	}

	@Test
	public void testMultiplePrimaryKey() throws Exception {
		Dao<Basic, String> fooDao = createDao(Basic.class, true);
		Basic foo1 = new Basic();
		foo1.id = "dup";
		assertEquals(1, fooDao.create(foo1));
		try {
			fooDao.create(foo1);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testDefaultValue() throws Exception {
		Dao<DefaultValue, Object> defValDao = createDao(DefaultValue.class, true);
		DefaultValue defVal1 = new DefaultValue();
		assertEquals(1, defValDao.create(defVal1));
		List<DefaultValue> defValList = defValDao.queryForAll();
		assertEquals(1, defValList.size());
		DefaultValue defVal2 = defValList.get(0);
		assertEquals(DEFAULT_VALUE, (int) defVal2.intField);
	}

	@Test
	public void testNotNull() throws Exception {
		Dao<NotNull, Object> defValDao = createDao(NotNull.class, true);
		NotNull notNull = new NotNull();
		try {
			defValDao.create(notNull);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testNotNullOkay() throws Exception {
		Dao<NotNull, Object> defValDao = createDao(NotNull.class, true);
		NotNull notNull = new NotNull();
		notNull.notNull = "not null";
		assertEquals(1, defValDao.create(notNull));
	}

	@Test
	public void testGeneratedId() throws Exception {
		Dao<GeneratedId, Object> genIdDao = createDao(GeneratedId.class, true);
		GeneratedId genId = new GeneratedId();
		assertEquals(0, genId.id);
		assertEquals(1, genIdDao.create(genId));
		long id = genId.id;
		assertEquals(1, id);
		GeneratedId genId2 = genIdDao.queryForId(id);
		assertNotNull(genId2);
		assertEquals(id, genId2.id);

		genId = new GeneratedId();
		assertEquals(0, genId.id);
		assertEquals(1, genIdDao.create(genId));
		id = genId.id;
		assertEquals(2, id);
		genId2 = genIdDao.queryForId(id);
		assertNotNull(genId2);
		assertEquals(id, genId2.id);
	}

	@Test
	public void testBigDecimal() throws Exception {
		Dao<BigDecimalNumeric, Object> dao = createDao(BigDecimalNumeric.class, true);
		BigDecimalNumeric foo = new BigDecimalNumeric();
		String databaseTypeClassName = databaseType.getClass().getSimpleName();
		if (databaseTypeClassName.equals("DerbyEmbeddedDatabaseType")
				|| databaseTypeClassName.equals("MysqlDatabaseType")
				|| databaseTypeClassName.equals("SqlServerDatabaseType")
				|| databaseTypeClassName.equals("SqlServerJtdsDatabaseType")
				|| databaseTypeClassName.equals("SqliteAndroidDatabaseType")) {
			// some databases have miniscule default precision
			foo.bigDecimalNumeric = new BigDecimal("12");
		} else {
			// some databases have miniscule default precision
			foo.bigDecimalNumeric = new BigDecimal("12645.34324234");
		}
		assertEquals(1, dao.create(foo));

		List<BigDecimalNumeric> results = dao.queryForAll();
		assertNotNull(results);
		assertEquals(1, results.size());
		assertEquals(foo.id, results.get(0).id);
		assertEquals(foo.bigDecimalNumeric, results.get(0).bigDecimalNumeric);
	}

	@Test
	public void testAllTypes() throws Exception {
		Dao<AllTypes, Integer> allDao = createDao(AllTypes.class, true);
		AllTypes allTypes = new AllTypes();
		String stringVal = "some string";
		boolean boolVal = true;
		// we have to round this because the db may not be storing millis
		long millis = (System.currentTimeMillis() / 1000) * 1000;
		Date dateVal = new Date(millis);
		Date dateLongVal = new Date(millis);
		Date dateStringVal = new Date(millis);
		char charVal = 'w';
		byte byteVal = 117;
		short shortVal = 15217;
		int intVal = 1023213;
		long longVal = 1231231231231L;
		float floatVal = 123.13F;
		double doubleVal = 1413312.1231233;
		OurEnum enumVal = OurEnum.FIRST;
		UUID uuidVal = UUID.randomUUID();
		BigInteger bigIntegerVal = new BigInteger("13213123214432423423423423423423423423423423423423423");
		BigDecimal bigDecimalVal = new BigDecimal("1321312.1231231233214432423423423423423423423423423423423423423");
		// some databases have miniscule default precision
		BigDecimal bigDecimalNumericVal;
		String databaseTypeClassName = databaseType.getClass().getSimpleName();
		if (databaseTypeClassName.equals("DerbyEmbeddedDatabaseType")
				|| databaseTypeClassName.equals("MysqlDatabaseType")
				|| databaseTypeClassName.equals("SqlServerDatabaseType")
				|| databaseTypeClassName.equals("SqlServerJtdsDatabaseType")
				|| databaseTypeClassName.equals("SqliteAndroidDatabaseType")) {
			// some databases have miniscule default precision
			bigDecimalNumericVal = new BigDecimal("12");
		} else {
			// some databases have miniscule default precision
			bigDecimalNumericVal = new BigDecimal("12645.3432234");
		}
		allTypes.stringField = stringVal;
		allTypes.booleanField = boolVal;
		allTypes.dateField = dateVal;
		allTypes.dateLongField = dateLongVal;
		allTypes.dateStringField = dateStringVal;
		allTypes.charField = charVal;
		allTypes.byteField = byteVal;
		allTypes.shortField = shortVal;
		allTypes.intField = intVal;
		allTypes.longField = longVal;
		allTypes.floatField = floatVal;
		allTypes.doubleField = doubleVal;
		allTypes.enumField = enumVal;
		allTypes.enumStringField = enumVal;
		allTypes.enumIntegerField = enumVal;
		allTypes.uuid = uuidVal;
		allTypes.bigInteger = bigIntegerVal;
		allTypes.bigDecimal = bigDecimalVal;
		allTypes.bigDecimalNumeric = bigDecimalNumericVal;
		SerialData obj = new SerialData();
		String key = "key";
		String value = "value";
		obj.addEntry(key, value);
		allTypes.serialField = obj;
		assertEquals(1, allDao.create(allTypes));
		List<AllTypes> allTypesList = allDao.queryForAll();
		assertEquals(1, allTypesList.size());
		assertTrue(allDao.objectsEqual(allTypes, allTypesList.get(0)));
		assertEquals(value, allTypesList.get(0).serialField.map.get(key));
		assertEquals(1, allDao.refresh(allTypes));
		// queries on all fields
		QueryBuilder<AllTypes, Integer> qb = allDao.queryBuilder();
		checkQueryResult(allDao, qb, allTypes, AllTypes.STRING_FIELD_NAME, stringVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.BOOLEAN_FIELD_NAME, boolVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.DATE_FIELD_NAME, dateVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.DATE_LONG_FIELD_NAME, dateLongVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.DATE_STRING_FIELD_NAME, dateStringVal, true);
		if (!databaseType.getDatabaseName().equals("Derby")) {
			checkQueryResult(allDao, qb, allTypes, AllTypes.CHAR_FIELD_NAME, charVal, true);
		}
		checkQueryResult(allDao, qb, allTypes, AllTypes.BYTE_FIELD_NAME, byteVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.SHORT_FIELD_NAME, shortVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.INT_FIELD_NAME, intVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.LONG_FIELD_NAME, longVal, true);
		// float tested below
		checkQueryResult(allDao, qb, allTypes, AllTypes.DOUBLE_FIELD_NAME, doubleVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.ENUM_FIELD_NAME, enumVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.ENUM_STRING_FIELD_NAME, enumVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.ENUM_INTEGER_FIELD_NAME, enumVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.UUID_FIELD_NAME, uuidVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.BIG_INTEGER_FIELD_NAME, bigIntegerVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.BIG_DECIMAL_FIELD_NAME, bigDecimalVal, true);
		checkQueryResult(allDao, qb, allTypes, AllTypes.BIG_DECIMAL_NUMERIC_FIELD_NAME, bigDecimalNumericVal, true);
	}

	/**
	 * This is special because comparing floats may not work as expected.
	 */
	@Test
	public void testAllTypesFloat() throws Exception {
		Dao<AllTypes, Integer> allDao = createDao(AllTypes.class, true);
		AllTypes allTypes = new AllTypes();
		float floatVal = 123.13F;
		float floatLowVal = floatVal * 0.9F;
		float floatHighVal = floatVal * 1.1F;
		allTypes.floatField = floatVal;
		assertEquals(1, allDao.create(allTypes));
		List<AllTypes> allTypesList = allDao.queryForAll();
		assertEquals(1, allTypesList.size());
		assertTrue(allDao.objectsEqual(allTypes, allTypesList.get(0)));
		assertEquals(1, allDao.refresh(allTypes));
		// queries on all fields
		QueryBuilder<AllTypes, Integer> qb = allDao.queryBuilder();

		// float comparisons are not exactly right so we switch to a low -> high query instead
		if (!checkQueryResult(allDao, qb, allTypes, AllTypes.FLOAT_FIELD_NAME, floatVal, false)) {
			qb.where().gt(AllTypes.FLOAT_FIELD_NAME, floatLowVal).and().lt(AllTypes.FLOAT_FIELD_NAME, floatHighVal);
			List<AllTypes> results = allDao.query(qb.prepare());
			assertEquals(1, results.size());
			assertTrue(allDao.objectsEqual(allTypes, results.get(0)));
		}
	}

	@Test
	public void testAllTypesDefault() throws Exception {
		Dao<AllTypes, Integer> allDao = createDao(AllTypes.class, true);
		AllTypes allTypes = new AllTypes();
		assertEquals(1, allDao.create(allTypes));
		List<AllTypes> allTypesList = allDao.queryForAll();
		assertEquals(1, allTypesList.size());
		assertTrue(allDao.objectsEqual(allTypes, allTypesList.get(0)));
	}

	@Test
	public void testNumberTypes() throws Exception {
		Dao<NumberTypes, Integer> numberDao = createDao(NumberTypes.class, true);

		NumberTypes numberMins = new NumberTypes();
		numberMins.byteField = Byte.MIN_VALUE;
		numberMins.shortField = Short.MIN_VALUE;
		numberMins.intField = Integer.MIN_VALUE;
		numberMins.longField = Long.MIN_VALUE;
		numberMins.floatField = -1.0e+37F;
		numberMins.doubleField = -1.0e+307;
		assertEquals(1, numberDao.create(numberMins));

		NumberTypes numberMins2 = new NumberTypes();
		numberMins2.byteField = Byte.MIN_VALUE;
		numberMins2.shortField = Short.MIN_VALUE;
		numberMins2.intField = Integer.MIN_VALUE;
		numberMins2.longField = Long.MIN_VALUE;
		numberMins2.floatField = 1.0e-37F;
		// derby couldn't take 1.0e-307 for some reason
		numberMins2.doubleField = 1.0e-306;
		assertEquals(1, numberDao.create(numberMins2));

		NumberTypes numberMaxs = new NumberTypes();
		numberMaxs.byteField = Byte.MAX_VALUE;
		numberMaxs.shortField = Short.MAX_VALUE;
		numberMaxs.intField = Integer.MAX_VALUE;
		numberMaxs.longField = Long.MAX_VALUE;
		numberMaxs.floatField = 1.0e+37F;
		numberMaxs.doubleField = 1.0e+307;
		assertEquals(1, numberDao.create(numberMaxs));
		assertEquals(1, numberDao.refresh(numberMaxs));

		List<NumberTypes> allTypesList = numberDao.queryForAll();
		assertEquals(3, allTypesList.size());
		assertTrue(numberDao.objectsEqual(numberMins, allTypesList.get(0)));
		assertTrue(numberDao.objectsEqual(numberMins2, allTypesList.get(1)));
		assertTrue(numberDao.objectsEqual(numberMaxs, allTypesList.get(2)));
	}

	@Test
	public void testStringWidthTooLong() throws Exception {
		if (connectionSource == null) {
			return;
		}
		if (!connectionSource.getDatabaseType().isVarcharFieldWidthSupported()) {
			return;
		}
		Dao<StringWidth, Object> stringWidthDao = createDao(StringWidth.class, true);
		StringWidth stringWidth = new StringWidth();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < ALL_TYPES_STRING_WIDTH + 1; i++) {
			sb.append('c');
		}
		String string = sb.toString();
		assertTrue(string.length() > ALL_TYPES_STRING_WIDTH);
		stringWidth.stringField = string;
		try {
			stringWidthDao.create(stringWidth);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testStringWidthOkay() throws Exception {
		Dao<StringWidth, Object> stringWidthDao = createDao(StringWidth.class, true);
		StringWidth stringWidth = new StringWidth();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < ALL_TYPES_STRING_WIDTH; i++) {
			sb.append('c');
		}
		String string = sb.toString();
		assertTrue(string.length() == ALL_TYPES_STRING_WIDTH);
		stringWidth.stringField = string;
		assertEquals(1, stringWidthDao.create(stringWidth));
		List<StringWidth> stringWidthList = stringWidthDao.queryForAll();
		assertEquals(1, stringWidthList.size());
		assertTrue(stringWidthDao.objectsEqual(stringWidth, stringWidthList.get(0)));
	}

	@Test
	public void testCreateReserverdTable() throws Exception {
		Dao<Create, String> whereDao = createDao(Create.class, true);
		String id = "from-string";
		Create where = new Create();
		where.id = id;
		assertEquals(1, whereDao.create(where));
		Create where2 = whereDao.queryForId(id);
		assertEquals(id, where2.id);
		assertEquals(1, whereDao.delete(where2));
		assertNull(whereDao.queryForId(id));
	}

	@Test
	public void testCreateReserverdFields() throws Exception {
		Dao<ReservedField, Object> reservedDao = createDao(ReservedField.class, true);
		String from = "from-string";
		ReservedField res = new ReservedField();
		res.from = from;
		assertEquals(1, reservedDao.create(res));

		int id = res.select;
		ReservedField res2 = reservedDao.queryForId(id);
		assertNotNull(res2);
		assertEquals(id, res2.select);

		String group = "group-string";
		for (ReservedField reserved : reservedDao) {
			assertEquals(from, reserved.from);
			reserved.group = group;
			reservedDao.update(reserved);
		}

		List<ReservedField> results =
				reservedDao.queryBuilder().where().eq(ReservedField.GROUP_FIELD, "group-string").query();
		assertEquals(1, results.size());
		assertEquals(res.select, results.get(0).select);

		CloseableIterator<ReservedField> iterator = reservedDao.iterator();
		try {
			while (iterator.hasNext()) {
				ReservedField reserved = iterator.next();
				assertEquals(from, reserved.from);
				assertEquals(group, reserved.group);
				iterator.remove();
			}
			assertEquals(0, reservedDao.queryForAll().size());
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testEscapeCharInField() throws Exception {
		if (connectionSource == null) {
			return;
		}
		StringBuilder sb = new StringBuilder();
		String word = "foo";
		connectionSource.getDatabaseType().appendEscapedWord(sb, word);
		String escaped = sb.toString();
		int index = escaped.indexOf(word);
		String escapeString = escaped.substring(0, index);

		Dao<Basic, String> fooDao = createDao(Basic.class, true);
		Basic foo1 = new Basic();
		String id = word + escapeString + word;
		foo1.id = id;
		assertEquals(1, fooDao.create(foo1));
		Basic foo2 = fooDao.queryForId(id);
		assertNotNull(foo2);
		assertEquals(id, foo2.id);
	}

	@Test
	public void testGeneratedIdCapital() throws Exception {
		createDao(GeneratedColumnCapital.class, true);
	}

	@Test
	public void testObject() throws Exception {
		Dao<ObjectHolder, Integer> objDao = createDao(ObjectHolder.class, true);

		ObjectHolder foo1 = new ObjectHolder();
		foo1.obj = new SerialData();
		String key = "key2";
		String value = "val2";
		foo1.obj.addEntry(key, value);
		String strObj = "fjpwefefwpjoefwjpojopfew";
		foo1.strObj = strObj;
		assertEquals(1, objDao.create(foo1));

		ObjectHolder foo2 = objDao.queryForId(foo1.id);
		assertTrue(objDao.objectsEqual(foo1, foo2));
	}

	@Test
	public void testNotSerializable() throws Exception {
		try {
			createDao(NotSerializable.class, true);
			fail("expected exception");
		} catch (IllegalArgumentException e) {
			// expected
		}
	}

	@Test
	public void testStringEnum() throws Exception {
		Dao<LocalEnumString, Object> fooDao = createDao(LocalEnumString.class, true);
		OurEnum ourEnum = OurEnum.SECOND;
		LocalEnumString foo = new LocalEnumString();
		foo.ourEnum = ourEnum;
		assertEquals(1, fooDao.create(foo));

		List<LocalEnumString> fooList = fooDao.queryForAll();
		assertEquals(1, fooList.size());
		assertEquals(ourEnum, fooList.get(0).ourEnum);
	}

	@Test
	public void testUnknownStringEnum() throws Exception {
		Dao<LocalEnumString, Object> fooDao = createDao(LocalEnumString.class, true);
		OurEnum ourEnum = OurEnum.SECOND;
		LocalEnumString foo = new LocalEnumString();
		foo.ourEnum = ourEnum;
		assertEquals(1, fooDao.create(foo));

		Dao<LocalEnumString2, Object> foo2Dao = createDao(LocalEnumString2.class, false);
		try {
			foo2Dao.queryForAll();
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testIntEnum() throws Exception {
		Dao<LocalEnumInt, Object> fooDao = createDao(LocalEnumInt.class, true);
		OurEnum ourEnum = OurEnum.SECOND;
		LocalEnumInt foo = new LocalEnumInt();
		foo.ourEnum = ourEnum;
		assertEquals(1, fooDao.create(foo));

		List<LocalEnumInt> fooList = fooDao.queryForAll();
		assertEquals(1, fooList.size());
		assertEquals(ourEnum, fooList.get(0).ourEnum);
	}

	@Test
	public void testUnknownIntEnum() throws Exception {
		Dao<LocalEnumInt, Object> fooDao = createDao(LocalEnumInt.class, true);
		OurEnum ourEnum = OurEnum.SECOND;
		LocalEnumInt foo = new LocalEnumInt();
		foo.ourEnum = ourEnum;
		assertEquals(1, fooDao.create(foo));

		Dao<LocalEnumInt2, Object> foo2Dao = createDao(LocalEnumInt2.class, false);
		try {
			foo2Dao.queryForAll();
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testUnknownIntUnknownValEnum() throws Exception {
		Dao<LocalEnumInt, Object> fooDao = createDao(LocalEnumInt.class, true);
		OurEnum ourEnum = OurEnum.SECOND;
		LocalEnumInt foo = new LocalEnumInt();
		foo.ourEnum = ourEnum;
		assertEquals(1, fooDao.create(foo));

		Dao<LocalEnumInt3, Object> foo2Dao = createDao(LocalEnumInt3.class, false);
		List<LocalEnumInt3> fooList = foo2Dao.queryForAll();
		assertEquals(1, fooList.size());
		assertEquals(OurEnum2.FIRST, fooList.get(0).ourEnum);
	}

	@Test
	public void testNullHandling() throws Exception {
		Dao<AllObjectTypes, Object> allDao = createDao(AllObjectTypes.class, true);
		AllObjectTypes all = new AllObjectTypes();
		assertEquals(1, allDao.create(all));
		List<AllObjectTypes> allList = allDao.queryForAll();
		assertEquals(1, allList.size());
		assertTrue(allDao.objectsEqual(all, allList.get(0)));
	}

	@Test
	public void testObjectNotNullHandling() throws Exception {
		Dao<AllObjectTypes, Object> allDao = createDao(AllObjectTypes.class, true);
		AllObjectTypes all = new AllObjectTypes();
		all.stringField = "foo";
		all.booleanField = false;
		Date dateValue = new Date(1279649192000L);
		all.dateField = dateValue;
		all.byteField = 0;
		all.shortField = 0;
		all.intField = 0;
		all.longField = 0L;
		all.floatField = 0F;
		all.doubleField = 0D;
		all.objectField = new SerialData();
		all.ourEnum = OurEnum.FIRST;
		assertEquals(1, allDao.create(all));
		assertEquals(1, allDao.refresh(all));
		List<AllObjectTypes> allList = allDao.queryForAll();
		assertEquals(1, allList.size());
		assertTrue(allDao.objectsEqual(all, allList.get(0)));
	}

	@Test
	public void testDefaultValueHandling() throws Exception {
		Dao<AllTypesDefault, Object> allDao = createDao(AllTypesDefault.class, true);
		AllTypesDefault all = new AllTypesDefault();
		assertEquals(1, allDao.create(all));
		assertEquals(1, allDao.refresh(all));
		List<AllTypesDefault> allList = allDao.queryForAll();
		assertEquals(1, allList.size());
		all.stringField = DEFAULT_STRING_VALUE;
		DateFormat defaultDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS", Locale.US);
		all.dateField = defaultDateFormat.parse(DEFAULT_DATE_VALUE);
		all.dateLongField = new Date(Long.parseLong(DEFAULT_DATE_LONG_VALUE));
		DateFormat defaultDateStringFormat = new SimpleDateFormat(DEFAULT_DATE_STRING_FORMAT, Locale.US);
		all.dateStringField = defaultDateStringFormat.parse(DEFAULT_DATE_STRING_VALUE);
		all.booleanField = Boolean.parseBoolean(DEFAULT_BOOLEAN_VALUE);
		all.booleanObj = Boolean.parseBoolean(DEFAULT_BOOLEAN_VALUE);
		all.byteField = Byte.parseByte(DEFAULT_BYTE_VALUE);
		all.byteObj = Byte.parseByte(DEFAULT_BYTE_VALUE);
		all.shortField = Short.parseShort(DEFAULT_SHORT_VALUE);
		all.shortObj = Short.parseShort(DEFAULT_SHORT_VALUE);
		all.intField = Integer.parseInt(DEFAULT_INT_VALUE);
		all.intObj = Integer.parseInt(DEFAULT_INT_VALUE);
		all.longField = Long.parseLong(DEFAULT_LONG_VALUE);
		all.longObj = Long.parseLong(DEFAULT_LONG_VALUE);
		all.floatField = Float.parseFloat(DEFAULT_FLOAT_VALUE);
		all.floatObj = Float.parseFloat(DEFAULT_FLOAT_VALUE);
		all.doubleField = Double.parseDouble(DEFAULT_DOUBLE_VALUE);
		all.doubleObj = Double.parseDouble(DEFAULT_DOUBLE_VALUE);
		all.ourEnum = OurEnum.valueOf(DEFAULT_ENUM_VALUE);
		assertFalse(allDao.objectsEqual(all, allList.get(0)));
	}

	@Test
	public void testBooleanDefaultValueHandling() throws Exception {
		Dao<BooleanDefault, Object> allDao = createDao(BooleanDefault.class, true);
		BooleanDefault all = new BooleanDefault();
		assertEquals(1, allDao.create(all));
		List<BooleanDefault> allList = allDao.queryForAll();
		assertEquals(1, allList.size());
		all.booleanField = Boolean.parseBoolean(DEFAULT_BOOLEAN_VALUE);
		all.booleanObj = Boolean.parseBoolean(DEFAULT_BOOLEAN_VALUE);
		assertFalse(allDao.objectsEqual(all, allList.get(0)));
	}

	@Test
	public void testNullUnPersistToBooleanPrimitive() throws Exception {
		Dao<NullBoolean1, Object> null1Dao = createDao(NullBoolean1.class, true);
		NullBoolean1 nullThing = new NullBoolean1();
		assertEquals(1, null1Dao.create(nullThing));
		Dao<NullBoolean2, Object> null2Dao = createDao(NullBoolean2.class, false);
		try {
			null2Dao.queryForAll();
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testNullUnPersistToIntPrimitive() throws Exception {
		Dao<NullInt1, Object> null1Dao = createDao(NullInt1.class, true);
		NullInt1 nullThing = new NullInt1();
		assertEquals(1, null1Dao.create(nullThing));
		Dao<NullInt2, Object> null2Dao = createDao(NullInt2.class, false);
		try {
			null2Dao.queryForAll();
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testQueryRawStrings() throws Exception {
		Dao<Foo, Object> fooDao = createDao(Foo.class, true);
		Foo foo = new Foo();
		String stuff = "eprjpejrre";
		foo.stuff = stuff;

		String queryString = buildFooQueryAllString(fooDao);
		GenericRawResults<String[]> results = fooDao.queryRaw(queryString);
		assertEquals(0, results.getResults().size());
		assertEquals(1, fooDao.create(foo));

		results = fooDao.queryRaw(queryString);
		int colN = results.getNumberColumns();
		String[] colNames = results.getColumnNames();
		assertEquals(3, colNames.length);
		boolean gotId = false;
		boolean gotStuff = false;
		boolean gotVal = false;
		// all this crap is here because of android column order
		for (int colC = 0; colC < 3; colC++) {
			if (colNames[colC].equalsIgnoreCase(Foo.ID_FIELD_NAME)) {
				gotId = true;
			} else if (colNames[colC].equalsIgnoreCase(Foo.STUFF_FIELD_NAME)) {
				gotStuff = true;
			} else if (colNames[colC].equalsIgnoreCase(Foo.VAL_FIELD_NAME)) {
				gotVal = true;
			}
		}
		assertTrue(gotId);
		assertTrue(gotStuff);
		assertTrue(gotVal);
		List<String[]> resultList = results.getResults();
		assertEquals(1, resultList.size());
		String[] result = resultList.get(0);
		assertEquals(colN, result.length);
		for (int colC = 0; colC < results.getNumberColumns(); colC++) {
			if (results.getColumnNames()[colC] == "id") {
				assertEquals(Integer.toString(foo.id), result[colC]);
			}
			if (results.getColumnNames()[colC] == "stuff") {
				assertEquals(stuff, result[1]);
			}
		}
	}

	@Test
	public void testQueryRawStringsIterator() throws Exception {
		Dao<Foo, Object> fooDao = createDao(Foo.class, true);
		Foo foo = new Foo();
		String stuff = "eprjpejrre";
		int val = 12321411;
		foo.stuff = stuff;
		foo.val = val;

		String queryString = buildFooQueryAllString(fooDao);
		GenericRawResults<String[]> results = fooDao.queryRaw(queryString);
		CloseableIterator<String[]> iterator = results.closeableIterator();
		try {
			assertFalse(iterator.hasNext());
		} finally {
			iterator.close();
		}
		assertEquals(1, fooDao.create(foo));

		results = fooDao.queryRaw(queryString);
		int colN = results.getNumberColumns();
		String[] colNames = results.getColumnNames();
		assertEquals(3, colNames.length);
		iterator = results.closeableIterator();
		try {
			assertTrue(iterator.hasNext());
			String[] result = iterator.next();
			assertEquals(colN, result.length);
			boolean foundId = false;
			boolean foundStuff = false;
			boolean foundVal = false;
			for (int colC = 0; colC < results.getNumberColumns(); colC++) {
				if (results.getColumnNames()[colC].equalsIgnoreCase(Foo.ID_FIELD_NAME)) {
					assertEquals(Integer.toString(foo.id), result[colC]);
					foundId = true;
				}
				if (results.getColumnNames()[colC].equalsIgnoreCase(Foo.STUFF_FIELD_NAME)) {
					assertEquals(stuff, result[colC]);
					foundStuff = true;
				}
				if (results.getColumnNames()[colC].equalsIgnoreCase(Foo.VAL_FIELD_NAME)) {
					assertEquals(Integer.toString(val), result[colC]);
					foundVal = true;
				}
			}
			assertTrue(foundId);
			assertTrue(foundStuff);
			assertTrue(foundVal);
			assertFalse(iterator.hasNext());
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testQueryRawMappedIterator() throws Exception {
		Dao<Foo, Object> fooDao = createDao(Foo.class, true);
		final Foo foo = new Foo();
		String stuff = "eprjpejrre";
		foo.stuff = stuff;

		String queryString = buildFooQueryAllString(fooDao);
		Mapper mapper = new Mapper();
		GenericRawResults<Foo> rawResults = fooDao.queryRaw(queryString, mapper);
		assertEquals(0, rawResults.getResults().size());
		assertEquals(1, fooDao.create(foo));
		rawResults = fooDao.queryRaw(queryString, mapper);
		Iterator<Foo> iterator = rawResults.iterator();
		assertTrue(iterator.hasNext());
		Foo foo2 = iterator.next();
		assertEquals(foo.id, foo2.id);
		assertEquals(foo.stuff, foo2.stuff);
		assertEquals(foo.val, foo2.val);
		assertFalse(iterator.hasNext());
	}

	@Test
	public void testQueryRawObjectsIterator() throws Exception {
		Dao<Foo, Object> fooDao = createDao(Foo.class, true);
		Foo foo = new Foo();
		String stuff = "eprjpejrre";
		int val = 213123;
		foo.stuff = stuff;
		foo.val = val;

		String queryString = buildFooQueryAllString(fooDao);
		GenericRawResults<Object[]> results =
				fooDao.queryRaw(queryString, new DataType[] { DataType.INTEGER, DataType.STRING, DataType.INTEGER });
		CloseableIterator<Object[]> iterator = results.closeableIterator();
		try {
			assertFalse(iterator.hasNext());
		} finally {
			iterator.close();
		}
		assertEquals(1, fooDao.create(foo));

		results = fooDao.queryRaw(queryString, new DataType[] { DataType.INTEGER, DataType.STRING, DataType.INTEGER });
		int colN = results.getNumberColumns();
		String[] colNames = results.getColumnNames();
		assertEquals(3, colNames.length);
		iterator = results.closeableIterator();
		try {
			assertTrue(iterator.hasNext());
			Object[] result = iterator.next();
			assertEquals(colN, result.length);
			String[] columnNames = results.getColumnNames();
			boolean foundId = false;
			boolean foundStuff = false;
			boolean foundVal = false;
			for (int colC = 0; colC < results.getNumberColumns(); colC++) {
				if (columnNames[colC].equalsIgnoreCase(Foo.ID_FIELD_NAME)) {
					assertEquals(foo.id, result[colC]);
					foundId = true;
				}
				if (columnNames[colC].equalsIgnoreCase(Foo.STUFF_FIELD_NAME)) {
					assertEquals(stuff, result[colC]);
					foundStuff = true;
				}
				if (columnNames[colC].equalsIgnoreCase(Foo.VAL_FIELD_NAME)) {
					assertEquals(val, result[colC]);
					foundVal = true;
				}
			}
			assertTrue(foundId);
			assertTrue(foundStuff);
			assertTrue(foundVal);
			assertFalse(iterator.hasNext());
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testNotNullDefault() throws Exception {
		Dao<NotNullDefault, Object> dao = createDao(NotNullDefault.class, true);
		NotNullDefault notNullDefault = new NotNullDefault();
		assertEquals(1, dao.create(notNullDefault));
	}

	@Test
	public void testStringDefault() throws Exception {
		Dao<StringDefalt, Object> dao = createDao(StringDefalt.class, true);
		StringDefalt foo = new StringDefalt();
		assertEquals(1, dao.create(foo));
	}

	@Test
	public void testDateUpdate() throws Exception {
		Dao<LocalDate, Object> dao = createDao(LocalDate.class, true);
		LocalDate localDate = new LocalDate();
		// note: this does not have milliseconds
		Date date = new Date(2131232000);
		localDate.date = date;
		assertEquals(1, dao.create(localDate));
		List<LocalDate> allDates = dao.queryForAll();
		assertEquals(1, allDates.size());
		assertEquals(date, allDates.get(0).date);

		// now we update it
		assertEquals(1, dao.update(localDate));
		allDates = dao.queryForAll();
		assertEquals(1, allDates.size());
		assertEquals(date, allDates.get(0).date);

		// now we set it to null
		localDate.date = null;
		// now we update it
		assertEquals(1, dao.update(localDate));
		allDates = dao.queryForAll();
		assertEquals(1, allDates.size());
		// we should get null back and not some auto generated field
		assertNull(allDates.get(0).date);
	}

	@Test
	public void testDateRefresh() throws Exception {
		Dao<LocalDate, Object> dao = createDao(LocalDate.class, true);
		LocalDate localDate = new LocalDate();
		// note: this does not have milliseconds
		Date date = new Date(2131232000);
		localDate.date = date;
		assertEquals(1, dao.create(localDate));
		assertEquals(1, dao.refresh(localDate));
	}

	@Test
	public void testSpringBadWiring() throws Exception {
		BaseDaoImpl<String, String> daoSupport = new BaseDaoImpl<String, String>(String.class) {
		};
		try {
			daoSupport.initialize();
			fail("expected exception");
		} catch (IllegalStateException e) {
			// expected
		}
	}

	@Test
	public void testUnique() throws Exception {
		Dao<Unique, Long> dao = createDao(Unique.class, true);
		String stuff = "this doesn't need to be unique";
		String uniqueStuff = "this needs to be unique";
		Unique unique = new Unique();
		unique.stuff = stuff;
		unique.uniqueStuff = uniqueStuff;
		assertEquals(1, dao.create(unique));
		// can't create it twice with the same stuff which needs to be unique
		unique = new Unique();
		unique.stuff = stuff;
		assertEquals(1, dao.create(unique));
		unique = new Unique();
		unique.uniqueStuff = uniqueStuff;
		try {
			dao.create(unique);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testDoubleUnique() throws Exception {
		Dao<DoubleUnique, Long> dao = createDao(DoubleUnique.class, true);
		String stuff = "this doesn't need to be unique";
		String uniqueStuff = "this needs to be unique";
		DoubleUnique unique = new DoubleUnique();
		unique.stuff = stuff;
		unique.uniqueStuff = uniqueStuff;
		assertEquals(1, dao.create(unique));
		// can't create it twice with the same stuff which needs to be unique
		unique = new DoubleUnique();
		unique.stuff = stuff;
		try {
			// either 1st field can't be unique
			dao.create(unique);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
		unique = new DoubleUnique();
		unique.uniqueStuff = uniqueStuff;
		try {
			// nor 2nd field can't be unique
			dao.create(unique);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
		unique = new DoubleUnique();
		unique.stuff = stuff;
		unique.uniqueStuff = uniqueStuff;
		try {
			// nor both fields can't be unique
			dao.create(unique);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testDoubleUniqueCombo() throws Exception {
		Dao<DoubleUniqueCombo, Long> dao = createDao(DoubleUniqueCombo.class, true);
		String stuff = "this doesn't need to be unique";
		String uniqueStuff = "this needs to be unique";
		DoubleUniqueCombo unique = new DoubleUniqueCombo();
		unique.stuff = stuff;
		unique.uniqueStuff = uniqueStuff;
		assertEquals(1, dao.create(unique));
		// can't create it twice with the same stuff which needs to be unique
		unique = new DoubleUniqueCombo();
		unique.stuff = stuff;
		assertEquals(1, dao.create(unique));
		unique = new DoubleUniqueCombo();
		unique.uniqueStuff = uniqueStuff;
		assertEquals(1, dao.create(unique));
		unique = new DoubleUniqueCombo();
		unique.stuff = stuff;
		unique.uniqueStuff = uniqueStuff;
		try {
			dao.create(unique);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testUniqueAndUniqueCombo() throws Exception {
		Dao<UniqueAndUniqueCombo, Long> dao = createDao(UniqueAndUniqueCombo.class, true);
		String unique1 = "unique but not combo";
		String combo1 = "combo unique";
		String combo2 = "another combo unique";
		UniqueAndUniqueCombo unique = new UniqueAndUniqueCombo();
		unique.unique1 = unique1;
		assertEquals(1, dao.create(unique));
		// can't create it twice with the same stuff which needs to be unique
		unique = new UniqueAndUniqueCombo();
		unique.unique1 = unique1;
		try {
			dao.create(unique);
			fail("this should throw");
		} catch (Exception e) {
			// expected
		}
		unique = new UniqueAndUniqueCombo();
		unique.combo1 = combo1;
		unique.combo2 = combo2;
		assertEquals(1, dao.create(unique));
		unique = new UniqueAndUniqueCombo();
		unique.combo1 = combo1;
		unique.combo2 = unique1;
		assertEquals(1, dao.create(unique));
		unique = new UniqueAndUniqueCombo();
		unique.combo1 = unique1;
		unique.combo2 = combo2;
		assertEquals(1, dao.create(unique));
		unique = new UniqueAndUniqueCombo();
		unique.combo1 = combo1;
		unique.combo2 = combo2;
		try {
			dao.create(unique);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testForeignQuery() throws Exception {
		Dao<ForeignWrapper, Integer> wrapperDao = createDao(ForeignWrapper.class, true);
		Dao<AllTypes, Integer> foreignDao = createDao(AllTypes.class, true);

		AllTypes foreign = new AllTypes();
		String stuff1 = "stuff1";
		foreign.stringField = stuff1;
		Date date = new Date();
		foreign.dateField = date;
		// this sets the foreign id
		assertEquals(1, foreignDao.create(foreign));

		ForeignWrapper wrapper = new ForeignWrapper();
		wrapper.foreign = foreign;
		// this sets the wrapper id
		assertEquals(1, wrapperDao.create(wrapper));

		QueryBuilder<ForeignWrapper, Integer> qb = wrapperDao.queryBuilder();
		qb.where().eq(ForeignWrapper.FOREIGN_FIELD_NAME, foreign.id);
		List<ForeignWrapper> results = wrapperDao.query(qb.prepare());
		assertEquals(1, results.size());
		assertNotNull(results.get(0).foreign);
		assertEquals(foreign.id, results.get(0).foreign.id);

		/*
		 * now look it up not by foreign.id but by foreign which should extract the id automagically
		 */
		qb.where().eq(ForeignWrapper.FOREIGN_FIELD_NAME, foreign);
		results = wrapperDao.query(qb.prepare());
		assertEquals(1, results.size());
		assertNotNull(results.get(0).foreign);
		assertEquals(foreign.id, results.get(0).foreign.id);

		/*
		 * Now let's try the same thing but with a SelectArg
		 */
		SelectArg selectArg = new SelectArg();
		qb.where().eq(ForeignWrapper.FOREIGN_FIELD_NAME, selectArg);
		selectArg.setValue(foreign.id);
		results = wrapperDao.query(qb.prepare());
		assertEquals(1, results.size());
		assertNotNull(results.get(0).foreign);
		assertEquals(foreign.id, results.get(0).foreign.id);

		/*
		 * Now let's try the same thing but with a SelectArg with foreign value, not foreign.id
		 */
		selectArg = new SelectArg();
		qb.where().eq(ForeignWrapper.FOREIGN_FIELD_NAME, selectArg);
		selectArg.setValue(foreign);
		results = wrapperDao.query(qb.prepare());
		assertEquals(1, results.size());
		assertNotNull(results.get(0).foreign);
		assertEquals(foreign.id, results.get(0).foreign.id);
	}

	@Test
	public void testPrepareStatementUpdateValueString() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo = new Foo();
		String stuff = "dqedqdq";
		foo.stuff = stuff;
		assertEquals(1, fooDao.create(foo));

		QueryBuilder<Foo, Integer> stmtb = fooDao.queryBuilder();
		stmtb.where().eq(Foo.STUFF_FIELD_NAME, stuff);
		List<Foo> results = fooDao.query(stmtb.prepare());
		assertEquals(1, results.size());

		UpdateBuilder<Foo, Integer> updateb = fooDao.updateBuilder();
		String newStuff = "fepojefpjo";
		updateb.updateColumnValue(Foo.STUFF_FIELD_NAME, newStuff);
		assertEquals(1, fooDao.update(updateb.prepare()));

		results = fooDao.query(stmtb.prepare());
		assertEquals(0, results.size());
	}

	@Test
	public void testInSubQuery() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Dao<Basic, String> basicDao = createDao(Basic.class, true);

		Basic basic1 = new Basic();
		String string1 = "ewpofjewgprgrg";
		basic1.id = string1;
		assertEquals(1, basicDao.create(basic1));
		Basic basic2 = new Basic();
		String string2 = "e2432423432wpofjewgprgrg";
		basic2.id = string2;
		assertEquals(1, basicDao.create(basic2));

		Foo foo1 = new Foo();
		foo1.stuff = basic1.id;
		Foo foo2 = new Foo();
		foo2.stuff = basic2.id;
		Foo foo3 = new Foo();
		String string3 = "neither of the others";
		foo3.stuff = string3;

		int num1 = 7;
		for (int i = 0; i < num1; i++) {
			assertEquals(1, fooDao.create(foo1));
		}
		int num2 = 17;
		for (int i = 0; i < num2; i++) {
			assertEquals(1, fooDao.create(foo2));
		}
		int num3 = 29;
		long maxId = 0;
		for (int i = 0; i < num3; i++) {
			assertEquals(1, fooDao.create(foo3));
			if (foo3.id > maxId) {
				maxId = foo3.id;
			}
		}

		QueryBuilder<Basic, String> bqb = basicDao.queryBuilder();
		bqb.selectColumns(Basic.ID_FIELD);

		// string1
		bqb.where().eq(Basic.ID_FIELD, string1);
		List<Foo> results = fooDao.query(fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(num1, results.size());

		// string2
		bqb.where().eq(Basic.ID_FIELD, string2);
		results = fooDao.query(fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(num2, results.size());

		// ! string2 with not().in(...)
		bqb.where().eq(Basic.ID_FIELD, string2);
		results = fooDao.query(fooDao.queryBuilder().where().not().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(num1 + num3, results.size());

		// string3 which there should be none
		bqb.where().eq(Basic.ID_FIELD, string3);
		results = fooDao.query(fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(0, results.size());

		// string1 OR string2
		bqb.where().eq(Basic.ID_FIELD, string1).or().eq(Basic.ID_FIELD, string2);
		results = fooDao.query(fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(num1 + num2, results.size());

		// all strings IN
		bqb.where().in(Basic.ID_FIELD, string1, string2, string3);
		results = fooDao.query(fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(num1 + num2, results.size());

		// string1 AND string2 which there should be none
		bqb.where().eq(Basic.ID_FIELD, string1).and().eq(Basic.ID_FIELD, string2);
		results = fooDao.query(fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).prepare());
		assertEquals(0, results.size());
	}

	@Test
	public void testInSubQuerySelectArgs() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Dao<Basic, String> basicDao = createDao(Basic.class, true);

		Basic basic1 = new Basic();
		String string1 = "ewpofjewgprgrg";
		basic1.id = string1;
		assertEquals(1, basicDao.create(basic1));
		Basic basic2 = new Basic();
		String string2 = "e2432423432wpofjewgprgrg";
		basic2.id = string2;
		assertEquals(1, basicDao.create(basic2));

		Foo foo1 = new Foo();
		foo1.stuff = basic1.id;
		Foo foo2 = new Foo();
		foo2.stuff = basic2.id;

		int num1 = 7;
		for (int i = 0; i < num1; i++) {
			assertEquals(1, fooDao.create(foo1));
		}
		int num2 = 17;
		long maxId = 0;
		for (int i = 0; i < num2; i++) {
			assertEquals(1, fooDao.create(foo2));
			if (foo2.id > maxId) {
				maxId = foo2.id;
			}
		}
		// using seletArgs
		SelectArg arg1 = new SelectArg();
		SelectArg arg2 = new SelectArg();
		QueryBuilder<Basic, String> bqb = basicDao.queryBuilder();
		bqb.selectColumns(Basic.ID_FIELD);
		bqb.where().eq(Basic.ID_FIELD, arg1);
		PreparedQuery<Foo> preparedQuery =
				fooDao.queryBuilder().where().in(Foo.STUFF_FIELD_NAME, bqb).and().lt(Foo.ID_FIELD_NAME, arg2).prepare();
		arg1.setValue(string1);
		// this should get none
		arg2.setValue(0);
		List<Foo> results = fooDao.query(preparedQuery);
		assertEquals(0, results.size());
	}

	@Test
	public void testPrepareStatementUpdateValueNumber() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo = new Foo();
		foo.val = 123213;
		assertEquals(1, fooDao.create(foo));

		QueryBuilder<Foo, Integer> stmtb = fooDao.queryBuilder();
		stmtb.where().eq(Foo.ID_FIELD_NAME, foo.id);
		List<Foo> results = fooDao.query(stmtb.prepare());
		assertEquals(1, results.size());

		UpdateBuilder<Foo, Integer> updateb = fooDao.updateBuilder();
		updateb.updateColumnValue(Foo.VAL_FIELD_NAME, foo.val + 1);
		assertEquals(1, fooDao.update(updateb.prepare()));

		results = fooDao.query(stmtb.prepare());
		assertEquals(1, results.size());
		assertEquals(foo.val + 1, results.get(0).val);
	}

	@Test
	public void testPrepareStatementUpdateValueExpression() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo = new Foo();
		foo.val = 123213;
		assertEquals(1, fooDao.create(foo));

		QueryBuilder<Foo, Integer> stmtb = fooDao.queryBuilder();
		stmtb.where().eq(Foo.ID_FIELD_NAME, foo.id);
		List<Foo> results = fooDao.query(stmtb.prepare());
		assertEquals(1, results.size());

		UpdateBuilder<Foo, Integer> updateb = fooDao.updateBuilder();
		String stuff = "deopdjq";
		updateb.updateColumnValue(Foo.STUFF_FIELD_NAME, stuff);
		StringBuilder sb = new StringBuilder();
		updateb.escapeColumnName(sb, Foo.VAL_FIELD_NAME);
		sb.append("+ 1");
		updateb.updateColumnExpression(Foo.VAL_FIELD_NAME, sb.toString());
		assertEquals(1, fooDao.update(updateb.prepare()));

		results = fooDao.queryForAll();
		assertEquals(1, results.size());
		assertEquals(stuff, results.get(0).stuff);
		assertEquals(foo.val + 1, results.get(0).val);
	}

	@Test
	public void testPrepareStatementUpdateValueWhere() throws Exception {
		Dao<Foo, Integer> fooDao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		foo1.val = 78582351;
		assertEquals(1, fooDao.create(foo1));
		Foo foo2 = new Foo();
		String stuff = "eopqjdepodje";
		foo2.stuff = stuff;
		foo2.val = 123344131;
		assertEquals(1, fooDao.create(foo2));

		UpdateBuilder<Foo, Integer> updateb = fooDao.updateBuilder();
		String newStuff = "deopdjq";
		updateb.updateColumnValue(Foo.STUFF_FIELD_NAME, newStuff);
		StringBuilder sb = new StringBuilder();
		updateb.escapeColumnName(sb, Foo.VAL_FIELD_NAME);
		sb.append("+ 1");
		updateb.updateColumnExpression(Foo.VAL_FIELD_NAME, sb.toString());
		updateb.where().eq(Foo.ID_FIELD_NAME, foo2.id);
		assertEquals(1, fooDao.update(updateb.prepare()));

		List<Foo> results = fooDao.queryForAll();
		assertEquals(2, results.size());
		Foo foo = results.get(0);
		assertEquals(foo1.id, foo.id);
		assertEquals(foo1.val, foo.val);
		assertNull(foo.stuff);
		foo = results.get(1);
		assertEquals(foo2.id, foo.id);
		assertEquals(foo2.val + 1, foo.val);
		assertEquals(newStuff, foo.stuff);
	}

	@Test
	public void testStringAsId() throws Exception {
		checkTypeAsId(StringId.class, "foo", "bar");
	}

	@Test
	public void testLongStringAsId() throws Exception {
		try {
			createDao(LongStringId.class, true);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testBooleanAsId() throws Exception {
		try {
			createDao(BooleanId.class, true);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testBooleanObjAsId() throws Exception {
		try {
			createDao(BooleanObjId.class, true);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testDateAsId() throws Exception {
		// no milliseconds
		checkTypeAsId(DateId.class, new Date(1232312313000L), new Date(1232312783000L));
	}

	@Test
	public void testDateLongAsId() throws Exception {
		// no milliseconds
		checkTypeAsId(DateLongId.class, new Date(1232312313000L), new Date(1232312783000L));
	}

	@Test
	public void testDateStringAsId() throws Exception {
		// no milliseconds
		checkTypeAsId(DateStringId.class, new Date(1232312313000L), new Date(1232312783000L));
	}

	@Test
	public void testByteAsId() throws Exception {
		checkTypeAsId(ByteId.class, (byte) 1, (byte) 2);
	}

	@Test
	public void testByteObjAsId() throws Exception {
		checkTypeAsId(ByteObjId.class, (byte) 1, (byte) 2);
	}

	@Test
	public void testShortAsId() throws Exception {
		checkTypeAsId(ShortId.class, (short) 1, (short) 2);
	}

	@Test
	public void testShortObjAsId() throws Exception {
		checkTypeAsId(ShortObjId.class, (short) 1, (short) 2);
	}

	@Test
	public void testIntAsId() throws Exception {
		checkTypeAsId(IntId.class, (int) 1, (int) 2);
	}

	@Test
	public void testIntObjAsId() throws Exception {
		checkTypeAsId(IntObjId.class, (int) 1, (int) 2);
	}

	@Test
	public void testLongAsId() throws Exception {
		checkTypeAsId(LongId.class, (long) 1, (long) 2);
	}

	@Test
	public void testLongObjAsId() throws Exception {
		checkTypeAsId(LongObjId.class, (long) 1, (long) 2);
	}

	@Test
	public void testFloatAsId() throws Exception {
		checkTypeAsId(FloatId.class, (float) 1, (float) 2);
	}

	@Test
	public void testFloatObjAsId() throws Exception {
		checkTypeAsId(FloatObjId.class, (float) 1, (float) 2);
	}

	@Test
	public void testDoubleAsId() throws Exception {
		checkTypeAsId(DoubleId.class, (double) 1, (double) 2);
	}

	@Test
	public void testDoubleObjAsId() throws Exception {
		checkTypeAsId(DoubleObjId.class, (double) 1, (double) 2);
	}

	@Test
	public void testEnumAsId() throws Exception {
		checkTypeAsId(EnumId.class, OurEnum.SECOND, OurEnum.FIRST);
	}

	@Test
	public void testEnumStringAsId() throws Exception {
		checkTypeAsId(EnumStringId.class, OurEnum.SECOND, OurEnum.FIRST);
	}

	@Test
	public void testEnumIntegerAsId() throws Exception {
		checkTypeAsId(EnumIntegerId.class, OurEnum.SECOND, OurEnum.FIRST);
	}

	@Test
	public void testSerializableAsId() throws Exception {
		try {
			createDao(SerializableId.class, true);
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testRecursiveForeign() throws Exception {
		Dao<Recursive, Integer> recursiveDao = createDao(Recursive.class, true);
		Recursive recursive1 = new Recursive();
		Recursive recursive2 = new Recursive();
		recursive2.foreign = recursive1;
		assertEquals(recursiveDao.create(recursive1), 1);
		assertEquals(recursiveDao.create(recursive2), 1);
		Recursive recursive3 = recursiveDao.queryForId(recursive2.id);
		assertNotNull(recursive3);
		assertEquals(recursive1.id, recursive3.foreign.id);
	}

	@Test
	public void testSerializableWhere() throws Exception {
		Dao<AllTypes, Object> allDao = createDao(AllTypes.class, true);
		try {
			// can't query for a serial field
			allDao.queryBuilder().where().eq(AllTypes.SERIAL_FIELD_NAME, new SelectArg());
			fail("expected exception");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testSerializedBytes() throws Exception {
		Dao<SerializedBytes, Integer> dao = createDao(SerializedBytes.class, true);
		SerializedBytes serial = new SerializedBytes();
		serial.bytes = new byte[] { 1, 25, 3, 124, 10 };
		assertEquals(1, dao.create(serial));
		SerializedBytes raw2 = dao.queryForId(serial.id);
		assertNotNull(raw2);
		assertEquals(serial.id, raw2.id);
		assertTrue(Arrays.equals(serial.bytes, raw2.bytes));
	}

	@Test
	public void testByteArray() throws Exception {
		Dao<ByteArray, Integer> dao = createDao(ByteArray.class, true);
		ByteArray foo = new ByteArray();
		foo.bytes = new byte[] { 17, 25, 3, 124, 0, 127, 10 };
		assertEquals(1, dao.create(foo));
		ByteArray raw2 = dao.queryForId(foo.id);
		assertNotNull(raw2);
		assertEquals(foo.id, raw2.id);
		assertTrue(Arrays.equals(foo.bytes, raw2.bytes));
	}

	@Test
	public void testSuperClassAnnotations() throws Exception {
		Dao<Sub, Integer> dao = createDao(Sub.class, true);
		Sub sub1 = new Sub();
		String stuff = "doepqjdpqdq";
		sub1.stuff = stuff;
		assertEquals(1, dao.create(sub1));
		Sub sub2 = dao.queryForId(sub1.id);
		assertNotNull(sub2);
		assertEquals(sub1.id, sub2.id);
		assertEquals(sub1.stuff, sub2.stuff);
	}

	@Test
	public void testFieldIndex() throws Exception {
		Dao<Index, Integer> dao = createDao(Index.class, true);
		Index index1 = new Index();
		String stuff = "doepqjdpqdq";
		index1.stuff = stuff;
		assertEquals(1, dao.create(index1));
		Index index2 = dao.queryForId(index1.id);
		assertNotNull(index2);
		assertEquals(index1.id, index2.id);
		assertEquals(stuff, index2.stuff);
		// this should work
		assertEquals(1, dao.create(index1));

		PreparedQuery<Index> query = dao.queryBuilder().where().eq("stuff", index1.stuff).prepare();
		List<Index> results = dao.query(query);
		assertNotNull(results);
		assertEquals(2, results.size());
		assertEquals(stuff, results.get(0).stuff);
		assertEquals(stuff, results.get(1).stuff);
	}

	@Test
	public void testFieldIndexColumnName() throws Exception {
		Dao<IndexColumnName, Integer> dao = createDao(IndexColumnName.class, true);
		IndexColumnName index1 = new IndexColumnName();
		String stuff = "doepqjdpqdq";
		index1.stuff = stuff;
		assertEquals(1, dao.create(index1));
		IndexColumnName index2 = dao.queryForId(index1.id);
		assertNotNull(index2);
		assertEquals(index1.id, index2.id);
		assertEquals(stuff, index2.stuff);
		// this should work
		assertEquals(1, dao.create(index1));

		PreparedQuery<IndexColumnName> query =
				dao.queryBuilder().where().eq(IndexColumnName.STUFF_COLUMN_NAME, index1.stuff).prepare();
		List<IndexColumnName> results = dao.query(query);
		assertNotNull(results);
		assertEquals(2, results.size());
		assertEquals(stuff, results.get(0).stuff);
		assertEquals(stuff, results.get(1).stuff);
	}

	@Test
	public void testFieldUniqueIndex() throws Exception {
		Dao<UniqueIndex, Integer> dao = createDao(UniqueIndex.class, true);
		UniqueIndex index1 = new UniqueIndex();
		String stuff1 = "doepqjdpqdq";
		index1.stuff = stuff1;
		assertEquals(1, dao.create(index1));
		UniqueIndex index2 = dao.queryForId(index1.id);
		assertNotNull(index2);
		assertEquals(index1.id, index2.id);
		assertEquals(stuff1, index2.stuff);
		try {
			dao.create(index1);
			fail("This should have thrown");
		} catch (SQLException e) {
			// expected
		}
		String stuff2 = "fewofwgwgwee";
		index1.stuff = stuff2;
		assertEquals(1, dao.create(index1));

		PreparedQuery<UniqueIndex> query = dao.queryBuilder().where().eq("stuff", stuff1).prepare();
		List<UniqueIndex> results = dao.query(query);
		assertNotNull(results);
		assertEquals(1, results.size());
		assertEquals(stuff1, results.get(0).stuff);

		query = dao.queryBuilder().where().eq("stuff", stuff2).prepare();
		results = dao.query(query);
		assertNotNull(results);
		assertEquals(1, results.size());
		assertEquals(stuff2, results.get(0).stuff);
	}

	@Test
	public void testComboFieldIndex() throws Exception {
		Dao<ComboIndex, Integer> dao = createDao(ComboIndex.class, true);
		ComboIndex index1 = new ComboIndex();
		String stuff = "doepqjdpqdq";
		long junk1 = 131234124213213L;
		index1.stuff = stuff;
		index1.junk = junk1;
		assertEquals(1, dao.create(index1));
		ComboIndex index2 = dao.queryForId(index1.id);
		assertNotNull(index2);
		assertEquals(index1.id, index2.id);
		assertEquals(stuff, index2.stuff);
		assertEquals(junk1, index2.junk);
		assertEquals(1, dao.create(index1));

		PreparedQuery<ComboIndex> query = dao.queryBuilder().where().eq("stuff", index1.stuff).prepare();
		List<ComboIndex> results = dao.query(query);
		assertNotNull(results);
		assertEquals(2, results.size());
		assertEquals(stuff, results.get(0).stuff);
		assertEquals(junk1, results.get(0).junk);
		assertEquals(stuff, results.get(1).stuff);
		assertEquals(junk1, results.get(1).junk);
	}

	@Test
	public void testComboUniqueFieldIndex() throws Exception {
		Dao<ComboUniqueIndex, Integer> dao = createDao(ComboUniqueIndex.class, true);
		ComboUniqueIndex index1 = new ComboUniqueIndex();
		String stuff1 = "doepqjdpqdq";
		long junk = 131234124213213L;
		index1.stuff = stuff1;
		index1.junk = junk;
		assertEquals(1, dao.create(index1));
		ComboUniqueIndex index2 = dao.queryForId(index1.id);
		assertNotNull(index2);
		assertEquals(index1.id, index2.id);
		assertEquals(index1.stuff, index2.stuff);
		assertEquals(index1.junk, index2.junk);
		try {
			dao.create(index1);
			fail("This should have thrown");
		} catch (SQLException e) {
			// expected
		}
		String stuff2 = "fpeowjfewpf";
		index1.stuff = stuff2;
		// same junk
		assertEquals(1, dao.create(index1));

		PreparedQuery<ComboUniqueIndex> query = dao.queryBuilder().where().eq("stuff", stuff1).prepare();
		List<ComboUniqueIndex> results = dao.query(query);
		assertNotNull(results);
		assertEquals(1, results.size());
		assertEquals(stuff1, results.get(0).stuff);
		assertEquals(junk, results.get(0).junk);

		query = dao.queryBuilder().where().eq("stuff", stuff2).prepare();
		results = dao.query(query);
		assertNotNull(results);
		assertEquals(1, results.size());
		assertEquals(stuff2, results.get(0).stuff);
		assertEquals(junk, results.get(0).junk);
	}

	@Test
	public void testLongVarChar() throws Exception {
		Dao<LongVarChar, Integer> dao = createDao(LongVarChar.class, true);
		LongVarChar lvc = new LongVarChar();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 10240; i++) {
			sb.append('.');
		}
		String stuff = sb.toString();
		lvc.stuff = stuff;
		assertEquals(1, dao.create(lvc));

		LongVarChar lvc2 = dao.queryForId(lvc.id);
		assertNotNull(lvc2);
		assertEquals(stuff, lvc2.stuff);
	}

	@Test
	public void testTableExists() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, false);
		assertFalse(dao.isTableExists());
		TableUtils.createTable(connectionSource, Foo.class);
		assertTrue(dao.isTableExists());

		TableUtils.dropTable(connectionSource, Foo.class, false);
		assertFalse(dao.isTableExists());
	}

	@Test
	public void testRaw() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		Foo foo = new Foo();
		int val = 131265312;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		StringBuilder sb = new StringBuilder();
		databaseType.appendEscapedEntityName(sb, Foo.VAL_FIELD_NAME);
		String fieldName = sb.toString();
		QueryBuilder<Foo, Integer> qb = dao.queryBuilder();
		qb.where().eq(Foo.ID_FIELD_NAME, foo.id).and().raw(fieldName + " = " + val);
		assertEquals(1, dao.query(qb.prepare()).size());
		qb.where().eq(Foo.ID_FIELD_NAME, foo.id).and().raw(fieldName + " != " + val);
		assertEquals(0, dao.query(qb.prepare()).size());
	}

	@Test
	public void testUuidInsertQuery() throws Exception {
		Dao<UuidGeneratedId, UUID> dao = createDao(UuidGeneratedId.class, true);
		UuidGeneratedId uuid1 = new UuidGeneratedId();
		String stuff1 = "fopewfjefjwgw";
		uuid1.stuff = stuff1;
		assertNull(uuid1.id);
		assertEquals(1, dao.create(uuid1));
		assertNotNull(uuid1.id);

		UuidGeneratedId uuid2 = new UuidGeneratedId();
		String stuff2 = "fopefewjfepowfjefjwgw";
		uuid2.stuff = stuff2;
		assertNull(uuid2.id);
		assertEquals(1, dao.create(uuid2));
		assertNotNull(uuid2.id);
		assertFalse(uuid1.id.equals(uuid2.id));

		List<UuidGeneratedId> uuids = dao.queryForAll();
		assertEquals(2, uuids.size());
		UuidGeneratedId uuid3 = dao.queryForId(uuid1.id);
		assertEquals(stuff1, uuid3.stuff);
		uuid3 = dao.queryForId(uuid2.id);
		assertEquals(stuff2, uuid3.stuff);
	}

	@Test
	public void testBaseDaoEnabled() throws Exception {
		Dao<One, Integer> dao = createDao(One.class, true);
		One one = new One();
		String stuff = "fewpfjewfew";
		one.stuff = stuff;
		one.setDao(dao);
		assertEquals(1, one.create());
	}

	@Test
	public void testBaseDaoEnabledForeign() throws Exception {
		Dao<One, Integer> oneDao = createDao(One.class, true);
		Dao<ForeignDaoEnabled, Integer> foreignDao = createDao(ForeignDaoEnabled.class, true);

		One one = new One();
		String stuff = "fewpfjewfew";
		one.stuff = stuff;
		one.setDao(oneDao);
		assertEquals(1, one.create());

		ForeignDaoEnabled foreign = new ForeignDaoEnabled();
		foreign.one = one;
		foreign.setDao(foreignDao);
		assertEquals(1, foreign.create());

		ForeignDaoEnabled foreign2 = foreignDao.queryForId(foreign.id);
		assertNotNull(foreign2);
		assertEquals(one.id, foreign2.one.id);
		assertNull(foreign2.one.stuff);
		assertEquals(1, foreign2.one.refresh());
		assertEquals(stuff, foreign2.one.stuff);
	}

	@Test
	public void testBasicEagerCollection() throws Exception {
		Dao<EagerAccount, Integer> accountDao = createDao(EagerAccount.class, true);
		Dao<EagerOrder, Integer> orderDao = createDao(EagerOrder.class, true);

		EagerAccount account = new EagerAccount();
		String name = "fwepfjewfew";
		account.name = name;
		assertEquals(1, accountDao.create(account));

		EagerOrder order1 = new EagerOrder();
		int val1 = 13123441;
		order1.val = val1;
		order1.account = account;
		assertEquals(1, orderDao.create(order1));

		EagerOrder order2 = new EagerOrder();
		int val2 = 113787097;
		order2.val = val2;
		order2.account = account;
		assertEquals(1, orderDao.create(order2));

		EagerAccount account2 = accountDao.queryForId(account.id);
		assertEquals(name, account2.name);
		assertNotNull(account2.orders);
		int orderC = 0;
		for (EagerOrder order : account2.orders) {
			orderC++;
			switch (orderC) {
				case 1:
					assertEquals(val1, order.val);
					break;
				case 2:
					assertEquals(val2, order.val);
					break;
			}
		}
		assertEquals(2, orderC);

		// insert it via the collection
		EagerOrder order3 = new EagerOrder();
		int val3 = 76557654;
		order3.val = val3;
		order3.account = account;
		account2.orders.add(order3);
		// the size should change immediately
		assertEquals(3, account2.orders.size());

		// now insert it behind the collections back
		EagerOrder order4 = new EagerOrder();
		int val4 = 1123587097;
		order4.val = val4;
		order4.account = account;
		assertEquals(1, orderDao.create(order4));
		// account2's collection should not have changed
		assertEquals(3, account2.orders.size());

		// now we refresh the collection
		assertEquals(1, accountDao.refresh(account2));
		assertEquals(name, account2.name);
		assertNotNull(account2.orders);
		orderC = 0;
		for (EagerOrder order : account2.orders) {
			orderC++;
			switch (orderC) {
				case 1:
					assertEquals(val1, order.val);
					break;
				case 2:
					assertEquals(val2, order.val);
					break;
				case 3:
					assertEquals(val3, order.val);
					break;
				case 4:
					assertEquals(val4, order.val);
					break;
			}
		}
		assertEquals(4, orderC);
	}

	@Test
	public void testBasicLazyCollection() throws Exception {
		Dao<LazyAccount, Integer> accountDao = createDao(LazyAccount.class, true);
		Dao<LazyOrder, Integer> orderDao = createDao(LazyOrder.class, true);

		LazyAccount account = new LazyAccount();
		String name = "fwepfjewfew";
		account.name = name;
		assertEquals(1, accountDao.create(account));

		LazyOrder order1 = new LazyOrder();
		int val1 = 13123441;
		order1.val = val1;
		order1.account = account;
		assertEquals(1, orderDao.create(order1));

		LazyOrder order2 = new LazyOrder();
		int val2 = 113787097;
		order2.val = val2;
		order2.account = account;
		assertEquals(1, orderDao.create(order2));

		LazyAccount account2 = accountDao.queryForId(account.id);
		assertEquals(name, account2.name);
		assertNotNull(account2.orders);
		int orderC = 0;
		for (LazyOrder order : account2.orders) {
			orderC++;
			switch (orderC) {
				case 1:
					assertEquals(val1, order.val);
					break;
				case 2:
					assertEquals(val2, order.val);
					break;
			}
		}
		assertEquals(2, orderC);

		// insert it via the collection
		LazyOrder order3 = new LazyOrder();
		int val3 = 76557654;
		order3.val = val3;
		order3.account = account;
		account2.orders.add(order3);
		orderC = 0;
		for (LazyOrder order : account2.orders) {
			orderC++;
			switch (orderC) {
				case 1:
					assertEquals(val1, order.val);
					break;
				case 2:
					assertEquals(val2, order.val);
					break;
				case 3:
					assertEquals(val3, order.val);
					break;
			}
		}
		assertEquals(3, orderC);

		// now insert it behind the collections back
		LazyOrder order4 = new LazyOrder();
		int val4 = 1123587097;
		order4.val = val4;
		order4.account = account;
		assertEquals(1, orderDao.create(order4));

		// without refreshing we should see the new order
		orderC = 0;
		for (LazyOrder order : account2.orders) {
			orderC++;
			switch (orderC) {
				case 1:
					assertEquals(val1, order.val);
					break;
				case 2:
					assertEquals(val2, order.val);
					break;
				case 3:
					assertEquals(val3, order.val);
					break;
				case 4:
					assertEquals(val4, order.val);
					break;
			}
		}
		assertEquals(4, orderC);
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testUseOfAndMany() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id = 1;
		foo.id = id;
		int val = 1231231;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		int notId = id + 1;
		foo.id = notId;
		foo.val = val + 1;
		assertEquals(1, dao.create(foo));

		Where<Foo, Integer> where = dao.queryBuilder().where();
		where.and(where.eq(Foo.VAL_FIELD_NAME, val), where.eq(Foo.ID_FIELD_NAME, id));

		List<Foo> results = where.query();
		assertEquals(1, results.size());
		assertEquals(id, results.get(0).id);

		// this should match none
		where.reset();
		where.and(where.eq(Foo.VAL_FIELD_NAME, val), where.eq(Foo.ID_FIELD_NAME, id),
				where.eq(Foo.ID_FIELD_NAME, notId));
		results = where.query();
		assertEquals(0, results.size());
	}

	@Test
	@SuppressWarnings("unchecked")
	public void testUseOfAndInt() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id = 1;
		foo.id = id;
		int val = 1231231;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		int notId = id + 1;
		foo.id = notId;
		foo.val = val + 1;
		assertEquals(1, dao.create(foo));

		Where<Foo, Integer> where = dao.queryBuilder().where();
		where.and(where.eq(Foo.VAL_FIELD_NAME, val), where.eq(Foo.ID_FIELD_NAME, id));

		List<Foo> results = where.query();
		assertEquals(1, results.size());
		assertEquals(id, results.get(0).id);

		// this should match none
		where.reset();
		where.eq(Foo.VAL_FIELD_NAME, val);
		where.eq(Foo.ID_FIELD_NAME, id);
		where.eq(Foo.ID_FIELD_NAME, notId);
		where.and(3);
		results = where.query();
		assertEquals(0, results.size());
	}

	@SuppressWarnings("unchecked")
	@Test
	public void testUseOfOrMany() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id = 1;
		foo.id = id;
		int val = 1231231;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		int notId = id + 1;
		foo.id = notId;
		foo.val = val + 1;
		assertEquals(1, dao.create(foo));

		Where<Foo, Integer> where = dao.queryBuilder().where();
		where.or(where.eq(Foo.ID_FIELD_NAME, id), where.eq(Foo.ID_FIELD_NAME, notId),
				where.eq(Foo.VAL_FIELD_NAME, val + 1), where.eq(Foo.VAL_FIELD_NAME, val + 1));

		List<Foo> results = where.query();
		assertEquals(2, results.size());
		assertEquals(id, results.get(0).id);
		assertEquals(notId, results.get(1).id);
	}

	@Test
	public void testUseOfOrInt() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id = 1;
		foo.id = id;
		int val = 1231231;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		int notId = id + 1;
		foo.id = notId;
		foo.val = val + 1;
		assertEquals(1, dao.create(foo));

		Where<Foo, Integer> where = dao.queryBuilder().where();
		where.eq(Foo.ID_FIELD_NAME, id);
		where.eq(Foo.ID_FIELD_NAME, notId);
		where.eq(Foo.VAL_FIELD_NAME, val + 1);
		where.eq(Foo.VAL_FIELD_NAME, val + 1);
		where.or(4);

		List<Foo> results = where.query();
		assertEquals(2, results.size());
		assertEquals(id, results.get(0).id);
		assertEquals(notId, results.get(1).id);
	}

	@Test
	public void testQueryForMatching() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id = 1;
		foo.id = id;
		int val = 1231231;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		int notId = id + 1;
		foo.id = notId;
		foo.val = val + 1;
		assertEquals(1, dao.create(foo));

		Foo match = new Foo();
		match.val = val;
		List<Foo> results = dao.queryForMatching(match);
		assertEquals(1, results.size());
		assertEquals(id, results.get(0).id);

		match = new Foo();
		match.id = notId;
		match.val = val;
		results = dao.queryForMatching(match);
		assertEquals(0, results.size());
	}

	@Test
	public void testQueryForFieldValues() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id = 1;
		foo.id = id;
		int val = 1231231;
		foo.val = val;
		assertEquals(1, dao.create(foo));
		int notId = id + 1;
		foo.id = notId;
		foo.val = val + 1;
		assertEquals(1, dao.create(foo));

		Map<String, Object> fieldValues = new HashMap<String, Object>();
		fieldValues.put(Foo.VAL_FIELD_NAME, val);
		List<Foo> results = dao.queryForFieldValues(fieldValues);
		assertEquals(1, results.size());
		assertEquals(id, results.get(0).id);

		fieldValues.put(Foo.ID_FIELD_NAME, notId);
		fieldValues.put(Foo.VAL_FIELD_NAME, val);
		results = dao.queryForFieldValues(fieldValues);
		assertEquals(0, results.size());
	}

	@Test
	public void testInsertAutoGeneratedId() throws Exception {
		Dao<Foo, Integer> dao1 = createDao(Foo.class, true);
		Dao<NotQuiteFoo, Integer> dao2 = createDao(NotQuiteFoo.class, false);
		Foo foo = new Foo();
		assertEquals(1, dao1.create(foo));
		NotQuiteFoo notQuiteFoo = new NotQuiteFoo();
		notQuiteFoo.id = foo.id + 1;
		assertEquals(1, dao2.create(notQuiteFoo));

		List<Foo> results = dao1.queryForAll();
		assertEquals(2, results.size());
		assertEquals(foo.id, results.get(0).id);
		assertEquals(notQuiteFoo.id, results.get(1).id);
	}

	@Test
	public void testCreateWithAllowGeneratedIdInsert() throws Exception {
		if (databaseType == null || !databaseType.isAllowGeneratedIdInsertSupported()) {
			return;
		}
		Dao<AllowGeneratedIdInsert, Integer> dao = createDao(AllowGeneratedIdInsert.class, true);
		AllowGeneratedIdInsert foo = new AllowGeneratedIdInsert();
		assertEquals(1, dao.create(foo));
		AllowGeneratedIdInsert result = dao.queryForId(foo.id);
		assertNotNull(result);
		assertEquals(foo.id, result.id);

		AllowGeneratedIdInsert foo2 = new AllowGeneratedIdInsert();
		assertEquals(1, dao.create(foo2));
		result = dao.queryForId(foo2.id);
		assertNotNull(result);
		assertEquals(foo2.id, result.id);
		assertFalse(foo2.id == foo.id);

		AllowGeneratedIdInsert foo3 = new AllowGeneratedIdInsert();
		foo3.id = 10002;
		assertEquals(1, dao.create(foo3));
		result = dao.queryForId(foo3.id);
		assertNotNull(result);
		assertEquals(foo3.id, result.id);
		assertFalse(foo3.id == foo.id);
		assertFalse(foo3.id == foo2.id);
	}

	@Test
	public void testCreateWithAllowGeneratedIdInsertObject() throws Exception {
		if (databaseType == null || !databaseType.isAllowGeneratedIdInsertSupported()) {
			return;
		}
		Dao<AllowGeneratedIdInsertObject, Integer> dao = createDao(AllowGeneratedIdInsertObject.class, true);
		AllowGeneratedIdInsertObject foo = new AllowGeneratedIdInsertObject();
		assertEquals(1, dao.create(foo));
		AllowGeneratedIdInsertObject result = dao.queryForId(foo.id);
		assertNotNull(result);
		assertEquals(foo.id, result.id);

		AllowGeneratedIdInsertObject foo2 = new AllowGeneratedIdInsertObject();
		assertEquals(1, dao.create(foo2));
		result = dao.queryForId(foo2.id);
		assertNotNull(result);
		assertEquals(foo2.id, result.id);
		assertFalse(foo2.id == foo.id);

		AllowGeneratedIdInsertObject foo3 = new AllowGeneratedIdInsertObject();
		foo3.id = 10002;
		assertEquals(1, dao.create(foo3));
		result = dao.queryForId(foo3.id);
		assertNotNull(result);
		assertEquals(foo3.id, result.id);
		assertFalse(foo3.id == foo.id);
		assertFalse(foo3.id == foo2.id);
	}

	@Test
	public void testCreateOrUpdate() throws Exception {
		Dao<NotQuiteFoo, Integer> dao = createDao(NotQuiteFoo.class, true);
		NotQuiteFoo foo1 = new NotQuiteFoo();
		foo1.stuff = "wow";
		CreateOrUpdateStatus status = dao.createOrUpdate(foo1);
		assertTrue(status.isCreated());
		assertFalse(status.isUpdated());
		assertEquals(1, status.getNumLinesChanged());

		String stuff2 = "4134132";
		foo1.stuff = stuff2;
		status = dao.createOrUpdate(foo1);
		assertFalse(status.isCreated());
		assertTrue(status.isUpdated());
		assertEquals(1, status.getNumLinesChanged());

		NotQuiteFoo result = dao.queryForId(foo1.id);
		assertEquals(stuff2, result.stuff);
	}

	@Test
	public void testCreateOrUpdateNull() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		CreateOrUpdateStatus status = dao.createOrUpdate(null);
		assertFalse(status.isCreated());
		assertFalse(status.isUpdated());
		assertEquals(0, status.getNumLinesChanged());
	}

	@Test
	public void testCreateOrUpdateNullId() throws Exception {
		Dao<CreateOrUpdateObjectId, Integer> dao = createDao(CreateOrUpdateObjectId.class, true);
		CreateOrUpdateObjectId foo = new CreateOrUpdateObjectId();
		String stuff = "21313";
		foo.stuff = stuff;
		CreateOrUpdateStatus status = dao.createOrUpdate(foo);
		assertTrue(status.isCreated());
		assertFalse(status.isUpdated());
		assertEquals(1, status.getNumLinesChanged());

		CreateOrUpdateObjectId result = dao.queryForId(foo.id);
		assertNotNull(result);
		assertEquals(stuff, result.stuff);

		String stuff2 = "pwojgfwe";
		foo.stuff = stuff2;
		dao.createOrUpdate(foo);

		result = dao.queryForId(foo.id);
		assertNotNull(result);
		assertEquals(stuff2, result.stuff);
	}

	@Test
	public void testUpdateNoChange() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		Foo foo = new Foo();
		foo.id = 13567567;
		foo.val = 1232131;
		assertEquals(1, dao.create(foo));
		assertEquals(1, dao.update(foo));
		assertEquals(1, dao.update(foo));
	}

	@Test
	public void testNullForeign() throws Exception {
		Dao<Order, Integer> orderDao = createDao(Order.class, true);

		int numOrders = 10;
		for (int orderC = 0; orderC < numOrders; orderC++) {
			Order order = new Order();
			order.val = orderC;
			assertEquals(1, orderDao.create(order));
		}

		List<Order> results = orderDao.queryBuilder().where().isNull(Order.ONE_FIELD_NAME).query();
		assertNotNull(results);
		assertEquals(numOrders, results.size());
	}

	@Test
	public void testSelfGeneratedIdPrimary() throws Exception {
		Dao<SelfGeneratedIdUuidPrimary, UUID> dao = createDao(SelfGeneratedIdUuidPrimary.class, true);
		SelfGeneratedIdUuidPrimary foo = new SelfGeneratedIdUuidPrimary();
		foo.stuff = "ewpfojwefjo";
		assertEquals(1, dao.create(foo));

		SelfGeneratedIdUuidPrimary result = dao.queryForId(foo.id);
		assertNotNull(result);
		assertEquals(foo.stuff, result.stuff);
	}

	@Test
	public void testCreateIfNotExists() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		String stuff = "stuff";
		foo1.stuff = stuff;

		Foo fooResult = dao.createIfNotExists(foo1);
		assertSame(foo1, fooResult);

		// now if we do it again, we should get the database copy of foo
		fooResult = dao.createIfNotExists(foo1);
		assertNotSame(foo1, fooResult);

		assertEquals(foo1.id, fooResult.id);
		assertEquals(foo1.stuff, fooResult.stuff);
	}

	@Test
	public void testCreateIfNotExistsNull() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		assertNull(dao.createIfNotExists(null));
	}

	@Test
	public void testCountOf() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		foo.id = 1;
		assertEquals(1, dao.create(foo));
		assertEquals(1, dao.countOf());
		foo.id = 2;
		assertEquals(1, dao.create(foo));
		assertEquals(2, dao.countOf());
	}

	@Test
	public void testCountOfPrepared() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		assertEquals(0, dao.countOf());
		Foo foo = new Foo();
		int id1 = 1;
		foo.id = id1;
		assertEquals(1, dao.create(foo));
		foo.id = 2;
		assertEquals(1, dao.create(foo));
		assertEquals(2, dao.countOf());

		QueryBuilder<Foo, String> qb = dao.queryBuilder();
		qb.setCountOf(true).where().eq(Foo.ID_FIELD_NAME, id1);
		assertEquals(1, dao.countOf(qb.prepare()));
	}

	@Test
	public void testCountOfPreparedNoCountOf() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		QueryBuilder<Foo, String> qb = dao.queryBuilder();
		try {
			dao.countOf(qb.prepare());
			fail("Should have thrown");
		} catch (IllegalArgumentException e) {
			// expected
		}
	}

	@Test
	public void testSelectRaw() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		Foo foo = new Foo();
		assertEquals(1, dao.create(foo));
		QueryBuilder<Foo, String> qb = dao.queryBuilder();
		qb.selectRaw("COUNT(*)");
		GenericRawResults<String[]> results = dao.queryRaw(qb.prepareStatementString());
		List<String[]> list = results.getResults();
		assertEquals(1, list.size());
		String[] array = list.get(0);
		assertEquals(1, array.length);
		assertEquals("1", array[0]);
	}

	@Test
	public void testSelectRawNotQuery() throws Exception {
		Dao<Foo, String> dao = createDao(Foo.class, true);
		Foo foo = new Foo();
		assertEquals(1, dao.create(foo));
		QueryBuilder<Foo, String> qb = dao.queryBuilder();
		qb.selectRaw("COUNTOF(*)");
		try {
			qb.query();
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testForeignAutoCreate() throws Exception {
		Dao<ForeignAutoCreate, Long> foreignAutoCreateDao = createDao(ForeignAutoCreate.class, true);
		Dao<ForeignAutoCreateForeign, Long> foreignAutoCreateForeignDao =
				createDao(ForeignAutoCreateForeign.class, true);

		List<ForeignAutoCreateForeign> results = foreignAutoCreateForeignDao.queryForAll();
		assertEquals(0, results.size());

		ForeignAutoCreateForeign foreign = new ForeignAutoCreateForeign();
		String stuff = "fopewjfpwejfpwjfw";
		foreign.stuff = stuff;

		ForeignAutoCreate foo1 = new ForeignAutoCreate();
		foo1.foreign = foreign;
		assertEquals(1, foreignAutoCreateDao.create(foo1));

		// we should not get something from the other dao
		results = foreignAutoCreateForeignDao.queryForAll();
		assertEquals(1, results.size());
		assertEquals(foreign.id, results.get(0).id);

		// if we get foo back, we should see the foreign-id
		List<ForeignAutoCreate> foreignAutoCreateResults = foreignAutoCreateDao.queryForAll();
		assertEquals(1, foreignAutoCreateResults.size());
		assertEquals(foo1.id, foreignAutoCreateResults.get(0).id);
		assertNotNull(foreignAutoCreateResults.get(0).foreign);
		assertEquals(foo1.foreign.id, foreignAutoCreateResults.get(0).foreign.id);

		// now we create it when the foreign field already has an id set
		ForeignAutoCreate foo2 = new ForeignAutoCreate();
		foo2.foreign = foreign;
		assertEquals(1, foreignAutoCreateDao.create(foo1));

		results = foreignAutoCreateForeignDao.queryForAll();
		// no additional results should be found
		assertEquals(1, results.size());
		assertEquals(foreign.id, results.get(0).id);
	}

	@Test
	public void testForeignNull() throws Exception {
		Dao<Foreign, Integer> dao = createDao(Foreign.class, true);
		Foreign foreign = new Foreign();
		foreign.foo = null;
		assertEquals(1, dao.create(foreign));
		Foreign foreign2 = dao.queryForId(foreign.id);
		assertNotNull(foreign2);
		assertNull(foreign2.foo);
	}

	@Test
	public void testForeignCantBeNull() throws Exception {
		Dao<ForeignNotNull, Integer> dao = createDao(ForeignNotNull.class, true);
		ForeignNotNull foreign = new ForeignNotNull();
		foreign.foo = null;
		try {
			dao.create(foreign);
			fail("Should have thrown");
		} catch (SQLException e) {
			// expected
		}
	}

	@Test
	public void testLimitOffset() throws Exception {
		if (databaseType == null || !databaseType.isOffsetSqlSupported()) {
			return;
		}
		final Dao<Foo, Object> dao = createDao(Foo.class, true);
		final int numPages = 10;
		final int numPerPage = 10;
		final List<Foo> foos = new ArrayList<Foo>();
		dao.callBatchTasks(new Callable<Void>() {
			@Override
			public Void call() throws Exception {
				for (int i = 0; i < numPages + numPerPage; i++) {
					Foo foo = new Foo();
					foos.add(foo);
					assertEquals(1, dao.create(foo));
				}
				return null;
			}
		});
		QueryBuilder<Foo, Object> qb = dao.queryBuilder();
		for (int pageC = 0; pageC < numPages; pageC++) {
			qb.limit((long) numPerPage);
			int offset = pageC * numPerPage;
			qb.offset((long) offset);
			List<Foo> results = qb.query();
			for (int i = 0; i < results.size(); i++) {
				assertEquals(foos.get(offset + i), results.get(i));
			}
		}
	}

	@Test
	public void testIteratorMove() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		Foo foo1 = new Foo();
		assertEquals(1, dao.create(foo1));
		Foo foo2 = new Foo();
		assertEquals(1, dao.create(foo2));
		Foo foo3 = new Foo();
		assertEquals(1, dao.create(foo3));

		CloseableIterator<Foo> iterator = dao.iterator(ResultSet.TYPE_SCROLL_INSENSITIVE);
		try {
			assertEquals(foo1, iterator.next());
			assertEquals(foo1, iterator.current());
			assertEquals(foo2, iterator.next());
			assertEquals(foo2, iterator.current());
			assertEquals(foo1, iterator.previous());
			assertEquals(foo2, iterator.next());
			assertEquals(foo3, iterator.next());
			assertEquals(foo1, iterator.first());
			assertEquals(foo3, iterator.moveRelative(2));
			assertEquals(foo3, iterator.moveRelative(0));
			assertEquals(foo2, iterator.moveRelative(-1));
			assertEquals(foo3, iterator.next());
			assertEquals(null, iterator.nextThrow());
		} finally {
			iterator.close();
		}
	}

	@Test
	public void testBasicCacheStuff() throws Exception {
		Dao<AllTypes, Integer> allTypesDao = createDao(AllTypes.class, true);
		allTypesDao.setObjectCache(true);
		Dao<ForeignWrapper, Integer> wrapperDao = createDao(ForeignWrapper.class, true);
		wrapperDao.setObjectCache(true);

		AllTypes allTypes1 = new AllTypes();
		assertEquals(1, allTypesDao.create(allTypes1));
		ForeignWrapper wrapper = new ForeignWrapper();
		wrapper.foreign = allTypes1;
		assertEquals(1, wrapperDao.create(wrapper));

		ForeignWrapper wrapperResult = wrapperDao.queryForId(wrapper.id);
		assertSame(wrapper, wrapperResult);
		AllTypes allTypesResult = allTypesDao.queryForId(allTypes1.id);
		assertSame(allTypes1, allTypesResult);
	}

	@Test
	public void testForeignColumnName() throws Exception {
		Dao<ForeignColumnName, Integer> dao = createDao(ForeignColumnName.class, true);
		Dao<ForeignColumnNameForeign, Integer> foreignDao = createDao(ForeignColumnNameForeign.class, true);

		ForeignColumnNameForeign foreign = new ForeignColumnNameForeign();
		foreign.name = "Buzz Lightyear";
		assertEquals(1, foreignDao.create(foreign));

		ForeignColumnName fcn = new ForeignColumnName();
		fcn.foreign = foreign;
		assertEquals(1, dao.create(fcn));

		ForeignColumnName result = dao.queryForId(fcn.id);
		assertNotNull(result);
		assertEquals(foreign.id, result.foreign.id);
		assertEquals(foreign.name, result.foreign.name);

		assertEquals(1, foreignDao.refresh(result.foreign));
	}

	@Test
	public void testVersionField() throws Exception {
		Dao<VersionField, Integer> dao = createDao(VersionField.class, true);

		VersionField foo1 = new VersionField();
		assertEquals(1, dao.create(foo1));

		assertEquals(1, foo1.id);
		assertEquals(0, foo1.version);

		assertEquals(1, dao.update(foo1));
		assertEquals(1, foo1.version);

		assertEquals(1, dao.update(foo1));
		assertEquals(2, foo1.version);

		VersionField result = dao.queryForId(foo1.id);
		// we update this one to a new version number
		assertEquals(1, dao.update(result));
		assertEquals(3, result.version);

		// the old one doesn't change
		assertEquals(2, foo1.version);
		// but when we try to update the earlier foo, the version doesn't match
		assertEquals(0, dao.update(foo1));
	}

	@Test
	public void testVersionFieldInsertOrUpdate() throws Exception {
		Dao<VersionField, Integer> dao = createDao(VersionField.class, true);

		VersionField foo1 = new VersionField();
		assertEquals(1, dao.create(foo1));

		assertEquals(1, foo1.id);
		assertEquals(0, foo1.version);

		CreateOrUpdateStatus status = dao.createOrUpdate(foo1);
		assertTrue(status.isUpdated());
		assertEquals(1, status.getNumLinesChanged());
		assertEquals(1, foo1.version);

		status = dao.createOrUpdate(foo1);
		assertTrue(status.isUpdated());
		assertEquals(1, status.getNumLinesChanged());
		assertEquals(2, foo1.version);

		VersionField result = dao.queryForId(foo1.id);
		// we update this one to a new version number
		assertEquals(1, dao.update(result));
		assertEquals(3, result.version);

		// the old one doesn't change
		assertEquals(2, foo1.version);
		// but when we try to update the earlier foo, the version doesn't match
		assertEquals(0, dao.update(foo1));
	}

	@Test
	public void testAutoCommitClose() throws Exception {
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		DatabaseConnection conn = null;
		try {
			conn = dao.startThreadConnection();
			dao.setAutoCommit(conn, false);

			Foo foo = new Foo();
			assertEquals(1, dao.create(foo));
			List<Foo> results = dao.queryForAll();
			assertEquals(1, results.size());

			try {
				closeConnectionSource();
			} catch (SQLException e) {
				// ignore any exceptions (stupid derby)
			}
			conn = null;
			DaoManager.clearCache();
			openConnectionSource();

			dao = createDao(Foo.class, true);

			results = dao.queryForAll();
			// we expect there to be no results because we closed the connection to the database before a commit
			// happened
			assertEquals(0, results.size());
		} finally {
			dao.endThreadConnection(conn);
		}
	}

	@Test
	public void testConnectionMethods() throws Exception {
		if (!AUTO_COMMIT_SUPPORTED) {
			return;
		}
		Dao<Foo, Integer> dao = createDao(Foo.class, true);
		DatabaseConnection conn = null;
		try {
			conn = dao.startThreadConnection();
			assertTrue(dao.isAutoCommit(conn));
			dao.setAutoCommit(conn, false);
			assertFalse(dao.isAutoCommit(conn));

			Foo foo = new Foo();
			assertEquals(1, dao.create(foo));
			assertNotNull(dao.queryForId(foo.id));

			dao.rollBack(conn);
			assertNull(dao.queryForId(foo.id));

			foo = new Foo();
			assertEquals(1, dao.create(foo));
			assertNotNull(dao.queryForId(foo.id));

			dao.commit(conn);
			assertNotNull(dao.queryForId(foo.id));

			dao.rollBack(conn);
			assertNotNull(dao.queryForId(foo.id));

		} finally {
			if (conn != null) {
				dao.setAutoCommit(conn, true);
				dao.endThreadConnection(conn);
			}
		}
	}

	@Test
	public void testAutoCommit() throws Exception {
		if (!AUTO_COMMIT_SUPPORTED) {
			return;
		}
		final Dao<Foo, Integer> dao = createDao(Foo.class, true);
		DatabaseConnection conn1 = null;
		try {
			conn1 = dao.startThreadConnection();
			assertTrue(dao.isAutoCommit(conn1));
			dao.setAutoCommit(conn1, false);
			assertFalse(dao.isAutoCommit(conn1));

			final Foo foo = new Foo();
			assertEquals(1, dao.create(foo));
			assertNotNull(dao.queryForId(foo.id));

			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						DatabaseConnection conn2 = dao.startThreadConnection();
						try {
							assertNotNull(dao.queryForId(foo.id));
						} finally {
							if (conn2 != null) {
								dao.endThreadConnection(conn2);
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}).start();

		} finally {
			if (conn1 != null) {
				dao.setAutoCommit(conn1, true);
				dao.endThreadConnection(conn1);
			}
		}
	}

	@Test
	public void testFewFields() throws Exception {
		Dao<FewFields, Object> dao = createDao(FewFields.class, true);
		FewFields few = new FewFields();
		assertEquals(1, dao.create(few));

		FewFields result = dao.queryForId(few.id);
		assertNotNull(result);
	}

	/* ==================================================================================== */

	private <T extends TestableType<ID>, ID> void checkTypeAsId(Class<T> clazz, ID id1, ID id2) throws Exception {
		Constructor<T> constructor = clazz.getDeclaredConstructor();
		Dao<T, ID> dao = createDao(clazz, true);

		String s1 = "stuff";
		T data1 = constructor.newInstance();
		data1.setId(id1);
		data1.setStuff(s1);

		// create it
		assertEquals(1, dao.create(data1));
		// refresh it
		assertEquals(1, dao.refresh(data1));

		// now we query for foo from the database to make sure it was persisted right
		T data2 = dao.queryForId(id1);
		assertNotNull(data2);
		assertEquals(id1, data2.getId());
		assertEquals(s1, data2.getStuff());

		// now we update 1 row in a the database after changing stuff
		String s2 = "stuff2";
		data2.setStuff(s2);
		assertEquals(1, dao.update(data2));

		// now we get it from the db again to make sure it was updated correctly
		T data3 = dao.queryForId(id1);
		assertEquals(s2, data3.getStuff());

		// change its id
		assertEquals(1, dao.updateId(data2, id2));
		// the old id should not exist
		assertNull(dao.queryForId(id1));
		T data4 = dao.queryForId(id2);
		assertNotNull(data4);
		assertEquals(s2, data4.getStuff());

		// delete it
		assertEquals(1, dao.delete(data2));
		// should not find it
		assertNull(dao.queryForId(id1));
		assertNull(dao.queryForId(id2));

		// create data1 and data2
		data1.setId(id1);
		assertEquals(1, dao.create(data1));
		data2 = constructor.newInstance();
		data2.setId(id2);
		assertEquals(1, dao.create(data2));

		data3 = dao.queryForId(id1);
		assertNotNull(data3);
		assertEquals(id1, data3.getId());
		data4 = dao.queryForId(id2);
		assertNotNull(data4);
		assertEquals(id2, data4.getId());

		// delete a collection of ids
		List<ID> idList = new ArrayList<ID>();
		idList.add(id1);
		idList.add(id2);
		assertEquals(2, dao.deleteIds(idList));
		assertNull(dao.queryForId(id1));
		assertNull(dao.queryForId(id2));

		// delete a collection of objects
		assertEquals(1, dao.create(data1));
		assertEquals(1, dao.create(data2));
		List<T> dataList = new ArrayList<T>();
		dataList.add(data1);
		dataList.add(data2);
		assertEquals(2, dao.delete(dataList));

		assertNull(dao.queryForId(id1));
		assertNull(dao.queryForId(id2));
	}

	/**
	 * Returns the object if the query failed or null otherwise.
	 */
	private boolean checkQueryResult(Dao<AllTypes, Integer> allDao, QueryBuilder<AllTypes, Integer> qb,
			AllTypes allTypes, String fieldName, Object value, boolean required) throws SQLException {
		qb.where().eq(fieldName, value);
		List<AllTypes> results = allDao.query(qb.prepare());
		if (required) {
			assertEquals(1, results.size());
			assertTrue(allDao.objectsEqual(allTypes, results.get(0)));
		} else if (results.size() == 1) {
			assertTrue(allDao.objectsEqual(allTypes, results.get(0)));
		} else {
			return false;
		}

		SelectArg selectArg = new SelectArg();
		qb.where().eq(fieldName, selectArg);
		selectArg.setValue(value);
		results = allDao.query(qb.prepare());
		assertEquals(1, results.size());
		assertTrue(allDao.objectsEqual(allTypes, results.get(0)));
		return true;
	}

	private String buildFooQueryAllString(Dao<Foo, Object> fooDao) throws SQLException {
		String queryString = fooDao.queryBuilder()
				.selectColumns(Foo.ID_FIELD_NAME, Foo.STUFF_FIELD_NAME, Foo.VAL_FIELD_NAME)
				.prepareStatementString();
		return queryString;
	}

	private interface TestableType<ID> {
		String getStuff();

		void setStuff(String stuff);

		ID getId();

		void setId(ID id);
	}

	private static class Mapper implements RawRowMapper<Foo> {
		@Override
		public Foo mapRow(String[] columnNames, String[] resultColumns) {
			Foo foo = new Foo();
			for (int i = 0; i < columnNames.length; i++) {
				if (columnNames[i].equalsIgnoreCase(Foo.ID_FIELD_NAME)) {
					foo.id = Integer.parseInt(resultColumns[i]);
				} else if (columnNames[i].equalsIgnoreCase(Foo.STUFF_FIELD_NAME)) {
					foo.stuff = resultColumns[i];
				} else if (columnNames[i].equalsIgnoreCase(Foo.VAL_FIELD_NAME)) {
					foo.val = Integer.parseInt(resultColumns[i]);
				}
			}
			return foo;
		}
	}

	/* ==================================================================================== */

	@DatabaseTable(tableName = FOO_TABLE_NAME)
	protected static class Foo {
		public final static String ID_FIELD_NAME = "id";
		public final static String STUFF_FIELD_NAME = "stuff";
		public final static String VAL_FIELD_NAME = "val";

		@DatabaseField(generatedId = true, columnName = ID_FIELD_NAME)
		public int id;
		@DatabaseField(columnName = STUFF_FIELD_NAME)
		public String stuff;
		@DatabaseField(columnName = VAL_FIELD_NAME)
		public int val;

		public Foo() {
		}

		@Override
		public boolean equals(Object other) {
			if (other == null || other.getClass() != getClass())
				return false;
			return id == ((Foo) other).id;
		}

		@Override
		public int hashCode() {
			return id;
		}

		@Override
		public String toString() {
			return "Foo.id=" + id;
		}
	}

	@DatabaseTable(tableName = FOO_TABLE_NAME)
	protected static class NotQuiteFoo {
		@DatabaseField(id = true, columnName = Foo.ID_FIELD_NAME)
		public int id;
		@DatabaseField(columnName = Foo.STUFF_FIELD_NAME)
		public String stuff;
		@DatabaseField(columnName = Foo.VAL_FIELD_NAME)
		public int val;

		public NotQuiteFoo() {
		}
	}

	protected static class DoubleCreate {
		@DatabaseField(id = true)
		int id;
	}

	protected static class NoId {
		@DatabaseField
		public String notId;
	}

	private static class JustId {
		@DatabaseField(id = true)
		public String id;
	}

	private static class ForeignWrapper {
		private final static String FOREIGN_FIELD_NAME = "foreign";
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(foreign = true, columnName = FOREIGN_FIELD_NAME)
		AllTypes foreign;
	}

	private static class MultipleForeignWrapper {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(foreign = true)
		AllTypes foreign;
		@DatabaseField(foreign = true)
		ForeignWrapper foreignWrapper;
	}

	protected static class GetSet {
		@DatabaseField(generatedId = true, useGetSet = true)
		private int id;
		@DatabaseField(useGetSet = true)
		private String stuff;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public String getStuff() {
			return stuff;
		}

		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	protected static class NoAnno {
		public int id;
		public String stuff;

		public NoAnno() {
		}
	}

	protected static class NoAnnoFor {
		public int id;
		public NoAnno foreign;

		public NoAnnoFor() {
		}
	}

	protected static class GeneratedIdNotNull {
		@DatabaseField(generatedId = true, canBeNull = false)
		public int id;
		@DatabaseField
		public String stuff;

		public GeneratedIdNotNull() {
		}
	}

	protected static class Basic {
		public final static String ID_FIELD = "id";
		@DatabaseField(id = true, columnName = ID_FIELD)
		String id;
	}

	private static class DefaultValue {
		@DatabaseField(defaultValue = DEFAULT_VALUE_STRING)
		Integer intField;

		DefaultValue() {
		}
	}

	protected static class NotNull {
		@DatabaseField(canBeNull = false)
		String notNull;

		NotNull() {
		}
	}

	protected static class GeneratedId {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String other;

		public GeneratedId() {
		}
	}

	protected static class AllTypes {
		public static final String STRING_FIELD_NAME = "stringField";
		public static final String BOOLEAN_FIELD_NAME = "booleanField";
		public static final String DATE_FIELD_NAME = "dateField";
		public static final String DATE_LONG_FIELD_NAME = "dateLongField";
		public static final String DATE_STRING_FIELD_NAME = "dateStringField";
		public static final String SERIAL_FIELD_NAME = "serialField";
		public static final String CHAR_FIELD_NAME = "charField";
		public static final String BYTE_FIELD_NAME = "byteField";
		public static final String SHORT_FIELD_NAME = "shortField";
		public static final String INT_FIELD_NAME = "intField";
		public static final String LONG_FIELD_NAME = "longField";
		public static final String FLOAT_FIELD_NAME = "floatField";
		public static final String DOUBLE_FIELD_NAME = "doubleField";
		public static final String ENUM_FIELD_NAME = "enumField";
		public static final String ENUM_STRING_FIELD_NAME = "enumStringField";
		public static final String ENUM_INTEGER_FIELD_NAME = "enumIntegerField";
		public static final String UUID_FIELD_NAME = "uuid";
		public static final String BIG_INTEGER_FIELD_NAME = "bigInteger";
		public static final String BIG_DECIMAL_FIELD_NAME = "bigDecimal";
		public static final String BIG_DECIMAL_NUMERIC_FIELD_NAME = "bigDecimalNumeric";
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(columnName = STRING_FIELD_NAME)
		String stringField;
		@DatabaseField(columnName = BOOLEAN_FIELD_NAME)
		boolean booleanField;
		@DatabaseField(columnName = DATE_FIELD_NAME)
		Date dateField;
		@DatabaseField(columnName = DATE_LONG_FIELD_NAME, dataType = DataType.DATE_LONG)
		Date dateLongField;
		@DatabaseField(columnName = DATE_STRING_FIELD_NAME, dataType = DataType.DATE_STRING,
				format = DEFAULT_DATE_STRING_FORMAT)
		Date dateStringField;
		@DatabaseField(columnName = CHAR_FIELD_NAME)
		char charField;
		@DatabaseField(columnName = BYTE_FIELD_NAME)
		byte byteField;
		@DatabaseField(columnName = SHORT_FIELD_NAME)
		short shortField;
		@DatabaseField(columnName = INT_FIELD_NAME)
		int intField;
		@DatabaseField(columnName = LONG_FIELD_NAME)
		long longField;
		@DatabaseField(columnName = FLOAT_FIELD_NAME)
		float floatField;
		@DatabaseField(columnName = DOUBLE_FIELD_NAME)
		double doubleField;
		@DatabaseField(columnName = SERIAL_FIELD_NAME, dataType = DataType.SERIALIZABLE)
		SerialData serialField;
		@DatabaseField(columnName = ENUM_FIELD_NAME)
		OurEnum enumField;
		@DatabaseField(columnName = ENUM_STRING_FIELD_NAME, dataType = DataType.ENUM_STRING)
		OurEnum enumStringField;
		@DatabaseField(columnName = ENUM_INTEGER_FIELD_NAME, dataType = DataType.ENUM_INTEGER)
		OurEnum enumIntegerField;
		@DatabaseField(columnName = UUID_FIELD_NAME)
		UUID uuid;
		@DatabaseField(columnName = BIG_INTEGER_FIELD_NAME)
		BigInteger bigInteger;
		@DatabaseField(columnName = BIG_DECIMAL_FIELD_NAME)
		BigDecimal bigDecimal;
		@DatabaseField(columnName = BIG_DECIMAL_NUMERIC_FIELD_NAME, dataType = DataType.BIG_DECIMAL_NUMERIC)
		BigDecimal bigDecimalNumeric;

		AllTypes() {
		}
	}

	protected static class AllTypesDefault {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(defaultValue = DEFAULT_STRING_VALUE)
		String stringField;
		@DatabaseField(defaultValue = DEFAULT_DATE_VALUE)
		Date dateField;
		@DatabaseField(dataType = DataType.DATE_LONG, defaultValue = DEFAULT_DATE_LONG_VALUE)
		Date dateLongField;
		@DatabaseField(dataType = DataType.DATE_STRING, defaultValue = DEFAULT_DATE_STRING_VALUE,
				format = DEFAULT_DATE_STRING_FORMAT)
		Date dateStringField;
		@DatabaseField(defaultValue = DEFAULT_BOOLEAN_VALUE)
		boolean booleanField;
		@DatabaseField(defaultValue = DEFAULT_BOOLEAN_VALUE)
		Boolean booleanObj;
		@DatabaseField(defaultValue = DEFAULT_BYTE_VALUE)
		byte byteField;
		@DatabaseField(defaultValue = DEFAULT_BYTE_VALUE)
		Byte byteObj;
		@DatabaseField(defaultValue = DEFAULT_SHORT_VALUE)
		short shortField;
		@DatabaseField(defaultValue = DEFAULT_SHORT_VALUE)
		Short shortObj;
		@DatabaseField(defaultValue = DEFAULT_INT_VALUE)
		int intField;
		@DatabaseField(defaultValue = DEFAULT_INT_VALUE)
		Integer intObj;
		@DatabaseField(defaultValue = DEFAULT_LONG_VALUE)
		long longField;
		@DatabaseField(defaultValue = DEFAULT_LONG_VALUE)
		Long longObj;
		@DatabaseField(defaultValue = DEFAULT_FLOAT_VALUE)
		float floatField;
		@DatabaseField(defaultValue = DEFAULT_FLOAT_VALUE)
		Float floatObj;
		@DatabaseField(defaultValue = DEFAULT_DOUBLE_VALUE)
		double doubleField;
		@DatabaseField(defaultValue = DEFAULT_DOUBLE_VALUE)
		Double doubleObj;
		@DatabaseField(dataType = DataType.SERIALIZABLE)
		SerialData objectField;
		@DatabaseField(defaultValue = DEFAULT_ENUM_VALUE)
		OurEnum ourEnum;
		@DatabaseField(defaultValue = DEFAULT_ENUM_NUMBER_VALUE, dataType = DataType.ENUM_INTEGER)
		OurEnum ourEnumNumber;

		AllTypesDefault() {
		}
	}

	protected static class BooleanDefault {
		@DatabaseField(defaultValue = DEFAULT_BOOLEAN_VALUE)
		boolean booleanField;
		@DatabaseField(defaultValue = DEFAULT_BOOLEAN_VALUE)
		Boolean booleanObj;

		BooleanDefault() {
		}
	}

	protected static class AllObjectTypes {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String stringField;
		@DatabaseField
		Boolean booleanField;
		@DatabaseField
		Date dateField;
		@DatabaseField
		Byte byteField;
		@DatabaseField
		Short shortField;
		@DatabaseField
		Integer intField;
		@DatabaseField
		Long longField;
		@DatabaseField
		Float floatField;
		@DatabaseField
		Double doubleField;
		@DatabaseField(dataType = DataType.SERIALIZABLE)
		SerialData objectField;
		@DatabaseField
		OurEnum ourEnum;

		AllObjectTypes() {
		}
	}

	protected static class NumberTypes {
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField
		public byte byteField;
		@DatabaseField
		public short shortField;
		@DatabaseField
		public int intField;
		@DatabaseField
		public long longField;
		@DatabaseField
		public float floatField;
		@DatabaseField
		public double doubleField;

		public NumberTypes() {
		}
	}

	protected static class StringWidth {
		@DatabaseField(width = ALL_TYPES_STRING_WIDTH)
		String stringField;

		StringWidth() {
		}
	}

	// for testing reserved table names as fields
	private static class Create {
		@DatabaseField(id = true)
		public String id;
	}

	// for testing reserved words as field names
	protected static class ReservedField {
		public static final String GROUP_FIELD = "group";
		@DatabaseField(id = true)
		public int select;
		@DatabaseField
		public String from;
		@DatabaseField
		public String table;
		@DatabaseField
		public String where;
		@DatabaseField(columnName = GROUP_FIELD)
		public String group;
		@DatabaseField
		public String order;
		@DatabaseField
		public String values;

		public ReservedField() {
		}
	}

	// test the field name that has a capital letter in it
	protected static class GeneratedColumnCapital {
		@DatabaseField(generatedId = true, columnName = "idCap")
		int id;
		@DatabaseField
		String other;

		public GeneratedColumnCapital() {
		}
	}

	protected static class ObjectHolder {
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField(dataType = DataType.SERIALIZABLE)
		public SerialData obj;
		@DatabaseField(dataType = DataType.SERIALIZABLE)
		public String strObj;

		public ObjectHolder() {
		}
	}

	protected static class NotSerializable {
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField(dataType = DataType.SERIALIZABLE)
		public ObjectHolder obj;

		public NotSerializable() {
		}
	}

	protected static class SerialData implements Serializable {
		private static final long serialVersionUID = -3883857119616908868L;
		public Map<String, String> map;

		public SerialData() {
		}

		public void addEntry(String key, String value) {
			if (map == null) {
				map = new HashMap<String, String>();
			}
			map.put(key, value);
		}

		@Override
		public int hashCode() {
			if (map == null) {
				return 0;
			} else {
				return map.hashCode();
			}
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null || obj.getClass() != getClass()) {
				return false;
			}
			SerialData other = (SerialData) obj;
			if (map == null) {
				return other.map == null;
			} else {
				return map.equals(other.map);
			}
		}
	}

	@DatabaseTable(tableName = ENUM_TABLE_NAME)
	protected static class LocalEnumString {
		@DatabaseField
		OurEnum ourEnum;
	}

	@DatabaseTable(tableName = ENUM_TABLE_NAME)
	protected static class LocalEnumString2 {
		@DatabaseField
		OurEnum2 ourEnum;
	}

	@DatabaseTable(tableName = ENUM_TABLE_NAME)
	protected static class LocalEnumInt {
		@DatabaseField(dataType = DataType.ENUM_INTEGER)
		OurEnum ourEnum;
	}

	@DatabaseTable(tableName = ENUM_TABLE_NAME)
	protected static class LocalEnumInt2 {
		@DatabaseField(dataType = DataType.ENUM_INTEGER)
		OurEnum2 ourEnum;
	}

	@DatabaseTable(tableName = ENUM_TABLE_NAME)
	protected static class LocalEnumInt3 {
		@DatabaseField(dataType = DataType.ENUM_INTEGER, unknownEnumName = "FIRST")
		OurEnum2 ourEnum;
	}

	private enum OurEnum {
		FIRST,
		SECOND,
		// end
		;
	}

	private enum OurEnum2 {
		FIRST,
		// end
		;
	}

	@DatabaseTable(tableName = NULL_BOOLEAN_TABLE_NAME)
	protected static class NullBoolean1 {
		@DatabaseField
		Boolean val;
	}

	@DatabaseTable(tableName = NULL_BOOLEAN_TABLE_NAME)
	protected static class NullBoolean2 {
		@DatabaseField(throwIfNull = true)
		boolean val;
	}

	@DatabaseTable(tableName = NULL_INT_TABLE_NAME)
	protected static class NullInt1 {
		@DatabaseField
		Integer val;
	}

	@DatabaseTable(tableName = NULL_INT_TABLE_NAME)
	protected static class NullInt2 {
		@DatabaseField(throwIfNull = true)
		int val;
	}

	@DatabaseTable
	protected static class NotNullDefault {
		@DatabaseField(canBeNull = false, defaultValue = "3")
		String stuff;
	}

	@DatabaseTable
	protected static class Unique {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String stuff;
		@DatabaseField(unique = true)
		String uniqueStuff;
	}

	@DatabaseTable
	protected static class DoubleUnique {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(unique = true)
		String stuff;
		@DatabaseField(unique = true)
		String uniqueStuff;
	}

	@DatabaseTable
	protected static class DoubleUniqueCombo {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(uniqueCombo = true)
		String stuff;
		@DatabaseField(uniqueCombo = true)
		String uniqueStuff;
	}

	@DatabaseTable
	protected static class UniqueAndUniqueCombo {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(unique = true)
		String unique1;
		@DatabaseField(uniqueCombo = true)
		String combo1;
		@DatabaseField(uniqueCombo = true)
		String combo2;
	}

	@DatabaseTable
	protected static class StringDefalt {
		@DatabaseField(defaultValue = "3")
		String stuff;
	}

	@DatabaseTable
	protected static class LocalDate {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		Date date;
	}

	@DatabaseTable
	protected static class StringId implements TestableType<String> {
		@DatabaseField(id = true)
		String id;
		@DatabaseField
		String stuff;

		@Override
		public String getId() {
			return id;
		}

		@Override
		public void setId(String id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class LongStringId implements TestableType<String> {
		@DatabaseField(id = true, dataType = DataType.LONG_STRING)
		String id;
		@DatabaseField
		String stuff;

		@Override
		public String getId() {
			return id;
		}

		@Override
		public void setId(String id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class BooleanId implements TestableType<Boolean> {
		@DatabaseField(id = true)
		boolean id;
		@DatabaseField
		String stuff;

		@Override
		public Boolean getId() {
			return id;
		}

		@Override
		public void setId(Boolean bool) {
			this.id = bool;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class BooleanObjId implements TestableType<Boolean> {
		@DatabaseField(id = true)
		Boolean id;
		@DatabaseField
		String stuff;

		@Override
		public Boolean getId() {
			return id;
		}

		@Override
		public void setId(Boolean bool) {
			this.id = bool;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class DateId implements TestableType<Date> {
		@DatabaseField(id = true)
		Date id;
		@DatabaseField
		String stuff;

		@Override
		public Date getId() {
			return id;
		}

		@Override
		public void setId(Date id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class DateLongId implements TestableType<Date> {
		@DatabaseField(id = true, dataType = DataType.DATE_LONG)
		Date id;
		@DatabaseField
		String stuff;

		@Override
		public Date getId() {
			return id;
		}

		@Override
		public void setId(Date id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class DateStringId implements TestableType<Date> {
		@DatabaseField(id = true, dataType = DataType.DATE_STRING)
		Date id;
		@DatabaseField
		String stuff;

		@Override
		public Date getId() {
			return id;
		}

		@Override
		public void setId(Date id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class ByteId implements TestableType<Byte> {
		@DatabaseField(id = true)
		byte id;
		@DatabaseField
		String stuff;

		@Override
		public Byte getId() {
			return id;
		}

		@Override
		public void setId(Byte id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class ByteObjId implements TestableType<Byte> {
		@DatabaseField(id = true)
		Byte id;
		@DatabaseField
		String stuff;

		@Override
		public Byte getId() {
			return id;
		}

		@Override
		public void setId(Byte id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class ShortId implements TestableType<Short> {
		@DatabaseField(id = true)
		short id;
		@DatabaseField
		String stuff;

		@Override
		public Short getId() {
			return id;
		}

		@Override
		public void setId(Short id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class ShortObjId implements TestableType<Short> {
		@DatabaseField(id = true)
		Short id;
		@DatabaseField
		String stuff;

		@Override
		public Short getId() {
			return id;
		}

		@Override
		public void setId(Short id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class IntId implements TestableType<Integer> {
		@DatabaseField(id = true)
		int id;
		@DatabaseField
		String stuff;

		@Override
		public Integer getId() {
			return id;
		}

		@Override
		public void setId(Integer id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class IntObjId implements TestableType<Integer> {
		@DatabaseField(id = true)
		Integer id;
		@DatabaseField
		String stuff;

		@Override
		public Integer getId() {
			return id;
		}

		@Override
		public void setId(Integer id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class LongId implements TestableType<Long> {
		@DatabaseField(id = true)
		long id;
		@DatabaseField
		String stuff;

		@Override
		public Long getId() {
			return id;
		}

		@Override
		public void setId(Long id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class LongObjId implements TestableType<Long> {
		@DatabaseField(id = true)
		Long id;
		@DatabaseField
		String stuff;

		@Override
		public Long getId() {
			return id;
		}

		@Override
		public void setId(Long id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class FloatId implements TestableType<Float> {
		@DatabaseField(id = true)
		float id;
		@DatabaseField
		String stuff;

		@Override
		public Float getId() {
			return id;
		}

		@Override
		public void setId(Float id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class FloatObjId implements TestableType<Float> {
		@DatabaseField(id = true)
		Float id;
		@DatabaseField
		String stuff;

		@Override
		public Float getId() {
			return id;
		}

		@Override
		public void setId(Float id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class DoubleId implements TestableType<Double> {
		@DatabaseField(id = true)
		double id;
		@DatabaseField
		String stuff;

		@Override
		public Double getId() {
			return id;
		}

		@Override
		public void setId(Double id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class DoubleObjId implements TestableType<Double> {
		@DatabaseField(id = true)
		Double id;
		@DatabaseField
		String stuff;

		@Override
		public Double getId() {
			return id;
		}

		@Override
		public void setId(Double id) {
			this.id = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class EnumId implements TestableType<OurEnum> {
		@DatabaseField(id = true)
		OurEnum ourEnum;
		@DatabaseField
		String stuff;

		@Override
		public OurEnum getId() {
			return ourEnum;
		}

		@Override
		public void setId(OurEnum id) {
			this.ourEnum = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class EnumStringId implements TestableType<OurEnum> {
		@DatabaseField(id = true, dataType = DataType.ENUM_STRING)
		OurEnum ourEnum;
		@DatabaseField
		String stuff;

		@Override
		public OurEnum getId() {
			return ourEnum;
		}

		@Override
		public void setId(OurEnum id) {
			this.ourEnum = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class EnumIntegerId implements TestableType<OurEnum> {
		@DatabaseField(id = true, dataType = DataType.ENUM_INTEGER)
		OurEnum ourEnum;
		@DatabaseField
		String stuff;

		@Override
		public OurEnum getId() {
			return ourEnum;
		}

		@Override
		public void setId(OurEnum id) {
			this.ourEnum = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class SerializableId implements TestableType<SerialData> {
		@DatabaseField(id = true, dataType = DataType.SERIALIZABLE)
		SerialData serial;
		@DatabaseField
		String stuff;

		@Override
		public SerialData getId() {
			return serial;
		}

		@Override
		public void setId(SerialData id) {
			this.serial = id;
		}

		@Override
		public String getStuff() {
			return stuff;
		}

		@Override
		public void setStuff(String stuff) {
			this.stuff = stuff;
		}
	}

	@DatabaseTable
	protected static class Recursive {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(foreign = true)
		Recursive foreign;

		public Recursive() {
		}
	}

	@DatabaseTable
	protected static class SerializedBytes {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(dataType = DataType.SERIALIZABLE)
		byte[] bytes;

		public SerializedBytes() {
		}
	}

	@DatabaseTable
	protected static class ByteArray {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(dataType = DataType.BYTE_ARRAY)
		byte[] bytes;

		public ByteArray() {
		}
	}

	@DatabaseTable
	protected static class Index {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(index = true)
		String stuff;

		public Index() {
		}
	}

	@DatabaseTable
	protected static class IndexColumnName {
		public static final String STUFF_COLUMN_NAME = "notStuff";
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(index = true, columnName = STUFF_COLUMN_NAME)
		String stuff;

		public IndexColumnName() {
		}
	}

	@DatabaseTable
	protected static class UniqueIndex {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(uniqueIndex = true)
		String stuff;

		public UniqueIndex() {
		}
	}

	@DatabaseTable
	protected static class ComboIndex {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(indexName = "stuffjunk")
		String stuff;
		@DatabaseField(indexName = "stuffjunk")
		long junk;

		public ComboIndex() {
		}
	}

	@DatabaseTable
	protected static class ComboUniqueIndex {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(uniqueIndexName = "stuffjunk")
		String stuff;
		@DatabaseField(uniqueIndexName = "stuffjunk")
		long junk;

		public ComboUniqueIndex() {
		}
	}

	@DatabaseTable
	protected static class LongVarChar {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(dataType = DataType.LONG_STRING)
		String stuff;

		public LongVarChar() {
		}
	}

	protected static class Base {
		@DatabaseField(id = true)
		int id;

		public Base() {
			// for ormlite
		}
	}

	protected static class Sub extends Base {
		@DatabaseField
		String stuff;

		public Sub() {
			// for ormlite
		}
	}

	protected static class UuidGeneratedId {
		@DatabaseField(generatedId = true)
		public UUID id;
		@DatabaseField
		public String stuff;

		public UuidGeneratedId() {
		}
	}

	protected static class One extends BaseDaoEnabled<One, Integer> {
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField
		public String stuff;

		public One() {
		}
	}

	protected static class ForeignDaoEnabled extends BaseDaoEnabled<ForeignDaoEnabled, Integer> {
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField(foreign = true)
		public One one;

		public ForeignDaoEnabled() {
		}
	}

	protected static class EagerAccount {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String name;
		@ForeignCollectionField(eager = true)
		Collection<EagerOrder> orders;

		protected EagerAccount() {
		}
	}

	protected static class EagerOrder {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		int val;
		@DatabaseField(foreign = true)
		EagerAccount account;

		protected EagerOrder() {
		}
	}

	protected static class LazyAccount {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String name;
		@ForeignCollectionField
		Collection<LazyOrder> orders;

		protected LazyAccount() {
		}
	}

	protected static class LazyOrder {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		int val;
		@DatabaseField(foreign = true)
		LazyAccount account;

		protected LazyOrder() {
		}
	}

	protected static class AllowGeneratedIdInsert {
		@DatabaseField(generatedId = true, allowGeneratedIdInsert = true)
		int id;

		@DatabaseField
		String stuff;
	}

	protected static class SelfGeneratedIdUuidPrimary {
		@DatabaseField(generatedId = true)
		UUID id;

		@DatabaseField
		String stuff;
	}

	protected static class AllowGeneratedIdInsertObject {
		@DatabaseField(generatedId = true, allowGeneratedIdInsert = true)
		Integer id;

		@DatabaseField
		String stuff;
	}

	protected static class CreateOrUpdateObjectId {
		@DatabaseField(generatedId = true)
		public Integer id;
		@DatabaseField
		public String stuff;

		public CreateOrUpdateObjectId() {
		}
	}

	protected static class Order {
		public static final String ONE_FIELD_NAME = "one_id";
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(unique = true)
		int val;
		@DatabaseField(foreign = true, columnName = ONE_FIELD_NAME)
		One one;

		protected Order() {
		}
	}

	protected static class ForeignAutoCreate {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(foreign = true, foreignAutoCreate = true)
		public ForeignAutoCreateForeign foreign;
	}

	protected static class ForeignAutoCreateForeign {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String stuff;
	}

	protected static class Foreign {
		public static final String FOREIGN_COLUMN_NAME = "foo_id";
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField(foreign = true, columnName = FOREIGN_COLUMN_NAME)
		public Foo foo;

		public Foreign() {
		}
	}

	protected static class ForeignNotNull {
		@DatabaseField(generatedId = true)
		public int id;
		@DatabaseField(foreign = true, canBeNull = false)
		public Foo foo;

		public ForeignNotNull() {
		}
	}

	protected static class BigDecimalNumeric {
		public static final String BIG_DECIMAL_NUMERIC_FIELD_NAME = "bigDecimalNumeric";
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(columnName = BIG_DECIMAL_NUMERIC_FIELD_NAME, dataType = DataType.BIG_DECIMAL_NUMERIC)
		BigDecimal bigDecimalNumeric;

		BigDecimalNumeric() {
		}
	}

	protected static class ForeignColumnName {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(foreign = true, foreignColumnName = ForeignColumnNameForeign.FIELD_NAME)
		ForeignColumnNameForeign foreign;

		public ForeignColumnName() {
		}
	}

	protected static class ForeignColumnNameForeign {
		public static final String FIELD_NAME = "name";
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField
		String name;

		public ForeignColumnNameForeign() {
		}
	}

	protected static class VersionField {
		@DatabaseField(generatedId = true)
		int id;
		@DatabaseField(version = true)
		int version;

		public VersionField() {
		}
	}

	protected static class FewFields {
		@DatabaseField(generatedId = true)
		int id;

		public FewFields() {
		}
	}
}