Index: /trunk/ippdb/Makefile.am
===================================================================
--- /trunk/ippdb/Makefile.am	(revision 10059)
+++ /trunk/ippdb/Makefile.am	(revision 10060)
@@ -11,6 +11,9 @@
     $(top_builddir)/docs/man/man3/ippdb.3 \
     $(top_builddir)/docs/man/man3/summitExpRow.3 \
+    $(top_builddir)/docs/man/man3/summitImfileRow.3 \
     $(top_builddir)/docs/man/man3/pzPendingExpRow.3 \
     $(top_builddir)/docs/man/man3/pzPendingImfileRow.3 \
+    $(top_builddir)/docs/man/man3/pzDoneExpRow.3 \
+    $(top_builddir)/docs/man/man3/pzDoneImfileRow.3 \
     $(top_builddir)/docs/man/man3/newExpRow.3 \
     $(top_builddir)/docs/man/man3/newImfileRow.3 \
@@ -42,5 +45,5 @@
 
 
-docs/man/man3/ippdb.3 docs/man/man3/summitExpRow.3 docs/man/man3/pzPendingExpRow.3 docs/man/man3/pzPendingImfileRow.3 docs/man/man3/newExpRow.3 docs/man/man3/newImfileRow.3 docs/man/man3/rawDetrendExpRow.3 docs/man/man3/rawScienceExpRow.3 docs/man/man3/rawImfileRow.3 docs/man/man3/p1PendingExpRow.3 docs/man/man3/p2PendingExpRow.3 docs/man/man3/p2PendingImfileRow.3 docs/man/man3/p2ProcessedExpRow.3 docs/man/man3/p2MaskRow.3 docs/man/man3/p2ProcessedImfileRow.3 docs/man/man3/p3PendingExpRow.3 docs/man/man3/p3ProcessedExpRow.3 docs/man/man3/p3MaskRow.3 docs/man/man3/detRunRow.3 docs/man/man3/detInputExpRow.3 docs/man/man3/detProcessedImfileRow.3 docs/man/man3/detProcessedExpRow.3 docs/man/man3/detStackedImfileRow.3 docs/man/man3/detNormalizedStatImfileRow.3 docs/man/man3/detNormalizedImfileRow.3 docs/man/man3/detNormalizedExpRow.3 docs/man/man3/detMasterFrameRow.3 docs/man/man3/detMasterImfileRow.3 docs/man/man3/detResidImfileRow.3 docs/man/man3/detResidExpRow.3 docs/man/man3/detRunSummaryRow.3:
+docs/man/man3/ippdb.3 docs/man/man3/summitExpRow.3 docs/man/man3/summitImfileRow.3 docs/man/man3/pzPendingExpRow.3 docs/man/man3/pzPendingImfileRow.3 docs/man/man3/pzDoneExpRow.3 docs/man/man3/pzDoneImfileRow.3 docs/man/man3/newExpRow.3 docs/man/man3/newImfileRow.3 docs/man/man3/rawDetrendExpRow.3 docs/man/man3/rawScienceExpRow.3 docs/man/man3/rawImfileRow.3 docs/man/man3/p1PendingExpRow.3 docs/man/man3/p2PendingExpRow.3 docs/man/man3/p2PendingImfileRow.3 docs/man/man3/p2ProcessedExpRow.3 docs/man/man3/p2MaskRow.3 docs/man/man3/p2ProcessedImfileRow.3 docs/man/man3/p3PendingExpRow.3 docs/man/man3/p3ProcessedExpRow.3 docs/man/man3/p3MaskRow.3 docs/man/man3/detRunRow.3 docs/man/man3/detInputExpRow.3 docs/man/man3/detProcessedImfileRow.3 docs/man/man3/detProcessedExpRow.3 docs/man/man3/detStackedImfileRow.3 docs/man/man3/detNormalizedStatImfileRow.3 docs/man/man3/detNormalizedImfileRow.3 docs/man/man3/detNormalizedExpRow.3 docs/man/man3/detMasterFrameRow.3 docs/man/man3/detMasterImfileRow.3 docs/man/man3/detResidImfileRow.3 docs/man/man3/detResidExpRow.3 docs/man/man3/detRunSummaryRow.3:
 	$(DOXYGEN)
 
Index: /trunk/ippdb/configure.ac
===================================================================
--- /trunk/ippdb/configure.ac	(revision 10059)
+++ /trunk/ippdb/configure.ac	(revision 10060)
@@ -7,5 +7,5 @@
 AC_PREREQ(2.59)
 
-AC_INIT([ippdb], [0.0.55], [pan-starrs.ifa.hawaii.edu])
+AC_INIT([ippdb], [0.0.56], [pan-starrs.ifa.hawaii.edu])
 AC_CONFIG_SRCDIR([ippdb.pc.in])
 
Index: /trunk/ippdb/src/ippdb.c
===================================================================
--- /trunk/ippdb/src/ippdb.c	(revision 10059)
+++ /trunk/ippdb/src/ippdb.c	(revision 10060)
@@ -32,6 +32,9 @@
 
 #define SUMMITEXP_TABLE_NAME "summitExp"
+#define SUMMITIMFILE_TABLE_NAME "summitImfile"
 #define PZPENDINGEXP_TABLE_NAME "pzPendingExp"
 #define PZPENDINGIMFILE_TABLE_NAME "pzPendingImfile"
+#define PZDONEEXP_TABLE_NAME "pzDoneExp"
+#define PZDONEIMFILE_TABLE_NAME "pzDoneImfile"
 #define NEWEXP_TABLE_NAME "newExp"
 #define NEWIMFILE_TABLE_NAME "newImfile"
@@ -234,5 +237,5 @@
 static void summitExpRowFree(summitExpRow *object);
 
-summitExpRow *summitExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, psTime* time, const char *exp_type, const char *uri)
+summitExpRow *summitExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, psTime* dateobs, const char *exp_type, const char *uri, psS32 imfiles)
 {
     summitExpRow    *_object;
@@ -244,7 +247,8 @@
     _object->camera = psStringCopy(camera);
     _object->telescope = psStringCopy(telescope);
-    _object->time = psTimeCopy(time);
+    _object->dateobs = psTimeCopy(dateobs);
     _object->exp_type = psStringCopy(exp_type);
     _object->uri = psStringCopy(uri);
+    _object->imfiles = imfiles;
 
     return _object;
@@ -256,5 +260,5 @@
     psFree(object->camera);
     psFree(object->telescope);
-    psFree(object->time);
+    psFree(object->dateobs);
     psFree(object->exp_type);
     psFree(object->uri);
@@ -279,12 +283,12 @@
         return false;
     }
-    psTime* time = psTimeFromISO("", PS_TIME_UTC);
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "time", PS_DATA_TIME, NULL, time)) {
-        psFree(time);
-        psError(PS_ERR_UNKNOWN, false, "failed to add item time");
-        psFree(md);
-        return false;
-    }
-    psFree(time);
+    psTime* dateobs = psTimeFromISO("", PS_TIME_UTC);
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "dateobs", PS_DATA_TIME, NULL, dateobs)) {
+        psFree(dateobs);
+        psError(PS_ERR_UNKNOWN, false, "failed to add item dateobs");
+        psFree(md);
+        return false;
+    }
+    psFree(dateobs);
     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
@@ -297,4 +301,9 @@
         return false;
     }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
 
     bool status = psDBCreateTable(dbh, SUMMITEXP_TABLE_NAME, md);
@@ -310,5 +319,5 @@
 }
 
-bool summitExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, psTime* time, const char *exp_type, const char *uri)
+bool summitExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, psTime* dateobs, const char *exp_type, const char *uri, psS32 imfiles)
 {
     psMetadata *md = psMetadataAlloc();
@@ -328,6 +337,6 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "time", PS_DATA_TIME, NULL, time)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item time");
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "dateobs", PS_DATA_TIME, NULL, dateobs)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item dateobs");
         psFree(md);
         return false;
@@ -340,4 +349,9 @@
     if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
         psFree(md);
         return false;
@@ -366,5 +380,5 @@
 bool summitExpInsertObject(psDB *dbh, summitExpRow *object)
 {
-    return summitExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->time, object->exp_type, object->uri);
+    return summitExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->dateobs, object->exp_type, object->uri, object->imfiles);
 }
 
@@ -454,6 +468,6 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "time", PS_DATA_TIME, NULL, object->time)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item time");
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "dateobs", PS_DATA_TIME, NULL, object->dateobs)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item dateobs");
         psFree(md);
         return false;
@@ -469,4 +483,9 @@
         return false;
     }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
 
 
@@ -493,7 +512,7 @@
         return false;
     }
-    psTime* time = psMetadataLookupPtr(&status, md, "time");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item time");
+    psTime* dateobs = psMetadataLookupPtr(&status, md, "dateobs");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item dateobs");
         return false;
     }
@@ -508,6 +527,11 @@
         return false;
     }
-
-    return summitExpRowAlloc(exp_id, camera, telescope, time, exp_type, uri);
+    psS32 imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+
+    return summitExpRowAlloc(exp_id, camera, telescope, dateobs, exp_type, uri, imfiles);
 }
 psArray *summitExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -604,31 +628,37 @@
     return true;
 }
