Index: trunk/ippTools/share/Makefile.am
===================================================================
--- trunk/ippTools/share/Makefile.am	(revision 37439)
+++ trunk/ippTools/share/Makefile.am	(revision 37551)
@@ -8,4 +8,8 @@
 	addtool_find_cam_id_dvo.sql \
 	addtool_find_cam_id.sql \
+	addtool_find_diff_id.sql \
+	addtool_find_diff_id_dvo.sql \
+	addtool_find_ff_id.sql \
+	addtool_find_ff_id_dvo.sql \
 	addtool_find_skycal_id_dvo.sql \
 	addtool_find_skycal_id.sql \
@@ -16,4 +20,6 @@
 	addtool_find_pendingexp.sql \
 	addtool_find_pendingexp_cam.sql \
+	addtool_find_pendingexp_diff.sql \
+	addtool_find_pendingexp_ff.sql \
 	addtool_find_pendingexp_skycal.sql \
 	addtool_find_pendingexp_stack.sql \
@@ -21,4 +27,6 @@
 	addtool_find_pendingmergeprocess.sql \
 	addtool_find_processedexp_cam.sql \
+	addtool_find_processedexp_diff.sql \
+	addtool_find_processedexp_ff.sql \
 	addtool_find_processedexp_skycal.sql \
 	addtool_find_processedexp_stack.sql \
@@ -29,4 +37,6 @@
 	addtool_pendingcleanuprun.sql \
 	addtool_queue_cam_id.sql \
+	addtool_queue_diff_id.sql \
+	addtool_queue_ff_id.sql \
 	addtool_queue_stack_id.sql \
 	addtool_queue_sky_id_multi.sql \
@@ -35,4 +45,6 @@
 	addtool_revertminidvodbprocessed.sql \
 	addtool_revertprocessedexp_cam.sql \
+	addtool_revertprocessedexp_diff.sql \
+	addtool_revertprocessedexp_ff.sql \
 	addtool_revertprocessedexp_skycal.sql \
 	addtool_revertprocessedexp_stack.sql \
