Index: trunk/ippTools/src/dettool.c
===================================================================
--- trunk/ippTools/src/dettool.c	(revision 7471)
+++ trunk/ippTools/src/dettool.c	(revision 7509)
@@ -34,4 +34,5 @@
 static detInputExpRow *rawDetrenTodetInputExpRow(rawDetrendExpRow *rawExp, psS32 det_id, psS32 iteration);
 static psArray *searchRawImfiles(pxConfig *config, psMetadata *where);
+static psS32 incrementIteration(pxConfig *config, const char *det_id);
 
 # define MODECASE(caseName, func) \
@@ -95,15 +96,4 @@
         return false;
     }
-
-    // start a transaction so we don't end up with orphaned det_ids
-    if (!psDBTransaction(config->dbh)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
-    // grab the 'position' column's value as the new det_id
-    // the first iteration is always 0
-    detRunInsert(config->dbh, det_type);
-    long det_id = psDBLastInsertID(config->dbh);
     
     // we have to support multipe exp_ids
@@ -128,19 +118,11 @@
                 psError(PS_ERR_UNKNOWN, true,
                         "at least one -exp_id is required");
-                // rollback
-                if (!psDBRollback(config->dbh)) {
-                    psError(PS_ERR_UNKNOWN, false, "database error");
-                }
                 psFree(where);
                 return false;
             }
 
-            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id",
-                        PS_META_DUPLICATE_OK, "==", exp_id)) {
+            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id", 0, "==",
+                        exp_id)) {
                 psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
-                // rollback
-                if (!psDBRollback(config->dbh)) {
-                    psError(PS_ERR_UNKNOWN, false, "database error");
-                }
                 psFree(iter);
                 psFree(where);
@@ -150,8 +132,4 @@
         psFree(iter);
     } else {
-        // rollback
-        if (!psDBRollback(config->dbh)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-        }
         psAbort(config->argv[0],
                 "-exp_id was not parsed correctly (this should not happen");
@@ -168,33 +146,24 @@
     if (!detrendExps) {
         psError(PS_ERR_UNKNOWN, false, "no rawDetrendExp rows found");
-        // rollback
-        if (!psDBRollback(config->dbh)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-        }
-        return false;
-    }
-
-    if (item->type == PS_DATA_METADATA_MULTI) {
-        // we should have one rawDetrendExp row be exp_id specified
-        if (psListLength(item->data.list) != psArrayLength(detrendExps)) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psAbort(config->argv[0],
-        "an -exp_id matched more then one rawDetrendExp (this should not happen");
-
-        }
-    } else {
-        // we should have matched only one exp_id
-        if (psArrayLength(detrendExps) != 1) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psAbort(config->argv[0],
-        "-exp_id matched more then one rawDetrendExp (this should not happen");
-        }
-    }
+        return false;
+    }
+
+    // we should have one rawDetrendExp row be exp_id specified
+    if (psListLength(item->data.list) != psArrayLength(detrendExps)) {
+        psAbort(config->argv[0],
+    "an -exp_id matched more then one rawDetrendExp (this should not happen");
+
+    }
+
+    // start a transaction so we don't end up with orphaned det_ids
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    // grab the 'position' column's value as the new det_id
+    // the first iteration is always 0
+    detRunInsert(config->dbh, det_type, 0);
+    long det_id = psDBLastInsertID(config->dbh);
 
     // create new detInputExp row(s) from the rawDetrendExp row(s)
@@ -1809,18 +1778,28 @@
         return false;
     }
+
     psList *exp_id_list = item->data.list;
-
+    psMetadata *where = psMetadataAlloc();
     // make sure that -exp_id was parsed correctly
     // XXX this can be removed someday
     if (item->type == PS_DATA_METADATA_MULTI) {
-        psListIterator *iter = psListIteratorAlloc(exp_id_list, 0, false);
+        psListIterator *iter = psListIteratorAlloc(item->data.list, 0, false);
         psMetadataItem *mItem = NULL;
         while ((mItem = psListGetAndIncrement(iter))) {
             psString exp_id = mItem->data.V;
             // if exp_id is NULL then it means that -exp_id has not been
-            // specified or something really bad happened
+            // specified
             if (!exp_id) {
                 psError(PS_ERR_UNKNOWN, true,
                         "at least one -exp_id is required");
+                psFree(where);
+                return false;
+            }
+
+            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id", 
+                        PS_META_DUPLICATE_OK, "==", exp_id)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+                psFree(iter);
+                psFree(where);
                 return false;
             }