-static void pzPendingExpRowFree(pzPendingExpRow *object);
-
-pzPendingExpRow *pzPendingExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
-{
-    pzPendingExpRow *_object;
-
-    _object = psAlloc(sizeof(pzPendingExpRow));
-    psMemSetDeallocator(_object, (psFreeFunc)pzPendingExpRowFree);
+static void summitImfileRowFree(summitImfileRow *object);
+
+summitImfileRow *summitImfileRowAlloc(const char *exp_id, const char *camera, const char *telescope, psS32 bytes, const char *md5sum, const char *class, const char *class_id, const char *uri)
+{
+    summitImfileRow *_object;
+
+    _object = psAlloc(sizeof(summitImfileRow));
+    psMemSetDeallocator(_object, (psFreeFunc)summitImfileRowFree);
 
     _object->exp_id = psStringCopy(exp_id);
     _object->camera = psStringCopy(camera);
     _object->telescope = psStringCopy(telescope);
-    _object->exp_type = psStringCopy(exp_type);
-    _object->imfiles = imfiles;
+    _object->bytes = bytes;
+    _object->md5sum = psStringCopy(md5sum);
+    _object->class = psStringCopy(class);
+    _object->class_id = psStringCopy(class_id);
+    _object->uri = psStringCopy(uri);
 
     return _object;
 }
 
-static void pzPendingExpRowFree(pzPendingExpRow *object)
+static void summitImfileRowFree(summitImfileRow *object)
 {
     psFree(object->exp_id);
     psFree(object->camera);
     psFree(object->telescope);
-    psFree(object->exp_type);
-}
-
-bool pzPendingExpCreateTable(psDB *dbh)
+    psFree(object->md5sum);
+    psFree(object->class);
+    psFree(object->class_id);
+    psFree(object->uri);
+}
+
+bool summitImfileCreateTable(psDB *dbh)
 {
     psMetadata *md = psMetadataAlloc();
@@ -648,16 +678,31 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, "64")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, 0)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
-        psFree(md);
-        return false;
-    }
-
-    bool status = psDBCreateTable(dbh, PZPENDINGEXP_TABLE_NAME, md);
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "bytes", PS_DATA_S32, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "md5sum", PS_DATA_STRING, NULL, "32")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBCreateTable(dbh, SUMMITIMFILE_TABLE_NAME, md);
 
     psFree(md);
@@ -666,10 +711,10 @@
 }
 
-bool pzPendingExpDropTable(psDB *dbh)
-{
-    return psDBDropTable(dbh, PZPENDINGEXP_TABLE_NAME);
-}
-
-bool pzPendingExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
+bool summitImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, SUMMITIMFILE_TABLE_NAME);
+}
+
+bool summitImfileInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, psS32 bytes, const char *md5sum, const char *class, const char *class_id, const char *uri)
 {
     psMetadata *md = psMetadataAlloc();
@@ -689,16 +734,31 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, exp_type)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, imfiles)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
-        psFree(md);
-        return false;
-    }
-
-    bool status = psDBInsertOneRow(dbh, PZPENDINGEXP_TABLE_NAME, md);
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "bytes", PS_DATA_S32, NULL, bytes)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "md5sum", PS_DATA_STRING, NULL, md5sum)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, class)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBInsertOneRow(dbh, SUMMITIMFILE_TABLE_NAME, md);
     psFree(md);
 
@@ -706,11 +766,11 @@
 }
 
-long long pzPendingExpDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
+long long summitImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
 {
     long long       deleted = 0;
 
-    long long count = psDBDeleteRows(dbh, PZPENDINGEXP_TABLE_NAME, where, limit);
+    long long count = psDBDeleteRows(dbh, SUMMITIMFILE_TABLE_NAME, where, limit);
     if (count < 0) {
-        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzPendingExp");
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from summitImfile");
         return count;
 
@@ -720,13 +780,13 @@
     return deleted;
 }
-bool pzPendingExpInsertObject(psDB *dbh, pzPendingExpRow *object)
-{
-    return pzPendingExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles);
-}
-
-bool pzPendingExpInsertObjects(psDB *dbh, psArray *objects)
+bool summitImfileInsertObject(psDB *dbh, summitImfileRow *object)
+{
+    return summitImfileInsert(dbh, object->exp_id, object->camera, object->telescope, object->bytes, object->md5sum, object->class, object->class_id, object->uri);
+}
+
+bool summitImfileInsertObjects(psDB *dbh, psArray *objects)
 {
     for (long i = 0; i < psArrayLength(objects); i++) {
-        if (!pzPendingExpInsertObject(dbh, objects->data[i])) {
+        if (!summitImfileInsertObject(dbh, objects->data[i])) {
             return false;
         }
@@ -736,11 +796,11 @@
 }
 
-bool pzPendingExpInsertFits(psDB *dbh, const psFits *fits)
+bool summitImfileInsertFits(psDB *dbh, const psFits *fits)
 {
     psArray         *rowSet;
 
-    // move to (the first?) extension named  PZPENDINGEXP_TABLE_NAME
-    if (!psFitsMoveExtName(fits, PZPENDINGEXP_TABLE_NAME)) {
-        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZPENDINGEXP_TABLE_NAME);
+    // move to (the first?) extension named  SUMMITIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, SUMMITIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", SUMMITIMFILE_TABLE_NAME);
         return false;
     }
@@ -760,4 +820,357 @@
     }
 
+    if (!psDBInsertRows(dbh, SUMMITIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool summitImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+
+    rowSet = psDBSelectRows(dbh, SUMMITIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, SUMMITIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *summitImfileMetadataFromObject(const summitImfileRow *object)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, object->exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, object->camera)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, object->telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "bytes", PS_DATA_S32, NULL, object->bytes)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "md5sum", PS_DATA_STRING, NULL, object->md5sum)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, object->class)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+
+    return md;
+}
+
+summitImfileRow *summitImfileObjectFromMetadata(psMetadata *md)
+{
+
+bool status = false;
+    char* exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    char* camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    char* telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    psS32 bytes = psMetadataLookupS32(&status, md, "bytes");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bytes");
+        return false;
+    }
+    char* md5sum = psMetadataLookupPtr(&status, md, "md5sum");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item md5sum");
+        return false;
+    }
+    char* class = psMetadataLookupPtr(&status, md, "class");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class");
+        return false;
+    }
+    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    char* uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+
+    return summitImfileRowAlloc(exp_id, camera, telescope, bytes, md5sum, class, class_id, uri);
+}
+psArray *summitImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SUMMITIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAllocEmpty(rowSet->n);
+
+    for (i = 0; i < rowSet->n; i++) {
+        summitImfileRow *object = summitImfileObjectFromMetadata(rowSet->data[i]);
+        psArrayAdd(returnSet, 0, object);
+        psFree(object);
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+bool summitImfileDeleteObject(psDB *dbh, const summitImfileRow *object)
+{
+    psMetadata *where = summitImfileMetadataFromObject(object);
+    long long count = psDBDeleteRows(dbh, SUMMITIMFILE_TABLE_NAME, where, 0);
+    psFree(where)
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from summitImfile");
+        return false;
+    }
+    if (count > 1) {
+        // XXX should this be a psAbort() instead?  It is possible that
+        // having an object match multiple rows was by design.
+        psError(PS_ERR_UNKNOWN, true, "summitImfileRow object matched more then one row.  Check your database schema");
+        return false;
+    }
+
+    return true;
+}
+long long summitImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        summitImfileRow *object = objects->data[i];
+        psMetadata *where = summitImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, SUMMITIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from summitImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool summitImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
+{
+    PS_ASSERT_PTR_NON_NULL(objects, false);
+
+    psMetadata *output = psMetadataAlloc();
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        psMetadata *md = summitImfileMetadataFromObject(objects->data[i]);
+        if (!psMetadataAddMetadata(
+            output,
+            PS_LIST_TAIL,
+            SUMMITIMFILE_TABLE_NAME,
+            PS_META_DUPLICATE_OK,
+            NULL,
+            md
+        )) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
+            psFree(md);
+            psFree(output);
+            return false;
+        }
+        psFree(md);
+    }
+
+    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
+        psFree(output);
+    }
+    psFree(output);
+
+    return true;
+}
+static void pzPendingExpRowFree(pzPendingExpRow *object);
+
+pzPendingExpRow *pzPendingExpRowAlloc(const char *exp_id, const char *camera, const char *telescope)
+{
+    pzPendingExpRow *_object;
+
+    _object = psAlloc(sizeof(pzPendingExpRow));
+    psMemSetDeallocator(_object, (psFreeFunc)pzPendingExpRowFree);
+
+    _object->exp_id = psStringCopy(exp_id);
+    _object->camera = psStringCopy(camera);
+    _object->telescope = psStringCopy(telescope);
+
+    return _object;
+}
+
+static void pzPendingExpRowFree(pzPendingExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+}
+
+bool pzPendingExpCreateTable(psDB *dbh)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBCreateTable(dbh, PZPENDINGEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool pzPendingExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, PZPENDINGEXP_TABLE_NAME);
+}
+
+bool pzPendingExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, camera)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBInsertOneRow(dbh, PZPENDINGEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+long long pzPendingExpDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    long long count = psDBDeleteRows(dbh, PZPENDINGEXP_TABLE_NAME, where, limit);
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzPendingExp");
+        return count;
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool pzPendingExpInsertObject(psDB *dbh, pzPendingExpRow *object)
+{
+    return pzPendingExpInsert(dbh, object->exp_id, object->camera, object->telescope);
+}
+
+bool pzPendingExpInsertObjects(psDB *dbh, psArray *objects)
+{
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        if (!pzPendingExpInsertObject(dbh, objects->data[i])) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool pzPendingExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  PZPENDINGEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, PZPENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZPENDINGEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
     if (!psDBInsertRows(dbh, PZPENDINGEXP_TABLE_NAME, rowSet)) {
         psError(PS_ERR_UNKNOWN, false, "databse insert failed");
@@ -810,14 +1223,4 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, object->exp_type)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, object->imfiles)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
-        psFree(md);
-        return false;
-    }
 
 
@@ -844,16 +1247,6 @@
         return false;
     }