Index: trunk/ippTools/share/addtool_find_diff_id.sql
===================================================================
--- trunk/ippTools/share/addtool_find_diff_id.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_diff_id.sql	(revision 37551)
@@ -0,0 +1,22 @@
+SELECT
+     diffRun.*, diffInputSkyfile.diff_skyfile_id
+FROM 
+     diffInputSkyfile 
+JOIN diffSkyfile using (diff_id, skycell_id) 
+JOIN diffRun using (diff_id)
+
+LEFT JOIN (SELECT diff_id       AS added_diff_id,
+                  addRun.dvodb AS previous_dvodb
+           FROM addRun
+JOIN diffRun on (diff_id = stage_id and addRun.stage = 'diff')
+          ) as foo
+     ON diff_id = added_diff_id 
+     -- AND stage = 'diff'
+     -- hook for qualifying the join on the previous_dvodb
+     AND %s
+WHERE
+    diffRun.state = 'full'
+    AND diffSkyfile.fault = 0
+    AND diffSkyfile.quality = 0
+    AND added_diff_id IS NULL
+    -- addtool adds checks on exposure being added to the dvodb previously
Index: trunk/ippTools/share/addtool_find_diff_id_dvo.sql
===================================================================
--- trunk/ippTools/share/addtool_find_diff_id_dvo.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_diff_id_dvo.sql	(revision 37551)
@@ -0,0 +1,15 @@
+SELECT diffRun.*, diffInputSkyfile.diff_skyfile_id 
+FROM 
+     diffInputSkyfile 
+JOIN diffSkyfile using (diff_id, skycell_id) 
+JOIN diffRun using (diff_id)
+
+
+diffRun JOIN diffSkyfile using (diff_id)
+
+WHERE diffRun.state = 'full' and diffSkyfile.quality = 0
+    AND diffRun.diff_id NOT IN (SELECT diffRun.diff_id
+       FROM addRun
+       JOIN diffRun on (diffRun.diff_id = addRun.stage_id and addRun.stage = 'diff') JOIN diffSkyfile on (diffRun.diff_id = diffSkyfile.diff_id)
+       WHERE addRun.stage = 'diff' AND %s
+      )
Index: trunk/ippTools/share/addtool_find_ff_id.sql
===================================================================
--- trunk/ippTools/share/addtool_find_ff_id.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_ff_id.sql	(revision 37551)
@@ -0,0 +1,21 @@
+SELECT
+     fullForceRun.*, fullForceResult.warp_id
+FROM 
+     fullForceRun
+JOIN fullForceResult using (ff_id)
+
+LEFT JOIN (SELECT ff_id       AS added_ff_id,
+                  addRun.dvodb AS previous_dvodb
+           FROM addRun
+JOIN fullForceRun on (ff_id = stage_id and addRun.stage = 'fullforce')
+          ) as foo
+     ON ff_id = added_ff_id 
+     --AND stage = 'skycal'
+     -- hook for qualifying the join on the previous_dvodb
+     AND %s
+WHERE
+    fullForceRun.state = 'full'
+    AND fullForceResult.quality = 0
+    AND fullForceResult.fault = 0 
+    AND added_ff_id IS NULL
+    -- addtool adds checks on exposure being added to the dvodb previously
Index: trunk/ippTools/share/addtool_find_ff_id_dvo.sql
===================================================================
--- trunk/ippTools/share/addtool_find_ff_id_dvo.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_ff_id_dvo.sql	(revision 37551)
@@ -0,0 +1,8 @@
+SELECT fullForceRun.*, fullForceResult.warp_id FROM fullForceRun JOIN fullForceResult using (ff_id)
+
+WHERE fullForceRun.state = 'full' and fullForceResult.quality = 0
+    AND fullForceRun.ff_id NOT IN (SELECT fullForceRun.ff_id
+       FROM addRun
+       JOIN fullForceRun on (fullForceRun.ff_id = addRun.stage_id and addRun.stage = 'fullforce') JOIN fullForceResult on (fullForceRun.ff_id = fullForceResult.ff_id)
+       WHERE addRun.stage = 'fullforce' AND %s
+      )
Index: trunk/ippTools/share/addtool_find_pendingexp_diff.sql
===================================================================
--- trunk/ippTools/share/addtool_find_pendingexp_diff.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_pendingexp_diff.sql	(revision 37551)
@@ -0,0 +1,21 @@
+   SELECT
+    addRun.*,
+    diffSkyfile.path_base as stageroot,
+    "NULL",
+    "NULL"
+FROM addRun
+JOIN diffInputSkyfile
+    ON (diff_id = stage_id and diff_skyfile_id = stage_extra1 and stage = "diff")
+JOIN diffSkyfile
+    USING (diff_id, skycell_id)
+JOIN diffRun
+    using(diff_id)
+LEFT JOIN addProcessedExp using (add_id)
+LEFT JOIN addMask
+    ON addRun.label = addMask.label
+WHERE
+    diffRun.state = 'full'
+    AND ((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
+    AND addRun.dvodb IS NOT NULL
+    AND addRun.workdir IS NOT NULL
+    AND addMask.label IS NULL
Index: trunk/ippTools/share/addtool_find_pendingexp_ff.sql
===================================================================
--- trunk/ippTools/share/addtool_find_pendingexp_ff.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_pendingexp_ff.sql	(revision 37551)
@@ -0,0 +1,19 @@
+   SELECT
+    addRun.*,
+    fullForceResult.path_base as stageroot,
+    "NULL",
+    "NULL"
+FROM addRun
+JOIN fullForceResult
+    ON (ff_id = stage_id and warp_id = stage_extra1 and stage = "fullforce")
+JOIN fullForceRun
+    using(ff_id)
+LEFT JOIN addProcessedExp using (add_id)
+LEFT JOIN addMask
+    ON addRun.label = addMask.label
+WHERE
+    fullForceRun.state = 'full'
+    AND ((addRun.state = 'new' AND addProcessedExp.add_id IS NULL) OR addRun.state = 'update')
+    AND addRun.dvodb IS NOT NULL
+    AND addRun.workdir IS NOT NULL
+    AND addMask.label IS NULL
Index: trunk/ippTools/share/addtool_find_processedexp_diff.sql
===================================================================
--- trunk/ippTools/share/addtool_find_processedexp_diff.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_processedexp_diff.sql	(revision 37551)
@@ -0,0 +1,6 @@
+SELECT
+    addProcessedExp.*,
+    addRun.workdir
+FROM addProcessedExp
+JOIN addRun
+    USING(add_id)
Index: trunk/ippTools/share/addtool_find_processedexp_ff.sql
===================================================================
--- trunk/ippTools/share/addtool_find_processedexp_ff.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_find_processedexp_ff.sql	(revision 37551)
@@ -0,0 +1,6 @@
+SELECT
+    addProcessedExp.*,
+    addRun.workdir
+FROM addProcessedExp
+JOIN addRun
+    USING(add_id)
Index: trunk/ippTools/share/addtool_queue_diff_id.sql
===================================================================
--- trunk/ippTools/share/addtool_queue_diff_id.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_queue_diff_id.sql	(revision 37551)
@@ -0,0 +1,24 @@
+INSERT INTO addRun
+    SELECT
+        0,              -- add_id
+        'diff',		-- stage
+        diff_id,        -- stage_id
+        diff_skyfile_id, -- stage_extra1
+        '%s',           -- state
+        '%s',           -- workdir
+	'%s',           -- workdir_state
+        '%s',           -- reduction
+        '%s',           -- label
+        '%s',           -- data_group
+        '%s',           -- dvodb 
+        '%s',           -- note
+	%d,		-- image_only
+	%d,		-- minidvodb
+	'%s',           -- minidvodb_group 
+ 	'%s'	        -- minidvodb_name
+    FROM diffInputSkyfile 
+    JOIN diffSkyfile using (diff_id, skycell_id)
+    JOIN diffRun using (diff_id)
+    WHERE
+        diffRun.state = 'full' AND
+        AND diffRun.diff_id = %lld
Index: trunk/ippTools/share/addtool_queue_ff_id.sql
===================================================================
--- trunk/ippTools/share/addtool_queue_ff_id.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_queue_ff_id.sql	(revision 37551)
@@ -0,0 +1,23 @@
+INSERT INTO addRun
+    SELECT
+        0,              -- add_id
+        'fullforce',		-- stage
+        ff_id,         -- stage_id
+	warp_id,	-- stage_extra1
+        '%s',           -- state
+        '%s',           -- workdir
+	'%s',           -- workdir_state
+        '%s',           -- reduction
+        '%s',           -- label
+        '%s',           -- data_group
+        '%s',           -- dvodb 
+        '%s',           -- note
+	%d,		-- image_only
+	%d,		-- minidvodb
+	'%s',           -- minidvodb_group 
+ 	'%s'	        -- minidvodb_name
+    FROM fullForceResult
+    JOIN fullForceRun using (ff_id)
+    WHERE
+        fullForceRun.state = 'full'
+        AND fullForceRun.ff_id = %lld
Index: trunk/ippTools/share/addtool_revertprocessedexp_diff.sql
===================================================================
--- trunk/ippTools/share/addtool_revertprocessedexp_diff.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_revertprocessedexp_diff.sql	(revision 37551)
@@ -0,0 +1,7 @@
+DELETE FROM addProcessedExp
+USING addProcessedExp, addRun
+WHERE
+    addRun.add_id = addProcessedExp.add_id
+    AND addProcessedExp.fault != 0
+    AND addRun.state = 'new'
+    AND addRun.stage = 'diff'
Index: trunk/ippTools/share/addtool_revertprocessedexp_ff.sql
===================================================================
--- trunk/ippTools/share/addtool_revertprocessedexp_ff.sql	(revision 37551)
+++ trunk/ippTools/share/addtool_revertprocessedexp_ff.sql	(revision 37551)
@@ -0,0 +1,7 @@
+DELETE FROM addProcessedExp
+USING addProcessedExp, addRun
+WHERE
+    addRun.add_id = addProcessedExp.add_id
+    AND addProcessedExp.fault != 0
+    AND addRun.state = 'new'
+    AND addRun.stage = 'fullforce'
Index: trunk/ippTools/src/addtool.c
===================================================================
--- trunk/ippTools/src/addtool.c	(revision 37439)
+++ trunk/ippTools/src/addtool.c	(revision 37551)
@@ -122,4 +122,7 @@
     PXOPT_COPY_S64(config->args, where,  "-sky_id",    "staticskyRun.sky_id", "==");
     PXOPT_COPY_S64(config->args, where,  "-skycal_id",  "skycalRun.skycal_id", "==");
+    PXOPT_COPY_S64(config->args, where,  "-diff_id",  "diffRun.diff_id", "==");
+    PXOPT_COPY_S64(config->args, where,  "-ff_id",  "fullForceRun.ff_id", "==");
+
     PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     if (strcmp(stage, "cam")== 0) {
@@ -146,5 +149,17 @@
       PXOPT_COPY_STR(config->args, where,  "-reduction", "skycalRun.reduction",  "==");
     }
-
+    if (strcmp(stage, "diff")==0) {
+      pxAddLabelSearchArgs (config, where, "-label",     "diffRun.label", "=="); //define using skycalRun label
+      pxAddLabelSearchArgs (config, where, "-data_group","diffRun.data_group", "==");
+      PXOPT_COPY_STR(config->args, where,  "-reduction", "diffRun.reduction",  "==");
+    }
+    if (strcmp(stage, "fullforce")==0) {
+      pxAddLabelSearchArgs (config, where, "-label",     "fullForceRun.label", "=="); //define using skycalRun label
+      pxAddLabelSearchArgs (config, where, "-data_group","fullForceRun.data_group", "==");
+      PXOPT_COPY_STR(config->args, where,  "-reduction", "fullForceRun.reduction",  "==");
+    }
+
+ 
+ 
     if (!psListLength(where->list)) {
         psFree(where);
@@ -258,5 +273,37 @@
     }
 
-
+    if (strcmp(stage,"diff") == 0) {
+      if (dvodb ) {
+        psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_diff_id_dvo.sql\n%s\n", dvodb,stage);
+        // find the skycal_id of all the exposures that we want to queue up.                                                                                                   
+        bare_query = pxDataGet("addtool_find_diff_id_dvo.sql");
+        // user supplied dvodb                                                                                                                                              
+        psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
+      } else {
+        psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_find_diff_id.sql\n%s\n",stage);
+        // find the skycal_id of all the exposures that we want to queue up.                                                                                                   
+        bare_query = pxDataGet("addtool_find_diff_id.sql");
+        // inherit dvodb from skycalRun, avoid matching NULL                                                                                                                   
+        psStringAppend(&dvodb_string, "(diffRun.dvodb IS NOT NULL AND previous_dvodb = diffRun.dvodb)");
+	// this is silly, there is no dvodb in skycalRun...?
+      }
+    }
+
+    if (strcmp(stage,"fullforce") == 0) {
+      if (dvodb ) {
+        psTrace("addtool.c", PS_LOG_INFO, "dvodb argument found (%s) using addtool_find_ff_id_dvo.sql\n%s\n", dvodb,stage);
+        // find the skycal_id of all the exposures that we want to queue up.                                                                                                   
+        bare_query = pxDataGet("addtool_find_ff_id_dvo.sql");
+        // user supplied dvodb                                                                                                                                              
+        psStringAppend(&dvodb_string, "addRun.dvodb = '%s'", dvodb);
+      } else {
+        psTrace("addtool.c", PS_LOG_INFO, "dvodb argument not found using addtool_ff_id.sql\n%s\n",stage);
+        // find the skycal_id of all the exposures that we want to queue up.                                                                                                   
+        bare_query = pxDataGet("addtool_find_ff_id.sql");
+        // inherit dvodb from skycalRun, avoid matching NULL                                                                                                                   
+        psStringAppend(&dvodb_string, "(fullForceRun.dvodb IS NOT NULL AND previous_dvodb = fullForceRun.dvodb)");
+	// this is silly, there is no dvodb in skycalRun...?
+      }
+    }
 
 
@@ -324,4 +371,15 @@
 	psStringAppend(&query, " GROUP BY skycal_id, sky_id, stack_id ");  //this needs checking, but I think it shoul be fine? it groups by lots of stuff (including stack - we only want one of each stack in there
       }
+      //needs to be checked HAF xxx
+      if (strcmp(stage,"diff") == 0) {
+	psStringAppend(&query, " GROUP BY diff_id ");  //this needs checking, but I think it shoul be fine? it groups by lots of stuff (including stack - we only want one of each stack in there
+      }
+      //needs to be checked HAF xxx
+      if (strcmp(stage,"fullforce") == 0) {
+	psStringAppend(&query, " GROUP BY ff_id, skycal_id ");  //this needs checking, but I think it shoul be fine? it groups by lots of stuff (including stack - we only want one of each stack in there
+      }
+
+
+
 
     psTrace("addtool.c", PS_LOG_INFO,"query: \n\n%s\n\n",query);
@@ -476,4 +534,57 @@
     }
 