@@ -1836,5 +1815,4 @@
 
     // add the det_id & iteration == 0 to the where claus
-    psMetadata *where = psMetadataAlloc();
     if (!psMetadataAddS32(where, PS_LIST_TAIL, "det_id", 0, "==",
                 (psS32)atol(det_id))) {
@@ -1853,4 +1831,5 @@
     if (!detrendExps) {
         psError(PS_ERR_UNKNOWN, false, "no rawDetrendExp rows found");
+        psFree(where);
         return false;
     }
@@ -1861,25 +1840,120 @@
         psHashAdd(valid_exp_ids,
             ((detInputExpRow *)detrendExps->data[i])->exp_id,
-            ((detInputExpRow *)detrendExps->data[i])->exp_id
+            detrendExps->data[i]
         );
     }
 
+    // start a transaction so we don't end up with an incremented iteration
+    // count but no detInputExps
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(valid_exp_ids);
+        return false;
+    }
+
+    // up the detRuns iteration count
+    psS32 newIteration = incrementIteration(config, det_id);
+    if (!newIteration) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psFree(valid_exp_ids);
+        return false;
+    }
+
+    // check exp_ids and build up an array of new detInputExp rows at the same
+    // time
     psListIterator *iter = psListIteratorAlloc(exp_id_list, 0, false);
     psMetadataItem *mItem = NULL;
+    psArray *newInputExps = psArrayAlloc(psListLength(exp_id_list));
     while ((mItem = psListGetAndIncrement(iter))) {
-        if (!psHashLookup(valid_exp_ids, (char *)mItem->data.V)) {
+        detInputExpRow *inputExp = psHashLookup(valid_exp_ids,
+                (char *)mItem->data.V); 
+        if (!inputExp) {
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
             // invalid exp_id
             psError(PS_ERR_UNKNOWN, false, "exp_id %s is invalid for det_id %s",
                     (char *)mItem->data.V, det_id);
+            psFree(iter);
             psFree(valid_exp_ids);
-            psFree(iter);
             return false;
         }
-    }
+        psArrayAdd(newInputExps, 0, detInputExpRowAlloc(
+            (psS32)atol(det_id),
+            newIteration,
+            inputExp->exp_id,
+            inputExp->camera,
+            inputExp->telescope,
+            inputExp->exp_type,
+            inputExp->imfiles,
+            inputExp->filter,
+            inputExp->stats
+        ));
+    }
+    psFree(iter);
     psFree(valid_exp_ids);
-    psFree(iter);
-
-    psFree(exp_id_list);
+
+    for (long i = 0; i < psArrayLength(newInputExps); i++) {
+        if (!detInputExpInsertObject(config->dbh, newInputExps->data[i])) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            // rollback
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+    }
+
+    // point of no return for det_id creation
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
 
     return true;
 }
+
+static psS32 incrementIteration(pxConfig *config, const char *det_id)
+{
+    // this function returns zero on error
+    PS_ASSERT_PTR_NON_NULL(config, 0);
+    PS_ASSERT_PTR_NON_NULL(det_id, 0);
+
+    char *query = "UPDATE detRun SET iteration = iteration + 1 WHERE position = '%s'";
+    if (!p_psDBRunQuery(config->dbh, query, det_id)) {
+        psError(PS_ERR_UNKNOWN, false,
+                "failed to increment iteration for det_id %s", det_id);
+        return 0;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+    if (!psMetadataAddS32(where, PS_LIST_TAIL, "position", 0, "==",
+                (psS32)atol(det_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(where);
+        return 0;
+    }
+
+    psArray *detRuns = detRunSelectRowObjects(config->dbh, where, 0);
+    psFree(where);
+    if (!detRuns) {
+        psError(PS_ERR_UNKNOWN, false, "no detRun rows found");
+        return 0;
+    }
+
+    // sanity check the database
+    if (psArrayLength(detRuns) != 1) {
+        // this should no happen
+        psAbort(config->argv[0],
+                "database query return too many rows (this should not happen");
+    }
+
+    psS32 newIteration = ((detRunRow *)detRuns->data[0])->iteration;
+    psFree(detRuns);
+
+    return newIteration;
+}
