Index: /trunk/ippTools/src/pztool.c
===================================================================
--- /trunk/ippTools/src/pztool.c	(revision 17654)
+++ /trunk/ippTools/src/pztool.c	(revision 17655)
@@ -2,5 +2,5 @@
  * pztool.c
  *
- * Copyright (C) 2006  Joshua Hoblitt
+ * Copyright (C) 2006-2008  Joshua Hoblitt
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -27,4 +27,5 @@
 #include <inttypes.h>
 
+#include "pslib.h"
 #include "pxtools.h"
 #include "pxdata.h"
@@ -41,4 +42,5 @@
 static bool updatecopiedMode(pxConfig *config);
 static bool revertcopiedMode(pxConfig *config);
+static bool advanceMode(pxConfig *config);
 
 static bool copydoneCompleteExp(pxConfig *config, const char *exp_name, const char *camera, const char *telescope);
@@ -75,4 +77,5 @@
         MODECASE(PZTOOL_MODE_UPDATECOPIED, updatecopiedMode);
         MODECASE(PZTOOL_MODE_REVERTCOPIED, revertcopiedMode);
+        MODECASE(PZTOOL_MODE_ADVANCE, advanceMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -360,6 +363,16 @@
     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
 
-    // need to know exp_name, camera, telescope, class, class_id (to find the
-    // pzDownloadImfile entry and the URI for the newImfile entry.
+    if (!pzDownloadImfileInsert(config->dbh,
+            exp_name,
+            camera,
+            telescope,
+            class,
+            class_id,
+            uri,
+            code
+    )) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
 
     // start a transaction so it's all rows or nothing
@@ -367,45 +380,4 @@
         psError(PS_ERR_UNKNOWN, false, "database error");
         return false;
-    }
-
-    // cp the imfile into pzDownloadImfile
-    {
-        char *query =
-            "INSERT INTO pzDownloadImfile"
-            "   SELECT"
-            "       exp_name,"
-            "       camera,"
-            "       telescope,"
-            "       class,"
-            "       class_id,"
-            "       '%s'," // uri of downloaded file
-            "       '%d'" // fault code
-            "   FROM summitImfile"
-            "   WHERE"
-            "       summitImfile.exp_name = '%s'"
-            "       AND summitImfile.camera = '%s'"
-            "       AND summitImfile.telescope = '%s'"
-            "       AND summitImfile.class = '%s'"
-            "       AND summitImfile.class_id = '%s'";
-
-        if (!p_psDBRunQuery(config->dbh, query, uri, code, exp_name, camera, telescope, class, class_id)) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "database error");
-            return false;
-        } 
-
-        // sanity check: we should have inserted only one row
-        psU64 affected = psDBAffectedRows(config->dbh);
-        if (psDBAffectedRows(config->dbh) != 1) {
-            // rollback
-            if (!psDBRollback(config->dbh)) {
-                psError(PS_ERR_UNKNOWN, false, "database error");
-            }
-            psError(PS_ERR_UNKNOWN, false, "should have affected 1 row but %" PRIu64 " rows were modified", affected);
-            return false;
-        }
     }
 
@@ -434,4 +406,6 @@
 static bool copydoneCompleteExp(pxConfig *config, const char *exp_name, const char *camera, const char *telescope)
 {
+    // THIS FUNCTION MUST BE INVOKED FROM INSIDE A TRANSACTION!!!
+    
     PS_ASSERT_PTR_NON_NULL(config, false);
 
@@ -440,5 +414,4 @@
     // these options are thrown away unless we just -copydone'd the last imfile
     // in an exp.  
-    // This function MUST NOT be invoked from anywhere but copydoneMode().
  
     // optional
@@ -457,6 +430,35 @@
     }
 
-    psStringAppend(&query, "WHERE exp_name = '%s' AND telescope = '%s' AND camera = '%s'",
-                          exp_name, telescope, camera);
+    psMetadata *where = psMetadataAlloc();
+    if (exp_name) {
+        if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_name", 0, "==", exp_name)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_name");
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (camera) {
+        if (!psMetadataAddStr(where, PS_LIST_TAIL, "camera", 0, "==", camera)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (telescope) {
+        if (!psMetadataAddStr(where, PS_LIST_TAIL, "telescope", 0, "==", telescope)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+            psFree(where);
+            return false;
+        }
+    }
+
+    if (config->where) {
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
 
     if (!p_psDBRunQuery(config->dbh, query)) {
@@ -736,4 +738,38 @@
 
 
+static bool advanceMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // start a transaction so it's all rows or nothing
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!copydoneCompleteExp(config, NULL, NULL, NULL)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "copydoneCompleteExp() failed");
+        return false;
+    }
+
+    // point of no return
+    if (!psDBCommit(config->dbh)) {
+        // rollback
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+
+    return true;
+}
+
+
 static bool pzDownloadExpSetState(pxConfig *config, const char *exp_name, const char *camera, const char *telescope, const char *state)
 {
Index: /trunk/ippTools/src/pztool.h
===================================================================
--- /trunk/ippTools/src/pztool.h	(revision 17654)
+++ /trunk/ippTools/src/pztool.h	(revision 17655)
@@ -33,5 +33,6 @@
     PZTOOL_MODE_COPIED,
     PZTOOL_MODE_UPDATECOPIED,
-    PZTOOL_MODE_REVERTCOPIED
+    PZTOOL_MODE_REVERTCOPIED,
+    PZTOOL_MODE_ADVANCE
 } pztoolMode;
 
Index: /trunk/ippTools/src/pztoolConfig.c
===================================================================
--- /trunk/ippTools/src/pztoolConfig.c	(revision 17654)
+++ /trunk/ippTools/src/pztoolConfig.c	(revision 17655)
@@ -176,4 +176,17 @@
             "search by fault code", 0);
 
+    // -advance
+    psMetadata *advanceArgs = psMetadataAlloc();
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-workdir",  0,
+        "define the \"default\" workdir for this exposure", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-dvodb",  0,
+        "define the dvodb for the next processing step", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-tess_id",  0,
+        "define the tess_id for the next processing step", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-end_stage",  0,
+        "define the end goal processing step", NULL);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-label",  0,
+        "define the label for the chip stage", NULL);
+
     psMetadata *argSets = psMetadataAlloc();
     psMetadata *modes = psMetadataAlloc();
@@ -188,4 +201,5 @@
     PXOPT_ADD_MODE("-updatecopied",    "", PZTOOL_MODE_UPDATECOPIED,updatecopiedArgs);
     PXOPT_ADD_MODE("-revertcopied",    "", PZTOOL_MODE_REVERTCOPIED,revertcopiedArgs);
+    PXOPT_ADD_MODE("-advance",          "", PZTOOL_MODE_ADVANCE,    advanceArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