+    if (strcmp(stage,"diff") == 0) {
+      for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        diffRunRow *row = diffRunObjectFromMetadata(md);
+
+        if (!row) {
+	  psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into skycalRun");
+	  psFree(output);
+	  return false;
+        }
+
+	if (!dvodb) {  // there's no skycalRun.dvodb
+ 	  psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined dvodb: label: %s, diff_id %" PRId64, row->label, row->diff_id);
+	  psFree(output);
+	  return false;
+        }
+        if (!workdir && !row->workdir) {
+	  psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined workdir: label: %s, diff_id %" PRId64, row->label, row->diff_id);
+	  psFree(output);
+	  return false;
+        }
+
+        psFree(row);
+      }
+    }
+
+    if (strcmp(stage,"fullforce") == 0) {
+      for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+
+        fullForceRunRow *row = fullForceRunObjectFromMetadata(md);
+
+        if (!row) {
+	  psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into skycalRun");
+	  psFree(output);
+	  return false;
+        }
+
+	if (!dvodb) {  // there's no skycalRun.dvodb
+ 	  psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined dvodb: label: %s, ff_id %" PRId64, row->label, row->ff_id);
+	  psFree(output);
+	  return false;
+        }
+        if (!workdir && !row->workdir) {
+	  psError(PS_ERR_UNKNOWN, false, "cannot queue addstar run without a defined workdir: label: %s, ff_id %" PRId64, row->label, row->ff_id);
+	  psFree(output);
+	  return false;
+        }
+
+        psFree(row);
+      }
+    }
 
 
@@ -672,4 +783,92 @@
       }
    