-    char* exp_type = psMetadataLookupPtr(&status, md, "exp_type");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
-        return false;
-    }
-    psS32 imfiles = psMetadataLookupS32(&status, md, "imfiles");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
-        return false;
-    }
-
-    return pzPendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles);
+
+    return pzPendingExpRowAlloc(exp_id, camera, telescope);
 }
 psArray *pzPendingExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -952,5 +1345,5 @@
 static void pzPendingImfileRowFree(pzPendingImfileRow *object);
 
-pzPendingImfileRow *pzPendingImfileRowAlloc(const char *exp_id, const char *camera, const char *telescope, psS32 bytes, const char *md5sum, const char *class, const char *class_id, const char *uri)
+pzPendingImfileRow *pzPendingImfileRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *class, const char *class_id, const char *exp_tag)
 {
     pzPendingImfileRow *_object;
@@ -962,9 +1355,7 @@
     _object->camera = psStringCopy(camera);
     _object->telescope = psStringCopy(telescope);
-    _object->bytes = bytes;
-    _object->md5sum = psStringCopy(md5sum);
     _object->class = psStringCopy(class);
     _object->class_id = psStringCopy(class_id);
-    _object->uri = psStringCopy(uri);
+    _object->exp_tag = psStringCopy(exp_tag);
 
     return _object;
@@ -976,8 +1367,7 @@
     psFree(object->camera);
     psFree(object->telescope);
-    psFree(object->md5sum);
     psFree(object->class);
     psFree(object->class_id);
-    psFree(object->uri);
+    psFree(object->exp_tag);
 }
 
@@ -1000,15 +1390,5 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "bytes", PS_DATA_S32, NULL, 0)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "md5sum", PS_DATA_STRING, NULL, "32")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, "64")) {
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, "Primary Key", "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item class");
         psFree(md);
@@ -1020,6 +1400,6 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Unique Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
         psFree(md);
         return false;
@@ -1038,5 +1418,5 @@
 }
 
-bool pzPendingImfileInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, psS32 bytes, const char *md5sum, const char *class, const char *class_id, const char *uri)
+bool pzPendingImfileInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *class, const char *class_id, const char *exp_tag)
 {
     psMetadata *md = psMetadataAlloc();
@@ -1056,14 +1436,4 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "bytes", PS_DATA_S32, NULL, bytes)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "md5sum", PS_DATA_STRING, NULL, md5sum)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
-        psFree(md);
-        return false;
-    }
     if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, class)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item class");
@@ -1076,6 +1446,6 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
         psFree(md);
         return false;
@@ -1104,5 +1474,5 @@
 bool pzPendingImfileInsertObject(psDB *dbh, pzPendingImfileRow *object)
 {
-    return pzPendingImfileInsert(dbh, object->exp_id, object->camera, object->telescope, object->bytes, object->md5sum, object->class, object->class_id, object->uri);
+    return pzPendingImfileInsert(dbh, object->exp_id, object->camera, object->telescope, object->class, object->class_id, object->exp_tag);
 }
 
@@ -1192,14 +1562,4 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "bytes", PS_DATA_S32, NULL, object->bytes)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "md5sum", PS_DATA_STRING, NULL, object->md5sum)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
-        psFree(md);
-        return false;
-    }
     if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, object->class)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item class");
@@ -1212,6 +1572,6 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
         psFree(md);
         return false;
@@ -1241,14 +1601,4 @@
         return false;
     }
-    psS32 bytes = psMetadataLookupS32(&status, md, "bytes");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bytes");
-        return false;
-    }
-    char* md5sum = psMetadataLookupPtr(&status, md, "md5sum");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item md5sum");
-        return false;
-    }
     char* class = psMetadataLookupPtr(&status, md, "class");
     if (!status) {
@@ -1261,11 +1611,11 @@
         return false;
     }
-    char* uri = psMetadataLookupPtr(&status, md, "uri");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
-        return false;
-    }
-
-    return pzPendingImfileRowAlloc(exp_id, camera, telescope, bytes, md5sum, class, class_id, uri);
+    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
+        return false;
+    }
+
+    return pzPendingImfileRowAlloc(exp_id, camera, telescope, class, class_id, exp_tag);
 }
 psArray *pzPendingImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -1362,67 +1712,47 @@
     return true;
 }
-static void newExpRowFree(newExpRow *object);
-
-newExpRow *newExpRowAlloc(const char *exp_tag, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
-{
-    newExpRow       *_object;
-
-    _object = psAlloc(sizeof(newExpRow));
-    psMemSetDeallocator(_object, (psFreeFunc)newExpRowFree);
-
-    _object->exp_tag = psStringCopy(exp_tag);
+static void pzDoneExpRowFree(pzDoneExpRow *object);
+
+pzDoneExpRow *pzDoneExpRowAlloc(const char *exp_id, const char *camera, const char *telescope)
+{
+    pzDoneExpRow    *_object;
+
+    _object = psAlloc(sizeof(pzDoneExpRow));
+    psMemSetDeallocator(_object, (psFreeFunc)pzDoneExpRowFree);
+
     _object->exp_id = psStringCopy(exp_id);
     _object->camera = psStringCopy(camera);
     _object->telescope = psStringCopy(telescope);
-    _object->exp_type = psStringCopy(exp_type);
-    _object->imfiles = imfiles;
 
     return _object;
 }
 
-static void newExpRowFree(newExpRow *object)
-{
-    psFree(object->exp_tag);
+static void pzDoneExpRowFree(pzDoneExpRow *object)
+{
     psFree(object->exp_id);
     psFree(object->camera);
     psFree(object->telescope);
-    psFree(object->exp_type);
-}
-
-bool newExpCreateTable(psDB *dbh)
+}
+
+bool pzDoneExpCreateTable(psDB *dbh)
 {
     psMetadata *md = psMetadataAlloc();
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Primary Key", "64")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, "Key", "64")) {
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, "Primary Key", "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
         psFree(md);
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, "64")) {
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, "Primary Key", "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
         psFree(md);
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, "64")) {
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, "Primary Key", "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
         psFree(md);
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, "64")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, 0)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
-        psFree(md);
-        return false;
-    }
-
-    bool status = psDBCreateTable(dbh, NEWEXP_TABLE_NAME, md);
+
+    bool status = psDBCreateTable(dbh, PZDONEEXP_TABLE_NAME, md);
 
     psFree(md);
@@ -1431,17 +1761,12 @@
 }
 
-bool newExpDropTable(psDB *dbh)
-{
-    return psDBDropTable(dbh, NEWEXP_TABLE_NAME);
-}
-
-bool newExpInsert(psDB * dbh, const char *exp_tag, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
+bool pzDoneExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, PZDONEEXP_TABLE_NAME);
+}
+
+bool pzDoneExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope)
 {
     psMetadata *md = psMetadataAlloc();
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
-        psFree(md);
-        return false;
-    }
     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, exp_id)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
@@ -1459,16 +1784,6 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, exp_type)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
-        psFree(md);
-        return false;
-    }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, imfiles)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
-        psFree(md);
-        return false;
-    }
-
-    bool status = psDBInsertOneRow(dbh, NEWEXP_TABLE_NAME, md);
+
+    bool status = psDBInsertOneRow(dbh, PZDONEEXP_TABLE_NAME, md);
     psFree(md);
 
@@ -1476,11 +1791,11 @@
 }
 