+    if (strcmp(stage,"diff") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+	psS64 stage_id =0; 
+	
+		  diffRunRow *row = diffRunObjectFromMetadata(md);
+	  stage_id = row->diff_id;
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into skycalRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxaddQueueByCamID(config,
+			       stage,
+                               stage_id,
+			       0,
+                               workdir     ? workdir   : row->workdir,
+                               reduction   ? reduction : row->reduction,
+                               label       ? label     : row->label,
+                               data_group  ? data_group : (row->data_group ? row->data_group :  (label ? label : row->label)),
+                               dvodb       ? dvodb     : NULL,
+                               note        ? note      : NULL,
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+      }
+ 
+    if (strcmp(stage,"fullforce") == 0) {
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *md = output->data[i];
+	psS64 stage_id =0; 
+	
+		  fullForceRunRow *row = fullForceRunObjectFromMetadata(md);
+	  stage_id = row->ff_id;
+	
+        if (!row) {
+            psError(PS_ERR_UNKNOWN, false, "failed to convert metadata into skycalRun");
+            psFree(output);
+            return false;
+        }
+
+        // queue the exp
+        if (!pxaddQueueByCamID(config,
+			       stage,
+                               stage_id,
+			       0,
+                               workdir     ? workdir   : row->workdir,
+                               reduction   ? reduction : row->reduction,
+                               label       ? label     : row->label,
+                               data_group  ? data_group : (row->data_group ? row->data_group :  (label ? label : row->label)),
+                               dvodb       ? dvodb     : NULL,
+                               note        ? note      : NULL,
+                               image_only,
+                               minidvodb,
+                               minidvodb_group,
+                               minidvodb_name
+        )) {
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error sfg");
+            }
+            psError(PS_ERR_UNKNOWN, false,
+                    "failed to trying to queue stage %s %" PRId64,stage, stage_id);
+            psFree(row);
+            psFree(output);
+            return false;
+        }
+        psFree(row);
+    }
+      }
+
+
+
 
 
@@ -695,4 +894,7 @@
     PXOPT_COPY_S64(config->args, where, "-sky_id",    "staticskyRun.sky_id", "==");
     PXOPT_COPY_S64(config->args, where, "-skycal_id", "skycalRun.skycal_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-diff_id", "diffRun.diff_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-ff_id", "fullForceRun.ff_id", "==");
+
     PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where); // most search arguments based on camera
@@ -709,14 +911,20 @@
     psString query = NULL;
     if (strcmp(stage, "cam")==0) {
-      query = psStringCopy("UPDATE addRun JOIN camRun on cam_id = stage_id JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
+      query = psStringCopy("UPDATE addRun JOIN camRun on (cam_id = stage_id and stage = 'cam')  JOIN chipRun USING(chip_id) JOIN rawExp USING(exp_id)");
     }
     if (strcmp(stage, "stack")==0) {
-      query = psStringCopy("UPDATE addRun JOIN stackRun on stack_id = stage_id");
+      query = psStringCopy("UPDATE addRun JOIN stackRun on (stack_id = stage_id and stage = 'stack')");
     }
     if (strcmp(stage, "staticsky")==0) {
-      query = psStringCopy("UPDATE addRun JOIN staticskyRun on sky_id = stage_id");
+      query = psStringCopy("UPDATE addRun JOIN staticskyRun on (sky_id = stage_id and stage = 'staticsky')");
     }
     if (strcmp(stage, "skycal")==0) {
-      query = psStringCopy("UPDATE addRun JOIN skycalRun on skycal_id = stage_id");
+      query = psStringCopy("UPDATE addRun JOIN skycalRun on (skycal_id = stage_id and stage = 'skycal')");
+    }
+    if (strcmp(stage, "diff")==0) {
+      query = psStringCopy("UPDATE addRun JOIN diffInputSkyfile on (diff_id = stage_id and diff_skyfile_id = stage_extra1 and stage = 'diff') JOIN diffSkyfile on (diff_id, skycell_id) JOIN diffRun using (diff_id)");
+    }
+    if (strcmp(stage, "fullforce")==0) {
+      query = psStringCopy("UPDATE addRun JOIN fullForceResult on (ff_id = stage_id and warp_id = stage_extra1 and stage = 'fullforce') JOIN fullForceRun on (ff_id)");
     }
 
@@ -743,4 +951,6 @@
     PXOPT_COPY_S64(config->args, where, "-sky_id",    "staticskyRun.sky_id", "==");
     PXOPT_COPY_S64(config->args, where, "-skycal_id", "skycalRun.skycal_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-ff_id",    "fullForceRun.ff_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-diff_id",    "diffRun.diff_id", "==");
     PXOPT_LOOKUP_STR(stage,       config->args, "-stage", false, false);
     pxcamGetSearchArgs (config, where);
@@ -764,4 +974,10 @@
       query = pxDataGet("addtool_find_pendingexp_skycal.sql");
     }