-long long newExpDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
+long long pzDoneExpDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
 {
     long long       deleted = 0;
 
-    long long count = psDBDeleteRows(dbh, NEWEXP_TABLE_NAME, where, limit);
+    long long count = psDBDeleteRows(dbh, PZDONEEXP_TABLE_NAME, where, limit);
     if (count < 0) {
-        psError(PS_ERR_UNKNOWN, true, "failed to delete row from newExp");
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDoneExp");
         return count;
 
@@ -1490,13 +1805,13 @@
     return deleted;
 }
-bool newExpInsertObject(psDB *dbh, newExpRow *object)
-{
-    return newExpInsert(dbh, object->exp_tag, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles);
-}
-
-bool newExpInsertObjects(psDB *dbh, psArray *objects)
+bool pzDoneExpInsertObject(psDB *dbh, pzDoneExpRow *object)
+{
+    return pzDoneExpInsert(dbh, object->exp_id, object->camera, object->telescope);
+}
+
+bool pzDoneExpInsertObjects(psDB *dbh, psArray *objects)
 {
     for (long i = 0; i < psArrayLength(objects); i++) {
-        if (!newExpInsertObject(dbh, objects->data[i])) {
+        if (!pzDoneExpInsertObject(dbh, objects->data[i])) {
             return false;
         }
@@ -1506,11 +1821,11 @@
 }
 
-bool newExpInsertFits(psDB *dbh, const psFits *fits)
+bool pzDoneExpInsertFits(psDB *dbh, const psFits *fits)
 {
     psArray         *rowSet;
 
-    // move to (the first?) extension named  NEWEXP_TABLE_NAME
-    if (!psFitsMoveExtName(fits, NEWEXP_TABLE_NAME)) {
-        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", NEWEXP_TABLE_NAME);
+    // move to (the first?) extension named  PZDONEEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, PZDONEEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZDONEEXP_TABLE_NAME);
         return false;
     }
@@ -1530,4 +1845,747 @@
     }
 
+    if (!psDBInsertRows(dbh, PZDONEEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool pzDoneExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+
+    rowSet = psDBSelectRows(dbh, PZDONEEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, PZDONEEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *pzDoneExpMetadataFromObject(const pzDoneExpRow *object)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, object->exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, object->camera)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, object->telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+
+
+    return md;
+}
+
+pzDoneExpRow *pzDoneExpObjectFromMetadata(psMetadata *md)
+{
+
+bool status = false;
+    char* exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    char* camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    char* telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+
+    return pzDoneExpRowAlloc(exp_id, camera, telescope);
+}
+psArray *pzDoneExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, PZDONEEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAllocEmpty(rowSet->n);
+
+    for (i = 0; i < rowSet->n; i++) {
+        pzDoneExpRow *object = pzDoneExpObjectFromMetadata(rowSet->data[i]);
+        psArrayAdd(returnSet, 0, object);
+        psFree(object);
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+bool pzDoneExpDeleteObject(psDB *dbh, const pzDoneExpRow *object)
+{
+    psMetadata *where = pzDoneExpMetadataFromObject(object);
+    long long count = psDBDeleteRows(dbh, PZDONEEXP_TABLE_NAME, where, 0);
+    psFree(where)
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDoneExp");
+        return false;
+    }
+    if (count > 1) {
+        // XXX should this be a psAbort() instead?  It is possible that
+        // having an object match multiple rows was by design.
+        psError(PS_ERR_UNKNOWN, true, "pzDoneExpRow object matched more then one row.  Check your database schema");
+        return false;
+    }
+
+    return true;
+}
+long long pzDoneExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        pzDoneExpRow *object = objects->data[i];
+        psMetadata *where = pzDoneExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, PZDONEEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDoneExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool pzDoneExpPrintObjects(FILE *stream, psArray *objects, bool mdcf)
+{
+    PS_ASSERT_PTR_NON_NULL(objects, false);
+
+    psMetadata *output = psMetadataAlloc();
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        psMetadata *md = pzDoneExpMetadataFromObject(objects->data[i]);
+        if (!psMetadataAddMetadata(
+            output,
+            PS_LIST_TAIL,
+            PZDONEEXP_TABLE_NAME,
+            PS_META_DUPLICATE_OK,
+            NULL,
+            md
+        )) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
+            psFree(md);
+            psFree(output);
+            return false;
+        }
+        psFree(md);
+    }
+
+    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
+        psFree(output);
+    }
+    psFree(output);
+
+    return true;
+}
+static void pzDoneImfileRowFree(pzDoneImfileRow *object);
+
+pzDoneImfileRow *pzDoneImfileRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *class, const char *class_id, const char *exp_tag, const char *uri)
+{
+    pzDoneImfileRow *_object;
+
+    _object = psAlloc(sizeof(pzDoneImfileRow));
+    psMemSetDeallocator(_object, (psFreeFunc)pzDoneImfileRowFree);
+
+    _object->exp_id = psStringCopy(exp_id);
+    _object->camera = psStringCopy(camera);
+    _object->telescope = psStringCopy(telescope);
+    _object->class = psStringCopy(class);
+    _object->class_id = psStringCopy(class_id);
+    _object->exp_tag = psStringCopy(exp_tag);
+    _object->uri = psStringCopy(uri);
+
+    return _object;
+}
+
+static void pzDoneImfileRowFree(pzDoneImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->class);
+    psFree(object->class_id);
+    psFree(object->exp_tag);
+    psFree(object->uri);
+}
+
+bool pzDoneImfileCreateTable(psDB *dbh)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Unique Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBCreateTable(dbh, PZDONEIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool pzDoneImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, PZDONEIMFILE_TABLE_NAME);
+}
+
+bool pzDoneImfileInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *class, const char *class_id, const char *exp_tag, const char *uri)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, camera)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, class)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBInsertOneRow(dbh, PZDONEIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+long long pzDoneImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    long long count = psDBDeleteRows(dbh, PZDONEIMFILE_TABLE_NAME, where, limit);
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDoneImfile");
+        return count;
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool pzDoneImfileInsertObject(psDB *dbh, pzDoneImfileRow *object)
+{
+    return pzDoneImfileInsert(dbh, object->exp_id, object->camera, object->telescope, object->class, object->class_id, object->exp_tag, object->uri);
+}
+
+bool pzDoneImfileInsertObjects(psDB *dbh, psArray *objects)
+{
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        if (!pzDoneImfileInsertObject(dbh, objects->data[i])) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool pzDoneImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  PZDONEIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, PZDONEIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZDONEIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, PZDONEIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool pzDoneImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+
+    rowSet = psDBSelectRows(dbh, PZDONEIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, PZDONEIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *pzDoneImfileMetadataFromObject(const pzDoneImfileRow *object)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, object->exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, object->camera)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, object->telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, object->class)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+
+    return md;
+}
+
+pzDoneImfileRow *pzDoneImfileObjectFromMetadata(psMetadata *md)
+{
+
+bool status = false;
+    char* exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    char* camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    char* telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    char* class = psMetadataLookupPtr(&status, md, "class");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class");
+        return false;
+    }
+    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
+        return false;
+    }
+    char* uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+
+    return pzDoneImfileRowAlloc(exp_id, camera, telescope, class, class_id, exp_tag, uri);
+}
+psArray *pzDoneImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, PZDONEIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAllocEmpty(rowSet->n);
+
+    for (i = 0; i < rowSet->n; i++) {
+        pzDoneImfileRow *object = pzDoneImfileObjectFromMetadata(rowSet->data[i]);
+        psArrayAdd(returnSet, 0, object);
+        psFree(object);
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+bool pzDoneImfileDeleteObject(psDB *dbh, const pzDoneImfileRow *object)
+{
+    psMetadata *where = pzDoneImfileMetadataFromObject(object);
+    long long count = psDBDeleteRows(dbh, PZDONEIMFILE_TABLE_NAME, where, 0);
+    psFree(where)
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDoneImfile");
+        return false;
+    }
+    if (count > 1) {
+        // XXX should this be a psAbort() instead?  It is possible that
+        // having an object match multiple rows was by design.
+        psError(PS_ERR_UNKNOWN, true, "pzDoneImfileRow object matched more then one row.  Check your database schema");
+        return false;
+    }
+
+    return true;
+}
+long long pzDoneImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        pzDoneImfileRow *object = objects->data[i];
+        psMetadata *where = pzDoneImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, PZDONEIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDoneImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool pzDoneImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
+{
+    PS_ASSERT_PTR_NON_NULL(objects, false);
+
+    psMetadata *output = psMetadataAlloc();
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        psMetadata *md = pzDoneImfileMetadataFromObject(objects->data[i]);
+        if (!psMetadataAddMetadata(
+            output,
+            PS_LIST_TAIL,
+            PZDONEIMFILE_TABLE_NAME,
+            PS_META_DUPLICATE_OK,
+            NULL,
+            md
+        )) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
+            psFree(md);
+            psFree(output);
+            return false;
+        }
+        psFree(md);
+    }
+
+    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
+        psFree(output);
+    }
+    psFree(output);
+
+    return true;
+}
+static void newExpRowFree(newExpRow *object);
+
+newExpRow *newExpRowAlloc(psU64 exp_tag, const char *exp_id, const char *camera, const char *telescope, psTime* dateobs, const char *exp_type, psS32 imfiles)
+{
+    newExpRow       *_object;
+
+    _object = psAlloc(sizeof(newExpRow));
+    psMemSetDeallocator(_object, (psFreeFunc)newExpRowFree);
+
+    _object->exp_tag = exp_tag;
+    _object->exp_id = psStringCopy(exp_id);
+    _object->camera = psStringCopy(camera);
+    _object->telescope = psStringCopy(telescope);
+    _object->dateobs = psTimeCopy(dateobs);
+    _object->exp_type = psStringCopy(exp_type);
+    _object->imfiles = imfiles;
+
+    return _object;
+}
+
+static void newExpRowFree(newExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->dateobs);
+    psFree(object->exp_type);
+}
+
+bool newExpCreateTable(psDB *dbh)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_U64, "Primary Key AUTO_INCREMENT", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    psTime* dateobs = psTimeFromISO("", PS_TIME_UTC);
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "dateobs", PS_DATA_TIME, NULL, dateobs)) {
+        psFree(dateobs);
+        psError(PS_ERR_UNKNOWN, false, "failed to add item dateobs");
+        psFree(md);
+        return false;
+    }
+    psFree(dateobs);
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBCreateTable(dbh, NEWEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool newExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, NEWEXP_TABLE_NAME);
+}
+
+bool newExpInsert(psDB * dbh, psU64 exp_tag, const char *exp_id, const char *camera, const char *telescope, psTime* dateobs, const char *exp_type, psS32 imfiles)
+{
+    psMetadata *md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_U64, NULL, exp_tag)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_STRING, NULL, exp_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, camera)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, telescope)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "dateobs", PS_DATA_TIME, NULL, dateobs)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item dateobs");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, exp_type)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+
+    bool status = psDBInsertOneRow(dbh, NEWEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+long long newExpDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    long long count = psDBDeleteRows(dbh, NEWEXP_TABLE_NAME, where, limit);
+    if (count < 0) {
+        psError(PS_ERR_UNKNOWN, true, "failed to delete row from newExp");
+        return count;
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+bool newExpInsertObject(psDB *dbh, newExpRow *object)
+{
+    return newExpInsert(dbh, object->exp_tag, object->exp_id, object->camera, object->telescope, object->dateobs, object->exp_type, object->imfiles);
+}
+
+bool newExpInsertObjects(psDB *dbh, psArray *objects)
+{
+    for (long i = 0; i < psArrayLength(objects); i++) {
+        if (!newExpInsertObject(dbh, objects->data[i])) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool newExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  NEWEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, NEWEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", NEWEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
     if (!psDBInsertRows(dbh, NEWEXP_TABLE_NAME, rowSet)) {
         psError(PS_ERR_UNKNOWN, false, "databse insert failed");
@@ -1565,5 +2623,5 @@
 {
     psMetadata *md = psMetadataAlloc();
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_U64, NULL, object->exp_tag)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
         psFree(md);
@@ -1585,4 +2643,9 @@
         return false;
     }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "dateobs", PS_DATA_TIME, NULL, object->dateobs)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item dateobs");
+        psFree(md);
+        return false;
+    }
     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_type", PS_DATA_STRING, NULL, object->exp_type)) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
@@ -1604,5 +2667,5 @@
 
 bool status = false;
-    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
+    psU64 exp_tag = psMetadataLookupU64(&status, md, "exp_tag");
     if (!status) {
         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
@@ -1624,4 +2687,9 @@
         return false;
     }
+    psTime* dateobs = psMetadataLookupPtr(&status, md, "dateobs");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item dateobs");
+        return false;
+    }
     char* exp_type = psMetadataLookupPtr(&status, md, "exp_type");
     if (!status) {
@@ -1635,5 +2703,5 @@
     }
 
-    return newExpRowAlloc(exp_tag, exp_id, camera, telescope, exp_type, imfiles);
+    return newExpRowAlloc(exp_tag, exp_id, camera, telescope, dateobs, exp_type, imfiles);
 }
 psArray *newExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