+    if (strcmp(stage, "diff")==0) {
+      query = pxDataGet("addtool_find_pendingexp_diff.sql");
+    }
+    if (strcmp(stage, "fullforce")==0) {
+      query = pxDataGet("addtool_find_pendingexp_ff.sql");
+    }
 
 
@@ -790,4 +1006,15 @@
       psStringAppend(&query, " GROUP BY %s", "sky_id, stage_extra1");
     }
+    if (strcmp(stage, "diff") == 0) {
+      //this group by is needed to join against all the warps (to get camera)
+      psStringAppend(&query, " GROUP BY %s", "diff_id, stage_extra1");
+    }
+    if (strcmp(stage, "fullforce") == 0) {
+      //this group by is needed to join against all the warps (to get camera)
+      psStringAppend(&query, " GROUP BY %s", "ff_id, stage_extra1");
+    }
+
+
+
     // treat limit == 0 as "no limit"
     if (limit) {
@@ -994,4 +1221,9 @@
     } else if (strcmp (stage,"skycal") == 0) {
       query = pxDataGet("addtool_find_processedexp_skycal.sql");
+    } else if (strcmp (stage,"diff") == 0) {
+      query = pxDataGet("addtool_find_processedexp_diff.sql");
+    } else if (strcmp (stage,"fullforce") == 0) {
+      query = pxDataGet("addtool_find_processedexp_ff.sql");
+
     } else {
         psFree(where);
@@ -1112,4 +1344,10 @@
     if (strcmp(stage, "skycal") == 0) {
       query = pxDataGet("addtool_revertprocessedexp_skycal.sql");
+    }
+    if (strcmp(stage, "diff") == 0) {
+      query = pxDataGet("addtool_revertprocessedexp_diff.sql");
+    }
+    if (strcmp(stage, "fullforce") == 0) {
+      query = pxDataGet("addtool_revertprocessedexp_ff.sql");
     }
 
Index: trunk/ippTools/src/addtoolConfig.c
===================================================================
--- trunk/ippTools/src/addtoolConfig.c	(revision 37439)
+++ trunk/ippTools/src/addtoolConfig.c	(revision 37551)
@@ -55,4 +55,6 @@
     psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-skycal_id",          0, "search by skycal_id", 0);
     pxcamSetSearchArgs(definebyqueryArgs);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-diff_id",            0, "search by diff_id", 0);
+    psMetadataAddS64(definebyqueryArgs, PS_LIST_TAIL, "-ff_id",              0, "search by ff_id", 0);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by camRun label", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-data_group", PS_META_DUPLICATE_OK, "search by camRun data_group", NULL);
@@ -83,4 +85,6 @@
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-sky_id",                 0, "search by sky_id", 0);
     psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-skycal_id",                 0, "search by skycal_id", 0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-diff_id",                0, "search by diff_id",0);
+    psMetadataAddS64(updaterunArgs, PS_LIST_TAIL, "-ff_id",                  0, "search by _ff_id",0);
     pxcamSetSearchArgs(updaterunArgs);
     psMetadataAddStr(updaterunArgs, PS_LIST_TAIL, "-label",                  0, "search by addRun label", NULL);
@@ -101,7 +105,9 @@
     psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-add_id",            0, "search by add_id", 0);
     psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-cam_id",            0, "search by cam_id", 0);
-    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-stack_id",                 0, "search by stack_id", 0);
-    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-sky_id",                 0, "search by sky_id", 0);
-    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-skycal_id",                 0, "search by skycal_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-stack_id",                0, "search by stack_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-sky_id",                  0, "search by sky_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-skycal_id",               0, "search by skycal_id", 0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-diff_id",                 0, "search by diff_id",0);
+    psMetadataAddS64(pendingexpArgs, PS_LIST_TAIL, "-ff_id",                   0, "search by ff_id",0);
     pxcamSetSearchArgs(pendingexpArgs);
     psMetadataAddStr(pendingexpArgs, PS_LIST_TAIL, "-label", PS_META_DUPLICATE_OK, "search by addRun label", NULL);
@@ -236,5 +242,5 @@
     psMetadata *modes = psMetadataAlloc();
 
-    PXOPT_ADD_MODE("-definebyquery",        "create runs from cam stage",           ADDTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
+    PXOPT_ADD_MODE("-definebyquery",        "create runs from cam/skycal/forcedwarp/diff stage",           ADDTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
     PXOPT_ADD_MODE("-updaterun",            "change add run properties",            ADDTOOL_MODE_UPDATERUN,      updaterunArgs);
     PXOPT_ADD_MODE("-pendingexp",           "show pending exps",                    ADDTOOL_MODE_PENDINGEXP,    pendingexpArgs);
Index: trunk/ippTools/src/pxadd.c
===================================================================
--- trunk/ippTools/src/pxadd.c	(revision 37439)
+++ trunk/ippTools/src/pxadd.c	(revision 37551)
@@ -164,4 +164,14 @@
         psMemSetPersistent(query, true);
       }
+      else if (strcmp(stage,"diff") == 0) {
+	query = pxDataGet("addtool_queue_diff_id.sql");
+        psMemSetPersistent(query, true);
+      }
+      else if (strcmp(stage,"fullforce") == 0) {
+	query = pxDataGet("addtool_queue_ff_id.sql");
+        psMemSetPersistent(query, true);
+      }
+
+
       else 
 	{