@@ -1763,5 +2831,5 @@
         return false;
     }
-    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, NULL, "64")) {
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "class", PS_DATA_STRING, "Primary Key", "64")) {
         psError(PS_ERR_UNKNOWN, false, "failed to add item class");
         psFree(md);
Index: /trunk/ippdb/src/ippdb.h
===================================================================
--- /trunk/ippdb/src/ippdb.h	(revision 10059)
+++ /trunk/ippdb/src/ippdb.h	(revision 10060)
@@ -134,7 +134,8 @@
     char            *camera;
     char            *telescope;
-    psTime*         time;
+    psTime*         dateobs;
     char            *exp_type;
     char            *uri;
+    psS32           imfiles;
 } summitExpRow;
 
@@ -148,7 +149,8 @@
     const char      *camera,
     const char      *telescope,
-    psTime*         time,
+    psTime*         dateobs,
     const char      *exp_type,
-    const char      *uri
+    const char      *uri,
+    psS32           imfiles
 );
 
@@ -183,7 +185,8 @@
     const char      *camera,
     const char      *telescope,
-    psTime*         time,
+    psTime*         dateobs,
     const char      *exp_type,
-    const char      *uri
+    const char      *uri,
+    psS32           imfiles
 );
 
@@ -322,201 +325,7 @@
     bool            mdcf                ///< format as mdconfig or simple
 );
-/** pzPendingExpRow data structure
- *
- * Structure for representing a single row of pzPendingExp table data.
- */
-
-typedef struct {
-    char            *exp_id;
-    char            *camera;
-    char            *telescope;
-    char            *exp_type;
-    psS32           imfiles;
-} pzPendingExpRow;
-
-/** Creates a new pzPendingExpRow object
- *
- *  @return A new pzPendingExpRow object or NULL on failure.
- */
-
-pzPendingExpRow *pzPendingExpRowAlloc(
-    const char      *exp_id,
-    const char      *camera,
-    const char      *telescope,
-    const char      *exp_type,
-    psS32           imfiles
-);
-
-/** Creates a new pzPendingExp table
- *
- * @return true on success
- */
-
-bool pzPendingExpCreateTable(
-    psDB            *dbh                ///< Database handle
-);
-
-/** Deletes a pzPendingExp table
- *
- * @return true on success
- */
-
-bool pzPendingExpDropTable(
-    psDB            *dbh                ///< Database handle
-);
-
-/** Insert a single row into a table
- *
- * This function constructs and inserts a single row based on it's parameters.
- *
- * @return true on success
- */
-
-bool pzPendingExpInsert(
-    psDB            *dbh,               ///< Database handle
-    const char      *exp_id,
-    const char      *camera,
-    const char      *telescope,
-    const char      *exp_type,
-    psS32           imfiles
-);
-
-/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
- *
- * @return A The number of rows removed or a negative value on error
- */
-
-long long pzPendingExpDelete(
-    psDB            *dbh,               ///< Database handle
-    const psMetadata *where,            ///< Row match criteria
-    unsigned long long limit            ///< Maximum number of elements to delete 
-);
-
-/** Insert a single pzPendingExpRow object into a table
- *
- * This function constructs and inserts a single row based on it's parameters.
- *
- * @return true on success
- */
-
-bool pzPendingExpInsertObject(
-    psDB            *dbh,               ///< Database handle
-    pzPendingExpRow *object             ///< pzPendingExpRow object
-);
-
-/** Insert an array of pzPendingExpRow object into a table
- *
- * This function constructs and inserts multiple rows based on it's parameters.
- *
- * @return true on success
- */
-
-bool pzPendingExpInsertObjects(
-    psDB            *dbh,               ///< Database handle
-    psArray         *objects            ///< array of pzPendingExpRow objects
-);
-
-/** Insert data from a binary FITS table pzPendingExpRow into the database
- *
- * This function expects a psFits object with a FITS table as the first
- * extension.  The table must have at least one row of data in it, that is of
- * the appropriate format (number of columns and their type).  All other
- * extensions are ignored.
- *
- * @return true on success
- */
-
-bool pzPendingExpInsertFits(
-    psDB            *dbh,               ///< Database handle
-    const psFits    *fits               ///< psFits object
-);
-
-/** Selects up to limit from the database and returns them in a binary FITS table
- *
- * This function assumes an empty psFits object and will create a FITS table
- * as the first extension.
- *
- *  See psDBSelectRows() for documentation on the format of where.
- *
- * @return true on success
- */
-
-bool pzPendingExpSelectRowsFits(
-    psDB            *dbh,               ///< Database handle
-    psFits          *fits,              ///< psFits object
-    const psMetadata *where,            ///< Row match criteria
-    unsigned long long limit            ///< Maximum number of elements to return
-);
-
-/** Convert a pzPendingExpRow into an equivalent psMetadata
- *
- * @return A psMetadata pointer or NULL on error
- */
-
-psMetadata *pzPendingExpMetadataFromObject(
-    const pzPendingExpRow *object             ///< fooRow to convert into a psMetadata
-);
-
-/** Convert a psMetadata into an equivalent fooRow
- *
- * @return A pzPendingExpRow pointer or NULL on error
- */
-
-pzPendingExpRow *pzPendingExpObjectFromMetadata(
-    psMetadata      *md                 ///< psMetadata to convert into a fooRow
-);
-/** Selects up to limit rows from the database and returns as pzPendingExpRow objects in a psArray
- *
- *  See psDBSelectRows() for documentation on the format of where.
- *
- * @return A psArray pointer or NULL on error
- */
-
-psArray *pzPendingExpSelectRowObjects(
-    psDB            *dbh,               ///< Database handle
-    const psMetadata *where,            ///< Row match criteria
-    unsigned long long limit            ///< Maximum number of elements to return
-);
-/** Deletes a row from the database coresponding to an pzPendingExp
- *
- *  Note that a 'where' search psMetadata is constructed from each object and
- *  used to find rows to delete.
- *
- * @return A The number of rows removed or a negative value on error
- */
-
-bool pzPendingExpDeleteObject(
-    psDB            *dbh,               ///< Database handle
-    const pzPendingExpRow *object    ///< Object to delete
-);
-/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
- *
- *  Note that a 'where' search psMetadata is constructed from each object and
- *  used to find rows to delete.
- *
- * @return A The number of rows removed or a negative value on error
- */
-
-long long pzPendingExpDeleteRowObjects(
-    psDB            *dbh,               ///< Database handle
-    const psArray   *objects,           ///< Array of objects to delete
-    unsigned long long limit            ///< Maximum number of elements to delete 
-);
-/** Formats and prints an array of pzPendingExpRow objects
- *
- * When mdcf is set the formated output is in psMetadataConfig
- * format, otherwise it is in a simple tabular format.
- *
- * @return true on success
- */
-
-bool pzPendingExpPrintObjects(
-    FILE            *stream,            ///< a stream
-    psArray         *objects,           ///< An array of pzPendingExpRow objects
-    bool            mdcf                ///< format as mdconfig or simple
-);
-/** pzPendingImfileRow data structure
- *
- * Structure for representing a single row of pzPendingImfile table data.
+/** summitImfileRow data structure
+ *
+ * Structure for representing a single row of summitImfile table data.
  */
 
@@ -530,12 +339,12 @@
     char            *class_id;
     char            *uri;
-} pzPendingImfileRow;
-
-/** Creates a new pzPendingImfileRow object
- *
- *  @return A new pzPendingImfileRow object or NULL on failure.
- */
-
-pzPendingImfileRow *pzPendingImfileRowAlloc(
+} summitImfileRow;
+
+/** Creates a new summitImfileRow object
+ *
+ *  @return A new summitImfileRow object or NULL on failure.
+ */
+
+summitImfileRow *summitImfileRowAlloc(
     const char      *exp_id,
     const char      *camera,
@@ -548,19 +357,19 @@
 );
 
-/** Creates a new pzPendingImfile table
- *
- * @return true on success
- */
-
-bool pzPendingImfileCreateTable(
+/** Creates a new summitImfile table
+ *
+ * @return true on success
+ */
+
+bool summitImfileCreateTable(
     psDB            *dbh                ///< Database handle
 );
 
-/** Deletes a pzPendingImfile table
- *
- * @return true on success
- */
-
-bool pzPendingImfileDropTable(
+/** Deletes a summitImfile table
+ *
+ * @return true on success
+ */
+
+bool summitImfileDropTable(
     psDB            *dbh                ///< Database handle
 );
@@ -573,5 +382,5 @@
  */
 
-bool pzPendingImfileInsert(
+bool summitImfileInsert(
     psDB            *dbh,               ///< Database handle
     const char      *exp_id,
@@ -590,5 +399,5 @@
  */
 
-long long pzPendingImfileDelete(
+long long summitImfileDelete(
     psDB            *dbh,               ///< Database handle
     const psMetadata *where,            ///< Row match criteria
@@ -596,5 +405,5 @@
 );
 
-/** Insert a single pzPendingImfileRow object into a table
+/** Insert a single summitImfileRow object into a table
  *
  * This function constructs and inserts a single row based on it's parameters.
@@ -603,10 +412,10 @@
  */
 
-bool pzPendingImfileInsertObject(
-    psDB            *dbh,               ///< Database handle
-    pzPendingImfileRow *object             ///< pzPendingImfileRow object
-);
-
-/** Insert an array of pzPendingImfileRow object into a table
+bool summitImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    summitImfileRow *object             ///< summitImfileRow object
+);
+
+/** Insert an array of summitImfileRow object into a table
  *
  * This function constructs and inserts multiple rows based on it's parameters.
@@ -615,10 +424,10 @@
  */
 
-bool pzPendingImfileInsertObjects(
-    psDB            *dbh,               ///< Database handle
-    psArray         *objects            ///< array of pzPendingImfileRow objects
-);
-
-/** Insert data from a binary FITS table pzPendingImfileRow into the database
+bool summitImfileInsertObjects(
+    psDB            *dbh,               ///< Database handle
+    psArray         *objects            ///< array of summitImfileRow objects
+);
+
+/** Insert data from a binary FITS table summitImfileRow into the database
  *
  * This function expects a psFits object with a FITS table as the first
@@ -630,4 +439,389 @@
  */
 
+bool summitImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool summitImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a summitImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *summitImfileMetadataFromObject(
+    const summitImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A summitImfileRow pointer or NULL on error
+ */
+
+summitImfileRow *summitImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as summitImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *summitImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes a row from the database coresponding to an summitImfile
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+bool summitImfileDeleteObject(
+    psDB            *dbh,               ///< Database handle
+    const summitImfileRow *object    ///< Object to delete
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long summitImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** Formats and prints an array of summitImfileRow objects
+ *
+ * When mdcf is set the formated output is in psMetadataConfig
+ * format, otherwise it is in a simple tabular format.
+ *
+ * @return true on success
+ */
+
+bool summitImfilePrintObjects(
+    FILE            *stream,            ///< a stream
+    psArray         *objects,           ///< An array of summitImfileRow objects
+    bool            mdcf                ///< format as mdconfig or simple
+);
+/** pzPendingExpRow data structure
+ *
+ * Structure for representing a single row of pzPendingExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+} pzPendingExpRow;
+
+/** Creates a new pzPendingExpRow object
+ *
+ *  @return A new pzPendingExpRow object or NULL on failure.
+ */
+
+pzPendingExpRow *pzPendingExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope
+);
+
+/** Creates a new pzPendingExp table
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a pzPendingExp table
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope
+);
+
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzPendingExpDelete(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+
+/** Insert a single pzPendingExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    pzPendingExpRow *object             ///< pzPendingExpRow object
+);
+
+/** Insert an array of pzPendingExpRow object into a table
+ *
+ * This function constructs and inserts multiple rows based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsertObjects(
+    psDB            *dbh,               ///< Database handle
+    psArray         *objects            ///< array of pzPendingExpRow objects
+);
+
+/** Insert data from a binary FITS table pzPendingExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a pzPendingExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *pzPendingExpMetadataFromObject(
+    const pzPendingExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A pzPendingExpRow pointer or NULL on error
+ */
+
+pzPendingExpRow *pzPendingExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as pzPendingExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *pzPendingExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes a row from the database coresponding to an pzPendingExp
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+bool pzPendingExpDeleteObject(
+    psDB            *dbh,               ///< Database handle
+    const pzPendingExpRow *object    ///< Object to delete
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzPendingExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** Formats and prints an array of pzPendingExpRow objects
+ *
+ * When mdcf is set the formated output is in psMetadataConfig
+ * format, otherwise it is in a simple tabular format.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpPrintObjects(
+    FILE            *stream,            ///< a stream
+    psArray         *objects,           ///< An array of pzPendingExpRow objects
+    bool            mdcf                ///< format as mdconfig or simple
+);
+/** pzPendingImfileRow data structure
+ *
+ * Structure for representing a single row of pzPendingImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *class;
+    char            *class_id;
+    char            *exp_tag;
+} pzPendingImfileRow;
+
+/** Creates a new pzPendingImfileRow object
+ *
+ *  @return A new pzPendingImfileRow object or NULL on failure.
+ */
+
+pzPendingImfileRow *pzPendingImfileRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *class,
+    const char      *class_id,
+    const char      *exp_tag
+);
+
+/** Creates a new pzPendingImfile table
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a pzPendingImfile table
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *class,
+    const char      *class_id,
+    const char      *exp_tag
+);
+
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzPendingImfileDelete(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+
+/** Insert a single pzPendingImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    pzPendingImfileRow *object             ///< pzPendingImfileRow object
+);
+
+/** Insert an array of pzPendingImfileRow object into a table
+ *
+ * This function constructs and inserts multiple rows based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileInsertObjects(
+    psDB            *dbh,               ///< Database handle
+    psArray         *objects            ///< array of pzPendingImfileRow objects
+);
+
+/** Insert data from a binary FITS table pzPendingImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
 bool pzPendingImfileInsertFits(
     psDB            *dbh,               ///< Database handle
@@ -719,14 +913,403 @@
     bool            mdcf                ///< format as mdconfig or simple
 );
-/** newExpRow data structure
- *
- * Structure for representing a single row of newExp table data.
+/** pzDoneExpRow data structure
+ *
+ * Structure for representing a single row of pzDoneExp table data.
  */
 
 typedef struct {
-    char            *exp_tag;
     char            *exp_id;
     char            *camera;
     char            *telescope;
+} pzDoneExpRow;
+
+/** Creates a new pzDoneExpRow object
+ *
+ *  @return A new pzDoneExpRow object or NULL on failure.
+ */
+
+pzDoneExpRow *pzDoneExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope
+);
+
+/** Creates a new pzDoneExp table
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a pzDoneExp table
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope
+);
+
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzDoneExpDelete(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+
+/** Insert a single pzDoneExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    pzDoneExpRow    *object             ///< pzDoneExpRow object
+);
+
+/** Insert an array of pzDoneExpRow object into a table
+ *
+ * This function constructs and inserts multiple rows based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpInsertObjects(
+    psDB            *dbh,               ///< Database handle
+    psArray         *objects            ///< array of pzDoneExpRow objects
+);
+
+/** Insert data from a binary FITS table pzDoneExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a pzDoneExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *pzDoneExpMetadataFromObject(
+    const pzDoneExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A pzDoneExpRow pointer or NULL on error
+ */
+
+pzDoneExpRow *pzDoneExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as pzDoneExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *pzDoneExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes a row from the database coresponding to an pzDoneExp
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+bool pzDoneExpDeleteObject(
+    psDB            *dbh,               ///< Database handle
+    const pzDoneExpRow *object    ///< Object to delete
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzDoneExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** Formats and prints an array of pzDoneExpRow objects
+ *
+ * When mdcf is set the formated output is in psMetadataConfig
+ * format, otherwise it is in a simple tabular format.
+ *
+ * @return true on success
+ */
+
+bool pzDoneExpPrintObjects(
+    FILE            *stream,            ///< a stream
+    psArray         *objects,           ///< An array of pzDoneExpRow objects
+    bool            mdcf                ///< format as mdconfig or simple
+);
+/** pzDoneImfileRow data structure
+ *
+ * Structure for representing a single row of pzDoneImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *class;
+    char            *class_id;
+    char            *exp_tag;
+    char            *uri;
+} pzDoneImfileRow;
+
+/** Creates a new pzDoneImfileRow object
+ *
+ *  @return A new pzDoneImfileRow object or NULL on failure.
+ */
+
+pzDoneImfileRow *pzDoneImfileRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *class,
+    const char      *class_id,
+    const char      *exp_tag,
+    const char      *uri
+);
+
+/** Creates a new pzDoneImfile table
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a pzDoneImfile table
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *class,
+    const char      *class_id,
+    const char      *exp_tag,
+    const char      *uri
+);
+
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzDoneImfileDelete(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+
+/** Insert a single pzDoneImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    pzDoneImfileRow *object             ///< pzDoneImfileRow object
+);
+
+/** Insert an array of pzDoneImfileRow object into a table
+ *
+ * This function constructs and inserts multiple rows based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileInsertObjects(
+    psDB            *dbh,               ///< Database handle
+    psArray         *objects            ///< array of pzDoneImfileRow objects
+);
+
+/** Insert data from a binary FITS table pzDoneImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a pzDoneImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *pzDoneImfileMetadataFromObject(
+    const pzDoneImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A pzDoneImfileRow pointer or NULL on error
+ */
+
+pzDoneImfileRow *pzDoneImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as pzDoneImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *pzDoneImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes a row from the database coresponding to an pzDoneImfile
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+bool pzDoneImfileDeleteObject(
+    psDB            *dbh,               ///< Database handle
+    const pzDoneImfileRow *object    ///< Object to delete
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzDoneImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** Formats and prints an array of pzDoneImfileRow objects
+ *
+ * When mdcf is set the formated output is in psMetadataConfig
+ * format, otherwise it is in a simple tabular format.
+ *
+ * @return true on success
+ */
+
+bool pzDoneImfilePrintObjects(
+    FILE            *stream,            ///< a stream
+    psArray         *objects,           ///< An array of pzDoneImfileRow objects
+    bool            mdcf                ///< format as mdconfig or simple
+);
+/** newExpRow data structure
+ *
+ * Structure for representing a single row of newExp table data.
+ */
+
+typedef struct {
+    psU64           exp_tag;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    psTime*         dateobs;
     char            *exp_type;
     psS32           imfiles;
@@ -739,8 +1322,9 @@
 
 newExpRow *newExpRowAlloc(
-    const char      *exp_tag,
+    psU64           exp_tag,
     const char      *exp_id,
     const char      *camera,
     const char      *telescope,
+    psTime*         dateobs,
     const char      *exp_type,
     psS32           imfiles
@@ -774,8 +1358,9 @@
 bool newExpInsert(
     psDB            *dbh,               ///< Database handle
-    const char      *exp_tag,
+    psU64           exp_tag,
     const char      *exp_id,
     const char      *camera,
     const char      *telescope,
+    psTime*         dateobs,
     const char      *exp_type,
     psS32           imfiles
Index: /trunk/ippdb/tests/alloc.c
===================================================================
--- /trunk/ippdb/tests/alloc.c	(revision 10059)
+++ /trunk/ippdb/tests/alloc.c	(revision 10060)
@@ -11,5 +11,5 @@
         summitExpRow    *object;
 
-        object = summitExpRowAlloc("a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string"    );
+        object = summitExpRowAlloc("a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string", -32    );
 
         if (!object) {
@@ -40,4 +40,53 @@
             exit(EXIT_FAILURE);
         }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        summitImfileRow *object;
+
+        object = summitImfileRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->bytes == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->md5sum, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
 
         psFree(object);
@@ -47,5 +96,5 @@
         pzPendingExpRow *object;
 
-        object = pzPendingExpRowAlloc("a string", "a string", "a string", "a string", -32    );
+        object = pzPendingExpRowAlloc("a string", "a string", "a string"    );
 
         if (!object) {
@@ -65,12 +114,4 @@
             exit(EXIT_FAILURE);
         }
-        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (!object->imfiles == -32) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
 
         psFree(object);
@@ -80,5 +121,5 @@
         pzPendingImfileRow *object;
 
-        object = pzPendingImfileRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", "a string"    );
+        object = pzPendingImfileRowAlloc("a string", "a string", "a string", "a string", "a string", "a string"    );
 
         if (!object) {
@@ -98,12 +139,4 @@
             exit(EXIT_FAILURE);
         }
-        if (!object->bytes == -32) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->md5sum, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
         if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
             psFree(object);
@@ -114,4 +147,70 @@
             exit(EXIT_FAILURE);
         }
+        if (strncmp(object->exp_tag, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        pzDoneExpRow    *object;
+
+        object = pzDoneExpRowAlloc("a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        pzDoneImfileRow *object;
+
+        object = pzDoneImfileRowAlloc("a string", "a string", "a string", "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_tag, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
         if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
             psFree(object);
@@ -125,11 +224,10 @@
         newExpRow       *object;
 
-        object = newExpRowAlloc("a string", "a string", "a string", "a string", "a string", -32    );
-
-        if (!object) {
-            exit(EXIT_FAILURE);
-        }
-
-        if (strncmp(object->exp_tag, "a string", MAX_STRING_LENGTH)) {
+        object = newExpRowAlloc(64, "a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
             psFree(object);
             exit(EXIT_FAILURE);
@@ -144,4 +242,7 @@
         }
         if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
             psFree(object);
             exit(EXIT_FAILURE);
Index: /trunk/ippdb/tests/createtable.c
===================================================================
--- /trunk/ippdb/tests/createtable.c	(revision 10059)
+++ /trunk/ippdb/tests/createtable.c	(revision 10060)
@@ -28,4 +28,19 @@
         }
 
+        if(!summitImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
         if(!pzPendingExpCreateTable(dbh)) {
             exit(EXIT_FAILURE);
@@ -44,4 +59,34 @@
 
         if(!pzPendingImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!pzDoneExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!pzDoneImfileCreateTable(dbh)) {
             exit(EXIT_FAILURE);
         }
Index: /trunk/ippdb/tests/dbcleanup.c
===================================================================
--- /trunk/ippdb/tests/dbcleanup.c	(revision 10059)
+++ /trunk/ippdb/tests/dbcleanup.c	(revision 10060)
@@ -12,6 +12,9 @@
 
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS summitExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS summitImfile");
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingExp");
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzDoneExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzDoneImfile");
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newExp");
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newImfile");
Index: /trunk/ippdb/tests/dbsetup.c
===================================================================
--- /trunk/ippdb/tests/dbsetup.c	(revision 10059)
+++ /trunk/ippdb/tests/dbsetup.c	(revision 10060)
@@ -16,4 +16,7 @@
     summitExpCreateTable(dbh);
 
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS summitImfile");
+    summitImfileCreateTable(dbh);
+
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingExp");
     pzPendingExpCreateTable(dbh);
@@ -21,4 +24,10 @@
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingImfile");
     pzPendingImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzDoneExp");
+    pzDoneExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzDoneImfile");
+    pzDoneImfileCreateTable(dbh);
 
     p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newExp");
Index: /trunk/ippdb/tests/droptable.c
===================================================================
--- /trunk/ippdb/tests/droptable.c	(revision 10059)
+++ /trunk/ippdb/tests/droptable.c	(revision 10060)
@@ -28,4 +28,19 @@
         }
 
+        if (!summitImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
         if (!pzPendingExpDropTable(dbh)) {
             exit(EXIT_FAILURE);
@@ -44,4 +59,34 @@
 
         if (!pzPendingImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneImfileDropTable(dbh)) {
             exit(EXIT_FAILURE);
         }
Index: /trunk/ippdb/tests/insert.c
===================================================================
--- /trunk/ippdb/tests/insert.c	(revision 10059)
+++ /trunk/ippdb/tests/insert.c	(revision 10060)
@@ -13,50 +13,95 @@
         }
 
-        if (!summitExpInsert(dbh, "a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string")) {
-            exit(EXIT_FAILURE);
-        }
-
-        psDBCleanup(dbh);
-    }
-
-    {
-        psDB            *dbh;
-
-        dbh = psDBInit("localhost", "test", NULL, "test");
-        if (!dbh) {
-            exit(EXIT_FAILURE);
-        }
-
-        if (!pzPendingExpInsert(dbh, "a string", "a string", "a string", "a string", -32)) {
-            exit(EXIT_FAILURE);
-        }
-
-        psDBCleanup(dbh);
-    }
-
-    {
-        psDB            *dbh;
-
-        dbh = psDBInit("localhost", "test", NULL, "test");
-        if (!dbh) {
-            exit(EXIT_FAILURE);
-        }
-
-        if (!pzPendingImfileInsert(dbh, "a string", "a string", "a string", -32, "a string", "a string", "a string", "a string")) {
-            exit(EXIT_FAILURE);
-        }
-
-        psDBCleanup(dbh);
-    }
-
-    {
-        psDB            *dbh;
-
-        dbh = psDBInit("localhost", "test", NULL, "test");
-        if (!dbh) {
-            exit(EXIT_FAILURE);
-        }
-
-        if (!newExpInsert(dbh, "a string", "a string", "a string", "a string", "a string", -32)) {
+        if (!summitExpInsert(dbh, "a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string", -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitImfileInsert(dbh, "a string", "a string", "a string", -32, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpInsert(dbh, "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfileInsert(dbh, "a string", "a string", "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneExpInsert(dbh, "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneImfileInsert(dbh, "a string", "a string", "a string", "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpInsert(dbh, 64, "a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", -32)) {
             exit(EXIT_FAILURE);
         }
Index: /trunk/ippdb/tests/insertfits.c
===================================================================
--- /trunk/ippdb/tests/insertfits.c	(revision 10059)
+++ /trunk/ippdb/tests/insertfits.c	(revision 10060)
@@ -50,4 +50,30 @@
         }
 
+        if (!summitImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
         if (!pzPendingExpInsertFits(dbh, fits)) {
             exit(EXIT_FAILURE);
@@ -77,4 +103,56 @@
 
         if (!pzPendingImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneImfileInsertFits(dbh, fits)) {
             exit(EXIT_FAILURE);
         }
Index: /trunk/ippdb/tests/insertobject.c
===================================================================
--- /trunk/ippdb/tests/insertobject.c	(revision 10059)
+++ /trunk/ippdb/tests/insertobject.c	(revision 10060)
@@ -14,5 +14,5 @@
         }
 
-        object = summitExpRowAlloc("a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string");
+        object = summitExpRowAlloc("a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string", -32);
         if (!object) {
             exit(EXIT_FAILURE);
@@ -29,4 +29,26 @@
     {
         psDB            *dbh;
+        summitImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = summitImfileRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
         pzPendingExpRow *object;
 
@@ -36,5 +58,5 @@
         }
 
-        object = pzPendingExpRowAlloc("a string", "a string", "a string", "a string", -32);
+        object = pzPendingExpRowAlloc("a string", "a string", "a string");
         if (!object) {
             exit(EXIT_FAILURE);
@@ -58,5 +80,5 @@
         }
 
-        object = pzPendingImfileRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", "a string");
+        object = pzPendingImfileRowAlloc("a string", "a string", "a string", "a string", "a string", "a string");
         if (!object) {
             exit(EXIT_FAILURE);
@@ -73,4 +95,48 @@
     {
         psDB            *dbh;
+        pzDoneExpRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzDoneExpRowAlloc("a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        pzDoneImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzDoneImfileRowAlloc("a string", "a string", "a string", "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
         newExpRow       *object;
 
@@ -80,5 +146,5 @@
         }
 
-        object = newExpRowAlloc("a string", "a string", "a string", "a string", "a string", -32);
+        object = newExpRowAlloc(64, "a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", -32);
         if (!object) {
             exit(EXIT_FAILURE);
Index: /trunk/ippdb/tests/metadatafromobject.c
===================================================================
--- /trunk/ippdb/tests/metadatafromobject.c	(revision 10059)
+++ /trunk/ippdb/tests/metadatafromobject.c	(revision 10060)
@@ -13,5 +13,5 @@
         bool            status;
 
-        object = summitExpRowAlloc("a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string");
+        object = summitExpRowAlloc("a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", "a string", -32);
         if (!object) {
             exit(EXIT_FAILURE);
@@ -48,4 +48,61 @@
             exit(EXIT_FAILURE);
         }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        summitImfileRow *object;
+        bool            status;
+
+        object = summitImfileRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = summitImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "bytes") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "md5sum"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
 
         psFree(md);
@@ -57,5 +114,5 @@
         bool            status;
 
-        object = pzPendingExpRowAlloc("a string", "a string", "a string", "a string", -32);
+        object = pzPendingExpRowAlloc("a string", "a string", "a string");
         if (!object) {
             exit(EXIT_FAILURE);
@@ -81,12 +138,4 @@
             exit(EXIT_FAILURE);
         }
-        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
 
         psFree(md);
@@ -98,5 +147,5 @@
         bool            status;
 
-        object = pzPendingImfileRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", "a string");
+        object = pzPendingImfileRowAlloc("a string", "a string", "a string", "a string", "a string", "a string");
         if (!object) {
             exit(EXIT_FAILURE);
@@ -122,12 +171,4 @@
             exit(EXIT_FAILURE);
         }
-        if (!psMetadataLookupS32(&status, md, "bytes") == -32) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(psMetadataLookupPtr(&status, md, "md5sum"), "a string", MAX_STRING_LENGTH)) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
         if (strncmp(psMetadataLookupPtr(&status, md, "class"), "a string", MAX_STRING_LENGTH)) {
             psFree(md);
@@ -138,4 +179,86 @@
             exit(EXIT_FAILURE);
         }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_tag"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        pzDoneExpRow    *object;
+        bool            status;
+
+        object = pzDoneExpRowAlloc("a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = pzDoneExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        pzDoneImfileRow *object;
+        bool            status;
+
+        object = pzDoneImfileRowAlloc("a string", "a string", "a string", "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = pzDoneImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_tag"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
         if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
             psFree(md);
@@ -151,5 +274,5 @@
         bool            status;
 
-        object = newExpRowAlloc("a string", "a string", "a string", "a string", "a string", -32);
+        object = newExpRowAlloc(64, "a string", "a string", "a string", "0001-01-01T00:00:00Z", "a string", -32);
         if (!object) {
             exit(EXIT_FAILURE);
@@ -163,5 +286,4 @@
         psFree(object);
 
-        if (strncmp(psMetadataLookupPtr(&status, md, "exp_tag"), "a string", MAX_STRING_LENGTH)) {
             psFree(md);
             exit(EXIT_FAILURE);
@@ -176,4 +298,7 @@
         }
         if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
             psFree(md);
             exit(EXIT_FAILURE);
Index: /trunk/ippdb/tests/objectfrommetadata.c
===================================================================
--- /trunk/ippdb/tests/objectfrommetadata.c	(revision 10059)
+++ /trunk/ippdb/tests/objectfrommetadata.c	(revision 10060)
@@ -36,4 +36,8 @@
             exit(EXIT_FAILURE);
         }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
 
         object = summitExpObjectFromMetadata(md);
@@ -68,4 +72,90 @@
             exit(EXIT_FAILURE);
         }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        summitImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "bytes", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = summitImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->bytes == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->md5sum, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
 
         psFree(object);
@@ -89,4 +179,234 @@
             exit(EXIT_FAILURE);
         }
+
+        object = pzPendingExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        pzPendingImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_tag", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_tag, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        pzDoneExpRow    *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzDoneExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        pzDoneImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_tag", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzDoneImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_tag, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        newExpRow       *object;
+
+        md = psMetadataAlloc();
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
         if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
             psFree(md);
@@ -98,12 +418,15 @@
         }
 
-        object = pzPendingExpObjectFromMetadata(md);
-        if (!object) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-
-        psFree(md);
-
+        object = newExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
         if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
             psFree(object);
@@ -118,149 +441,4 @@
             exit(EXIT_FAILURE);
         }
-        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (!object->imfiles == -32) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-
-        psFree(object);
-    }
-
-    {
-        psMetadata      *md;
-        pzPendingImfileRow *object;
-
-        md = psMetadataAlloc();
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddS32(md, PS_LIST_TAIL, "bytes", 0, NULL, -32)) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-
-        object = pzPendingImfileObjectFromMetadata(md);
-        if (!object) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-
-        psFree(md);
-
-        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (!object->bytes == -32) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->md5sum, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-
-        psFree(object);
-    }
-
-    {
-        psMetadata      *md;
-        newExpRow       *object;
-
-        md = psMetadataAlloc();
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_tag", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-
-        object = newExpObjectFromMetadata(md);
-        if (!object) {
-            psFree(md);
-            exit(EXIT_FAILURE);
-        }
-
-        psFree(md);
-
-        if (strncmp(object->exp_tag, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
-            psFree(object);
-            exit(EXIT_FAILURE);
-        }
-        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
             psFree(object);
             exit(EXIT_FAILURE);
Index: /trunk/ippdb/tests/selectrowsfits.c
===================================================================
--- /trunk/ippdb/tests/selectrowsfits.c	(revision 10059)
+++ /trunk/ippdb/tests/selectrowsfits.c	(revision 10060)
@@ -43,4 +43,26 @@
         }
 
+        if (!summitImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
         if (!pzPendingExpSelectRowsFits(dbh, fits, NULL, 1)) {
             exit(EXIT_FAILURE);
@@ -66,4 +88,48 @@
 
         if (!pzPendingImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzDoneImfileSelectRowsFits(dbh, fits, NULL, 1)) {
             exit(EXIT_FAILURE);
         }
