Index: trunk/ippTools/src/camtool.c
===================================================================
--- trunk/ippTools/src/camtool.c	(revision 23281)
+++ trunk/ippTools/src/camtool.c	(revision 23310)
@@ -44,4 +44,6 @@
 static bool pendingcleanupexpMode(pxConfig *config);
 static bool donecleanupMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -77,4 +79,6 @@
         MODECASE(CAMTOOL_MODE_PENDINGCLEANUPEXP,    pendingcleanupexpMode);
         MODECASE(CAMTOOL_MODE_DONECLEANUP,          donecleanupMode);
+        MODECASE(CAMTOOL_MODE_EXPORTRUN,            exportrunMode);
+        MODECASE(CAMTOOL_MODE_IMPORTRUN,            importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -1081,2 +1085,127 @@
     return true;
 }
+
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+  
+  int numExportTables = 2;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-cam_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
+
+  ExportTable tables [] = {
+    {"camRun", "camtool_export_run.sql"},
+    {"camProcessedExp", "camtool_export_processed_exp.sql"},
+  };
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    // we must write the export table in non-simple (true) format
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+  }
+
+  fclose (f);
+
+  return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  psMetadataItem *item = psMetadataLookup (input, "camRun");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  camRunRow *camRun = camRunObjectFromMetadata (entry->data.md);
+  camRunInsertObject (config->dbh, camRun);
+
+  // fprintf (stdout, "---- cam run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+  
+  item = psMetadataLookup (input, "camProcessedImfile");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  for (int i = 0; i < item->data.list->n; i++) {
+    psMetadataItem *entry = psListGet (item->data.list, i);
+    assert (entry);
+    assert (entry->type == PS_DATA_METADATA);
+    camProcessedExpRow *camProcessedExp = camProcessedExpObjectFromMetadata (entry->data.md);
+    camProcessedExpInsertObject (config->dbh, camProcessedExp);
+
+    // fprintf (stdout, "---- row %d ----\n", i);
+    // psMetadataPrint (stderr, entry->data.md, 1);
+  }
+
+  return true;
+}
Index: trunk/ippTools/src/camtool.h
===================================================================
--- trunk/ippTools/src/camtool.h	(revision 23281)
+++ trunk/ippTools/src/camtool.h	(revision 23310)
@@ -39,4 +39,6 @@
     CAMTOOL_MODE_PENDINGCLEANUPEXP,
     CAMTOOL_MODE_DONECLEANUP,
+    CAMTOOL_MODE_EXPORTRUN,
+    CAMTOOL_MODE_IMPORTRUN
 } camtoolMode;
 
Index: trunk/ippTools/src/camtoolConfig.c
===================================================================
--- trunk/ippTools/src/camtoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/camtoolConfig.c	(revision 23310)
@@ -228,4 +228,15 @@
     psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-cam_id", 0,          "export this camera ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
     psMetadata *argSets = psMetadataAlloc();
     psMetadata *modes = psMetadataAlloc();
@@ -245,4 +256,6 @@
     PXOPT_ADD_MODE("-pendingcleanupexp",    "show exposures for cleanup runs",      CAMTOOL_MODE_PENDINGCLEANUPEXP, pendingcleanupexpArgs);
     PXOPT_ADD_MODE("-donecleanup",          "show runs that have been cleaned",     CAMTOOL_MODE_DONECLEANUP,       donecleanupArgs);
+   PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", CAMTOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           CAMTOOL_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: trunk/ippTools/src/chiptool.c
===================================================================
--- trunk/ippTools/src/chiptool.c	(revision 23281)
+++ trunk/ippTools/src/chiptool.c	(revision 23310)
@@ -42,5 +42,5 @@
 static bool revertprocessedimfileMode(pxConfig *config);
 static bool updateprocessedimfileMode(pxConfig *config);
-static bool advanceexpMode(pxConfig *config);
+static bool promoteexpMode(pxConfig *config);
 static bool blockMode(pxConfig *config);
 static bool maskedMode(pxConfig *config);
@@ -52,10 +52,8 @@
 static bool runMode(pxConfig *config);
 static bool tocleanedimfileMode(pxConfig *config);
-// static bool tocleanedimfile_from_scrubbedMode(pxConfig *config);
 static bool tofullimfileMode(pxConfig *config);
 static bool topurgedimfileMode(pxConfig *config);
 static bool exportrunMode(pxConfig *config);
 static bool importrunMode(pxConfig *config);
-static bool change_imfile_data_state(pxConfig *config, psString data_state, psString run_state);
 
 # define MODECASE(caseName, func) \
@@ -83,5 +81,5 @@
         MODECASE(CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,   revertprocessedimfileMode);
         MODECASE(CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,   updateprocessedimfileMode);
-        MODECASE(CHIPTOOL_MODE_ADVANCEEXP,              advanceexpMode);
+        MODECASE(CHIPTOOL_MODE_PROMOTEEXP,              promoteexpMode);
         MODECASE(CHIPTOOL_MODE_BLOCK,                   blockMode);
         MODECASE(CHIPTOOL_MODE_MASKED,                  maskedMode);
@@ -93,5 +91,4 @@
         MODECASE(CHIPTOOL_MODE_RUN,                     runMode);
         MODECASE(CHIPTOOL_MODE_TOCLEANEDIMFILE,         tocleanedimfileMode);
-        // MODECASE(CHIPTOOL_MODE_TOCLEANEDIMFILE_FROM_SCRUBBED, tocleanedimfile_from_scrubbedMode);
         MODECASE(CHIPTOOL_MODE_TOFULLIMFILE,            tofullimfileMode);
         MODECASE(CHIPTOOL_MODE_TOPURGEDIMFILE,          topurgedimfileMode);
@@ -652,36 +649,13 @@
     PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
     PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
-    PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
-    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
-
-    if (state && code) {
-        psError(PS_ERR_UNKNOWN, true, "only one of -set_state and -code may be supplied");
-        return false;
-    }
-
-    if (state) {
-      // make sure that the state string is valid
-      if (!pxIsValidState(state)) {
-        psError(PXTOOLS_ERR_DATA, false, "%s is not a valid state", state);
-        return false;
-      }
-      if (!change_imfile_data_state(config, state, "unknown")) {
+    PXOPT_LOOKUP_S16(code, config->args, "-code", true, false);
+
+    if (!pxSetFaultCode(config->dbh, "chipProcessedImfile", where, code)) {
         psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
         return false;
-      }
-      return true;
-    }
-
-    if (code) {
-      if (!pxSetFaultCode(config->dbh, "chipProcessedImfile", where, code)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
-        return false;
-      }
-      psFree(where);
-      return true;
-    }
-
-    psError(PS_ERR_UNKNOWN, true, "one of -set_state or -code must be supplied");
-    return false;
+    }
+    psFree(where);
+
+    return true;
 }
 
@@ -1104,5 +1078,5 @@
 
 
-static bool advanceexpMode(pxConfig *config)
+static bool promoteexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -1219,9 +1193,4 @@
 // shared code for the modes -tocleanedimfile -tofullimfile -topurgedimfile
 
-// XXX EAM : this function was enforcing only certain transitions with the SQL.  However,
-// this is getting fairly messy now that we have added a few additional target and
-// destination states.  I'm disabling these restrictions for now; is there are better way
-// to enforce the allowed state transitions?
-
 static bool change_imfile_data_state(pxConfig *config, psString data_state, psString run_state)
 {
@@ -1239,8 +1208,6 @@
     }
 
-    // XXX this feature is disabled (run_state is ignored)
     // note only updates if chipRun.state = run_state
-
-    if (!p_psDBRunQueryF(config->dbh, query, data_state, chip_id, class_id)) {
+    if (!p_psDBRunQueryF(config->dbh, query, data_state, chip_id, class_id, run_state)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         // rollback
@@ -1289,43 +1256,57 @@
 bool exportrunMode(pxConfig *config)
 {
-    PS_ASSERT_PTR_NON_NULL(config, NULL);
-
-    PXOPT_LOOKUP_S64(chip_id, config->args, "-chip_id", true,  false);
-    PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
-    PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
-
-    FILE *f = fopen (outfile, "w");
-    if (f == NULL) {
-        psError(PS_ERR_UNKNOWN, false, "failed to open output file");
-        return false;
-    }
-
-    psMetadata *where = psMetadataAlloc();
-    PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
-
-    // *** extract the chipRun in this section ***
-    psString query = pxDataGet("chiptool_export_run.sql");
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+  
+  int numExportTables = 3;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-chip_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
+
+  ExportTable tables [] = {
+    {"chipRun", "chiptool_export_run.sql"},
+    {"chipImfile", "chiptool_export_imfile.sql"},
+    {"chipProcessedImfile", "chiptool_export_processed_imfile.sql"},
+  };
+
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
     if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
     }
 
     if (where && psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereSQL(where, NULL);
-        psStringAppend(&query, " %s", whereClause);
-        psFree(whereClause);
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
     }
 
     // treat limit == 0 as "no limit"
     if (limit) {
-        psString limitString = psDBGenerateLimitSQL(limit);
-        psStringAppend(&query, " %s", limitString);
-        psFree(limitString);
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
     }
 
     if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
     }
     psFree(query);
@@ -1333,77 +1314,34 @@
     psArray *output = p_psDBFetchResult(config->dbh);
     if (!output) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
     }
     if (!psArrayLength(output)) {
-        psTrace("chiptool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
     }
 
     // we must write the export table in non-simple (true) format
-    if (!ippdbPrintMetadatas(f, output, "chipRun", true)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
-        psFree(output);
-        return false;
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
     }
     psFree(output);
-
-    // *** extract the chipProcessedImfile entries in this section ***
-    query = pxDataGet("chiptool_export_imfiles.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    if (where && psListLength(where->list)) {
-        psString whereClause = psDBGenerateWhereSQL(where, NULL);
-        psStringAppend(&query, " %s", whereClause);
-        psFree(whereClause);
-    }
-    psFree(where);
-
-    // treat limit == 0 as "no limit"
-    if (limit) {
-        psString limitString = psDBGenerateLimitSQL(limit);
-        psStringAppend(&query, " %s", limitString);
-        psFree(limitString);
-    }
-
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
-    }
-    psFree(query);
-
-    output = p_psDBFetchResult(config->dbh);
-    if (!output) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-    if (!psArrayLength(output)) {
-        psTrace("chiptool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-
-    // we must write the export table in non-simple (true) format
-    if (!ippdbPrintMetadatas(f, output, "chipProcessedImfiles", true)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to print array");
-        psFree(output);
-        return false;
-    }
-    psFree(output);
-
-    fclose (f);
-
-    return true;
-}
-
+  }
+
+  fclose (f);
+
+  return true;
+}
 
 bool importrunMode(pxConfig *config)
 {
   unsigned int nFail;
+  
+  int numImportTables = 2;
+ 
+  char tables[2] [80] = {"chipImfile", "chipProcessedImfile"};
 
   PS_ASSERT_PTR_NON_NULL(config, NULL);
@@ -1416,31 +1354,49 @@
   psMetadataPrint (stderr, input, 1);
 
-  psMetadataItem *chipRunItem = psMetadataLookup (input, "chipRun");
-  psAssert (chipRunItem, "entry not in input?");
-  psAssert (chipRunItem->type == PS_DATA_METADATA_MULTI, "entry not multi?");
-  
-  psMetadataItem *chipRunEntry = psListGet (chipRunItem->data.list, 0);
-  assert (chipRunEntry);
-  assert (chipRunEntry->type == PS_DATA_METADATA);
-  chipRunRow *chipRun = chipRunObjectFromMetadata (chipRunEntry->data.md);
-  chipRunInsertObject (config->dbh, chipRun);
-
-  // fprintf (stdout, "---- chip run ----\n");
-  // psMetadataPrint (stderr, chipRunEntry->data.md, 1);
-
-  psMetadataItem *item = psMetadataLookup (input, "chipProcessedImfiles");
+  psMetadataItem *item = psMetadataLookup (input, "chipRun");
   psAssert (item, "entry not in input?");
   psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
 
-  // XXX would be better to use the iterator?
-  for (int i = 0; i < item->data.list->n; i++) {
-    psMetadataItem *entry = psListGet (item->data.list, i);
-    assert (entry);
-    assert (entry->type == PS_DATA_METADATA);
-    chipProcessedImfileRow *chipProcessedImfile = chipProcessedImfileObjectFromMetadata (entry->data.md);
-    chipProcessedImfileInsertObject (config->dbh, chipProcessedImfile);
-
-    // fprintf (stdout, "---- row %d ----\n", i);
-    // psMetadataPrint (stderr, entry->data.md, 1);
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  chipRunRow *chipRun = chipRunObjectFromMetadata (entry->data.md);
+  chipRunInsertObject (config->dbh, chipRun);
+
+  // fprintf (stdout, "---- chip run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+  
+  for (int i = 0; i < numImportTables; i++) {
+    psMetadataItem *item = psMetadataLookup (input, tables[i]);
+    psAssert (item, "entry not in input?");
+    psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+    switch (i) {
+      case 0:
+        for (int i = 0; i < item->data.list->n; i++) {
+          psMetadataItem *entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          chipImfileRow *chipImfile = chipImfileObjectFromMetadata (entry->data.md);
+          chipImfileInsertObject (config->dbh, chipImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 1:
+        for (int i = 0; i < item->data.list->n; i++) {
+          psMetadataItem *entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          chipProcessedImfileRow *chipProcessedImfile = chipProcessedImfileObjectFromMetadata (entry->data.md);
+          chipProcessedImfileInsertObject (config->dbh, chipProcessedImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+    }
   }
 
Index: trunk/ippTools/src/chiptool.h
===================================================================
--- trunk/ippTools/src/chiptool.h	(revision 23281)
+++ trunk/ippTools/src/chiptool.h	(revision 23310)
@@ -32,5 +32,5 @@
     CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,
     CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,
-    CHIPTOOL_MODE_ADVANCEEXP,
+    CHIPTOOL_MODE_PROMOTEEXP,
     CHIPTOOL_MODE_BLOCK,
     CHIPTOOL_MODE_MASKED,
@@ -43,5 +43,4 @@
     CHIPTOOL_MODE_RUN,
     CHIPTOOL_MODE_TOCLEANEDIMFILE,
-    CHIPTOOL_MODE_TOCLEANEDIMFILE_FROM_SCRUBBED,
     CHIPTOOL_MODE_TOFULLIMFILE,
     CHIPTOOL_MODE_TOPURGEDIMFILE,
Index: trunk/ippTools/src/chiptoolConfig.c
===================================================================
--- trunk/ippTools/src/chiptoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/chiptoolConfig.c	(revision 23310)
@@ -172,14 +172,13 @@
     // -updateprocessedimfile
     psMetadata *updateprocessedimfileArgs = psMetadataAlloc();
-    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-chip_id",    0, "search by chip ID", 0);
-    psMetadataAddStr(updateprocessedimfileArgs,  PS_LIST_TAIL, "-class_id",  0, "search by class ID", NULL);
-    psMetadataAddS16(updateprocessedimfileArgs, PS_LIST_TAIL, "-code",       0, "set fault code", 0);
-    psMetadataAddStr(updateprocessedimfileArgs, PS_LIST_TAIL, "-set_state",  0, "set state", NULL);
-
-    // -advanceexp
-    psMetadata *advanceexpArgs = psMetadataAlloc();
-    psMetadataAddS64(advanceexpArgs, PS_LIST_TAIL, "-chip_id",  0,          "search by chip ID", 0);
-    psMetadataAddStr(advanceexpArgs, PS_LIST_TAIL, "-label",  0,            "advance exposures for specified label", NULL);
-    psMetadataAddU64(advanceexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(updateprocessedimfileArgs, PS_LIST_TAIL, "-chip_id",  0,            "search by chip ID", 0);
+    psMetadataAddStr(updateprocessedimfileArgs,  PS_LIST_TAIL, "-class_id",           0, "search by class ID", NULL);
+    psMetadataAddS16(updateprocessedimfileArgs, PS_LIST_TAIL, "-code",  0,            "set fault code (required)", 0);
+
+    // -promoteexp
+    psMetadata *promoteexpArgs = psMetadataAlloc();
+    psMetadataAddS64(promoteexpArgs, PS_LIST_TAIL, "-chip_id",  0,          "search by chip ID", 0);
+    psMetadataAddStr(promoteexpArgs, PS_LIST_TAIL, "-label",  0,            "promote exposures for specified label", NULL);
+    psMetadataAddU64(promoteexpArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
 
     // -block
@@ -235,9 +234,4 @@
     psMetadataAddStr(tocleanedimfileArgs, PS_LIST_TAIL, "-class_id",  0,        "class ID to update", NULL);
 
-//    // -tocleanedimfile_from_scrubbed
-//    psMetadata *tocleanedimfile_from_scrubbedArgs = psMetadataAlloc();
-//    psMetadataAddS64(tocleanedimfile_from_scrubbedArgs, PS_LIST_TAIL, "-chip_id", 0,          "chip ID to update", 0);
-//    psMetadataAddStr(tocleanedimfile_from_scrubbedArgs, PS_LIST_TAIL, "-class_id",  0,        "class ID to update", NULL);
-//
     // -tofullimfile
     psMetadata *tofullimfileArgs = psMetadataAlloc();
@@ -271,5 +265,5 @@
     PXOPT_ADD_MODE("-updateprocessedimfile","change procesed imfile properties",    CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,updateprocessedimfileArgs);
     PXOPT_ADD_MODE("-revertprocessedimfile","undo a processed imfile",              CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,revertprocessedimfileArgs);
-    PXOPT_ADD_MODE("-advanceexp",           "advance completed exposures",          CHIPTOOL_MODE_ADVANCEEXP,           advanceexpArgs);
+    PXOPT_ADD_MODE("-promoteexp",           "promote completed exposures",          CHIPTOOL_MODE_PROMOTEEXP,           promoteexpArgs);
     PXOPT_ADD_MODE("-block",                "set a label block",                    CHIPTOOL_MODE_BLOCK,                blockArgs);
     PXOPT_ADD_MODE("-masked",               "show blocked labels",                  CHIPTOOL_MODE_MASKED,               maskedArgs);
@@ -281,5 +275,4 @@
     PXOPT_ADD_MODE("-run",                  "show runs",                            CHIPTOOL_MODE_RUN,                  runArgs);
     PXOPT_ADD_MODE("-tocleanedimfile",      "set imfile state to cleaned",          CHIPTOOL_MODE_TOCLEANEDIMFILE,      tocleanedimfileArgs);
-    //    PXOPT_ADD_MODE("-tocleanedimfile_from_scrubbed", "set imfile state to cleaned (for goto_scrubbed)", CHIPTOOL_MODE_TOCLEANEDIMFILE_FROM_SCRUBBED, tocleanedimfile_from_scrubbedArgs);
     PXOPT_ADD_MODE("-tofullimfile",         "set imfile state to full",              CHIPTOOL_MODE_TOFULLIMFILE,         tofullimfileArgs);
     PXOPT_ADD_MODE("-topurgedimfile",       "set imfile state to purged",            CHIPTOOL_MODE_TOPURGEDIMFILE,       topurgedimfileArgs);
Index: trunk/ippTools/src/dettool.c
===================================================================
--- trunk/ippTools/src/dettool.c	(revision 23281)
+++ trunk/ippTools/src/dettool.c	(revision 23310)
@@ -28,4 +28,6 @@
 static bool inputMode(pxConfig *config);
 static bool rawMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 // run
@@ -46,5 +48,10 @@
     } \
     break;
-
+/*
+typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+} ExportTable;
+*/
 int main(int argc, char **argv)
 {
@@ -146,4 +153,6 @@
         MODECASE(DETTOOL_MODE_REGISTER_DETREND, register_detrendMode);
         MODECASE(DETTOOL_MODE_REGISTER_DETREND_IMFILE, register_detrend_imfileMode);
+        MODECASE(DETTOOL_MODE_EXPORTRUN,               exportrunMode);
+        MODECASE(DETTOOL_MODE_IMPORTRUN,               importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -578,5 +587,9 @@
       // generate a random-valued vector, return an index sorted by the random values
       psVector *randomVector = psVectorAlloc(detrendExps->n, PS_TYPE_F32); // random values
-      psRandom *rng = psRandomAllocSpecific(PS_RANDOM_TAUS, 0);
+      /*
+       * change due to PAP work on random number generator?
+       * psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
+       */
+      psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
       for (int i = 0; i < randomVector->n; i++) {
         randomVector->data.F32[i] = psRandomUniform(rng);
@@ -1996,4 +2009,283 @@
 }
 
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+  
+  int numExportTables = 12;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-det_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-det_id", "det_id", "==");
+
+  ExportTable tables [] = {
+    {"detInputExp", "dettool_export_input_exp.sql"},
+    {"detNormalizedExp", "dettool_export_normalized_exp.sql"},
+    {"detNormalizedImfile", "dettool_export_normalized_imfile.sql"},
+    {"detNormalizedStatImfile", "dettool_export_normalized_stat_imfile.sql"},
+    {"detProcessedExp", "dettool_export_processed_exp.sql"},
+    {"detProcessedImfile", "dettool_export_processed_imfile.sql"},
+    {"detRegisteredImfile", "dettool_export_registered_imfile.sql"},
+    {"detResidExp", "dettool_export_resid_exp.sql"},
+    {"detResidImfile", "dettool_export_resid_imfile.sql"},
+    {"detRun", "dettool_export_run.sql"},
+    {"detRunSummary", "dettool_export_run_summary.sql"},
+    {"detStackedImfile", "dettool_export_stacked_imfile.sql"},
+  };
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("chiptool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    // we must write the export table in non-simple (true) format
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+  
+  }
+
+  fclose (f);
+
+  return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+  
+  int numImportTables = 11;
+  
+  char tables[11] [80] = {"detInputExp", "detNormalizedExp",
+    "detNormalizedStatImfile", "detProcessedExp", "detProcessedImfile",
+    "detRegisteredImfile", "detResidExp", "detResidImfile",
+    "detNormalizedImfile", "detRunSummary", "detStackedImfile"};
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+  
+  psMetadataItem *item = psMetadataLookup (input, "detRun");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  detRunRow *detRun = detRunObjectFromMetadata (entry->data.md);
+  detRunInsertObject (config->dbh, detRun);
+  
+  // fprintf (stdout, "---- det run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+
+  for (int i = 0; i < numImportTables; i++) {
+    item = psMetadataLookup (input, tables[i]);
+    psAssert (item, "entry not in input?");
+    psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+    switch (i) {
+      case 0:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detInputExpRow *detInputExp = detInputExpObjectFromMetadata (entry->data.md);
+          detInputExpInsertObject (config->dbh, detInputExp);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+  
+      case 1:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detNormalizedExpRow *detNormalizedExp = detNormalizedExpObjectFromMetadata (entry->data.md);
+          detNormalizedExpInsertObject (config->dbh, detNormalizedExp);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 2:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detNormalizedStatImfileRow *detNormalizedStatImfile = detNormalizedStatImfileObjectFromMetadata (entry->data.md);
+          detNormalizedStatImfileInsertObject (config->dbh, detNormalizedStatImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+ 
+      case 3:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detProcessedExpRow *detProcessedExp =  detProcessedExpObjectFromMetadata (entry->data.md);
+          detProcessedExpInsertObject (config->dbh, detProcessedExp);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 4:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detProcessedImfileRow *detProcessedImfile =  detProcessedImfileObjectFromMetadata (entry->data.md);
+          detProcessedImfileInsertObject (config->dbh, detProcessedImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 5:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detRegisteredImfileRow *detRegisteredImfile = detRegisteredImfileObjectFromMetadata (entry->data.md);
+          detRegisteredImfileInsertObject (config->dbh, detRegisteredImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 6:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detResidExpRow *detResidExp = detResidExpObjectFromMetadata (entry->data.md);
+          detResidExpInsertObject (config->dbh, detResidExp);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 7:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detResidImfileRow *detResidImfile = detResidImfileObjectFromMetadata (entry->data.md);
+          detResidImfileInsertObject (config->dbh, detResidImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 8:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detNormalizedImfileRow *detNormalizedImfile = detNormalizedImfileObjectFromMetadata (entry->data.md);
+          detNormalizedImfileInsertObject (config->dbh, detNormalizedImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 9:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detRunSummaryRow *detRunSummary = detRunSummaryObjectFromMetadata (entry->data.md);
+          detRunSummaryInsertObject (config->dbh, detRunSummary);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 10:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          detStackedImfileRow *detStackedImfile = detStackedImfileObjectFromMetadata (entry->data.md);
+          detStackedImfileInsertObject (config->dbh, detStackedImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+    }
+  }
+
+  return true;
+}
+
 #if 0
 // XXX this function was left in commented as this method may be useful in the
Index: trunk/ippTools/src/dettool.h
===================================================================
--- trunk/ippTools/src/dettool.h	(revision 23281)
+++ trunk/ippTools/src/dettool.h	(revision 23310)
@@ -114,5 +114,8 @@
     DETTOOL_MODE_RERUN,
     DETTOOL_MODE_REGISTER_DETREND,
-    DETTOOL_MODE_REGISTER_DETREND_IMFILE
+    DETTOOL_MODE_REGISTER_DETREND_IMFILE,
+
+    DETTOOL_MODE_EXPORTRUN,
+    DETTOOL_MODE_IMPORTRUN
 } dettoolMode;
 
Index: trunk/ippTools/src/dettoolConfig.c
===================================================================
--- trunk/ippTools/src/dettoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/dettoolConfig.c	(revision 23310)
@@ -73,6 +73,6 @@
     psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
-    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run period (CURRENTLY NOT USED)", NULL);
-    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(definebytagArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
     psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-reduction",  0,            "define reduction class for processing", NULL);
     psMetadataAddStr(definebytagArgs, PS_LIST_TAIL, "-label",  0,            "define detrun label", NULL);
@@ -104,6 +104,6 @@
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
-    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period (CURRENTLY NOT USED)", NULL);
-    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(definebyqueryArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_exp_type",  0,            "search for exp_type", NULL);
     psMetadataAddStr(definebyqueryArgs, PS_LIST_TAIL, "-select_inst",  0,            "search for camera", NULL);
@@ -159,6 +159,6 @@
     psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_time_begin",  0,            "start of period to apply detrend too", NULL);
     psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_time_end",  0,            "end of period to apply detrend too", NULL);
-    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_begin",  0,            "start of detrend run applicable period (CURRENTLY NOT USED)", NULL);
-    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(definebydetrunArgs, PS_LIST_TAIL, "-set_use_end",  0,            "end of detrend run applicable period", NULL);
     psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_reduction",  0,            "define reduction class for processing", NULL);
     psMetadataAddStr(definebydetrunArgs, PS_LIST_TAIL, "-set_label",  0,            "define detrun label", NULL);
@@ -640,14 +640,13 @@
     // -residimfile
     psMetadata *residimfileArgs = psMetadataAlloc();
-    psMetadataAddS64(residimfileArgs,  PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
-    psMetadataAddS32(residimfileArgs,  PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
-    psMetadataAddS64(residimfileArgs,  PS_LIST_TAIL, "-exp_id",  0,            "search by detrend ID", 0);
-    psMetadataAddStr(residimfileArgs,  PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
-    psMetadataAddStr(residimfileArgs,  PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
-    psMetadataAddU64(residimfileArgs,  PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+    psMetadataAddS64(residimfileArgs, PS_LIST_TAIL, "-det_id",  0,            "search for detrend ID", 0);
+    psMetadataAddS32(residimfileArgs, PS_LIST_TAIL, "-iteration",  0,            "search for iteration number", 0);
+    psMetadataAddS64(residimfileArgs, PS_LIST_TAIL, "-exp_id",  0,            "search by detrend ID", 0);
+    psMetadataAddStr(residimfileArgs, PS_LIST_TAIL, "-class_id",  0,            "search for class ID", NULL);
+    psMetadataAddStr(residimfileArgs, PS_LIST_TAIL, "-recip",  0,            "search for recipe", NULL);
+    psMetadataAddU64(residimfileArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
     psMetadataAddBool(residimfileArgs, PS_LIST_TAIL, "-faulted",  0,            "only return imfiles with a fault status set", false);
     psMetadataAddBool(residimfileArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
-    psMetadataAddBool(residimfileArgs, PS_LIST_TAIL, "-included",  0,            "restrict results to exposures 'includeded' in the current iteration", false);
-    psMetadataAddStr(residimfileArgs,  PS_LIST_TAIL, "-select_state",  0,            "search for state", NULL);
+    psMetadataAddStr(residimfileArgs, PS_LIST_TAIL, "-select_state",  0,            "search for state", NULL);
 
     // -revertresidimfile
@@ -834,6 +833,6 @@
     psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-time_begin",  0,            "detrend applies to exposures taken during this period", NULL);
     psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-time_end",  0,            "detrend applies to exposures taken during this period", NULL);
-    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period (CURRENTLY NOT USED)", NULL);
-    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period (CURRENTLY NOT USED)", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_begin",  0,            "start of detrend run applicable period", NULL);
+    psMetadataAddTime(register_detrendArgs, PS_LIST_TAIL, "-use_end",  0,            "end of detrend run applicable period", NULL);
     psMetadataAddS64(register_detrendArgs, PS_LIST_TAIL, "-ref_det_id",  0,            "define reference det_id", 0);
     psMetadataAddS32(register_detrendArgs, PS_LIST_TAIL, "-ref_iter",  0,            "define reference iteration", -1);
@@ -856,4 +855,15 @@
     psMetadataAddStr(register_detrend_imfileArgs, PS_LIST_TAIL, "-path_base",  0,            "define base output location", NULL);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-det_id", 0,          "export this detrend ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
     psFree(now);
 
@@ -948,4 +958,6 @@
     PXOPT_ADD_MODE("-register_detrend", "", DETTOOL_MODE_REGISTER_DETREND, register_detrendArgs);
     PXOPT_ADD_MODE("-register_detrend_imfile", "", DETTOOL_MODE_REGISTER_DETREND_IMFILE, register_detrend_imfileArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", DETTOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           DETTOOL_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: trunk/ippTools/src/difftool.c
===================================================================
--- trunk/ippTools/src/difftool.c	(revision 23281)
+++ trunk/ippTools/src/difftool.c	(revision 23310)
@@ -45,4 +45,6 @@
 static bool donecleanupMode(pxConfig *config);
 static bool updatediffskyfileMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 static bool setdiffRunState(pxConfig *config, psS64 diff_id, const char *state);
@@ -81,4 +83,6 @@
         MODECASE(DIFFTOOL_MODE_DONECLEANUP,           donecleanupMode);
         MODECASE(DIFFTOOL_MODE_UPDATEDIFFSKYFILE,     updatediffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_EXPORTRUN,             exportrunMode);
+        MODECASE(DIFFTOOL_MODE_IMPORTRUN,             importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -1437,2 +1441,150 @@
 }
 
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+  
+  int numExportFiles = 3;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-diff_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-diff_id", "diff_id", "==");
+
+  ExportTable tables [] = {
+    {"diffRun", "difftool_export_run.sql"},
+    {"diffInputSkyfile", "difftool_export_input_skyfile.sql"},
+    {"diffSkyfile", "difftool_export_skyfile.sql"},
+  };
+
+  for (int i=0; i < numExportFiles; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    // we must write the export table in non-simple (true) format
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+  }
+
+  fclose (f);
+
+  return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+  
+  int numImportTables = 2;
+  
+  char tables[2] [80] = {"diffInputSkyfile", "diffSkyfile"};
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  psMetadataItem *item = psMetadataLookup (input, "diffRun");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  diffRunRow *diffRun = diffRunObjectFromMetadata (entry->data.md);
+  diffRunInsertObject (config->dbh, diffRun);
+
+  // fprintf (stdout, "---- diff run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+
+  for (int i = 0; i < numImportTables; i++) {
+    item = psMetadataLookup (input, tables[i]);
+    psAssert (item, "entry not in input?");
+    psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+    switch (i) {
+      case 0:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          diffInputSkyfileRow *diffInputSkyfile = diffInputSkyfileObjectFromMetadata (entry->data.md);
+          diffInputSkyfileInsertObject (config->dbh, diffInputSkyfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 1:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          diffSkyfileRow *diffSkyfile = diffSkyfileObjectFromMetadata (entry->data.md);
+          diffSkyfileInsertObject (config->dbh, diffSkyfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+    }
+  }
+
+  return true;
+}
Index: trunk/ippTools/src/difftool.h
===================================================================
--- trunk/ippTools/src/difftool.h	(revision 23281)
+++ trunk/ippTools/src/difftool.h	(revision 23310)
@@ -39,4 +39,6 @@
     DIFFTOOL_MODE_DONECLEANUP,
     DIFFTOOL_MODE_UPDATEDIFFSKYFILE,
+    DIFFTOOL_MODE_EXPORTRUN,
+    DIFFTOOL_MODE_IMPORTRUN
 } difftoolMode;
 
Index: trunk/ippTools/src/difftoolConfig.c
===================================================================
--- trunk/ippTools/src/difftoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/difftoolConfig.c	(revision 23310)
@@ -187,4 +187,15 @@
     psMetadataAddS16(updatediffskyfileArgs, PS_LIST_TAIL, "-code", 0,         "set fault code (required)", 0);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-diff_id", 0,          "export this diff ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
 
     psFree(now);
@@ -207,4 +218,6 @@
     PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     DIFFTOOL_MODE_DONECLEANUP,          donecleanupArgs);
     PXOPT_ADD_MODE("-updatediffskyfile",     "update fault code for a diffskyfile",  DIFFTOOL_MODE_UPDATEDIFFSKYFILE,          updatediffskyfileArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", DIFFTOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           DIFFTOOL_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: trunk/ippTools/src/faketool.c
===================================================================
--- trunk/ippTools/src/faketool.c	(revision 23281)
+++ trunk/ippTools/src/faketool.c	(revision 23310)
@@ -41,5 +41,5 @@
 static bool revertprocessedimfileMode(pxConfig *config);
 static bool updateprocessedimfileMode(pxConfig *config);
-static bool advanceexpMode(pxConfig *config);
+static bool promoteexpMode(pxConfig *config);
 static bool blockMode(pxConfig *config);
 static bool maskedMode(pxConfig *config);
@@ -52,4 +52,6 @@
 static bool tofullimfileMode(pxConfig *config);
 static bool topurgedimfileMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -78,5 +80,5 @@
         MODECASE(FAKETOOL_MODE_REVERTPROCESSEDIMFILE,   revertprocessedimfileMode);
         MODECASE(FAKETOOL_MODE_UPDATEPROCESSEDIMFILE,   updateprocessedimfileMode);
-        MODECASE(FAKETOOL_MODE_ADVANCEEXP,              advanceexpMode);
+        MODECASE(FAKETOOL_MODE_PROMOTEEXP,              promoteexpMode);
         MODECASE(FAKETOOL_MODE_BLOCK,                   blockMode);
         MODECASE(FAKETOOL_MODE_MASKED,                  maskedMode);
@@ -89,4 +91,6 @@
         MODECASE(FAKETOOL_MODE_TOFULLIMFILE,            tofullimfileMode);
         MODECASE(FAKETOOL_MODE_TOPURGEDIMFILE,          topurgedimfileMode);
+        MODECASE(FAKETOOL_MODE_EXPORTRUN,               exportrunMode);
+        MODECASE(FAKETOOL_MODE_IMPORTRUN,               importrunMode);
 
         default:
@@ -1048,5 +1052,5 @@
 }
 
-static bool advanceexpMode(pxConfig *config)
+static bool promoteexpMode(pxConfig *config)
 {
     PS_ASSERT_PTR_NON_NULL(config, false);
@@ -1225,2 +1229,127 @@
     return change_imfile_data_state(config, "purged", "goto_purged");
 }
+
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+
+  int numExportTables = 2;
+  
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-fake_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
+
+  ExportTable tables [] = {
+    {"fakeRun", "faketool_export_run.sql"},
+    {"fakeProcessedImfile", "faketool_export_processed_imfile.sql"},
+  };
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    // we must write the export table in non-simple (true) format
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+  }
+
+    fclose (f);
+
+    return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  psMetadataItem *item = psMetadataLookup (input, "fakeRun");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  fakeRunRow *fakeRun = fakeRunObjectFromMetadata (entry->data.md);
+  fakeRunInsertObject (config->dbh, fakeRun);
+
+  // fprintf (stdout, "---- fake run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+
+  item = psMetadataLookup (input, "fakeProcessedImfile");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  for (int i = 0; i < item->data.list->n; i++) {
+    psMetadataItem *entry = psListGet (item->data.list, i);
+    assert (entry);
+    assert (entry->type == PS_DATA_METADATA);
+    fakeProcessedImfileRow *fakeProcessedImfile = fakeProcessedImfileObjectFromMetadata (entry->data.md);
+    fakeProcessedImfileInsertObject (config->dbh, fakeProcessedImfile);
+
+    // fprintf (stdout, "---- row %d ----\n", i);
+    // psMetadataPrint (stderr, entry->data.md, 1);
+  }
+
+  return true;
+}
Index: trunk/ippTools/src/faketool.h
===================================================================
--- trunk/ippTools/src/faketool.h	(revision 23281)
+++ trunk/ippTools/src/faketool.h	(revision 23310)
@@ -33,5 +33,5 @@
     FAKETOOL_MODE_REVERTPROCESSEDIMFILE,
     FAKETOOL_MODE_UPDATEPROCESSEDIMFILE,
-    FAKETOOL_MODE_ADVANCEEXP,
+    FAKETOOL_MODE_PROMOTEEXP,
     FAKETOOL_MODE_BLOCK,
     FAKETOOL_MODE_MASKED,
@@ -45,4 +45,6 @@
     FAKETOOL_MODE_TOFULLIMFILE,
     FAKETOOL_MODE_TOPURGEDIMFILE,
+    FAKETOOL_MODE_EXPORTRUN,
+    FAKETOOL_MODE_IMPORTRUN
 } FAKETOOLMode;
 
Index: trunk/ippTools/src/faketoolConfig.c
===================================================================
--- trunk/ippTools/src/faketoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/faketoolConfig.c	(revision 23310)
@@ -242,9 +242,9 @@
 
 
-    // -advanceexp
-    psMetadata *advanceexpArgs = psMetadataAlloc();
-    psMetadataAddS64(advanceexpArgs, PS_LIST_TAIL, "-fake_id", 0,      "search by fake ID", 0);
-    psMetadataAddStr(advanceexpArgs, PS_LIST_TAIL, "-label",  0,       "search by label ", NULL);
-    psMetadataAddU64(advanceexpArgs, PS_LIST_TAIL, "-limit",  0,       "limit exposures to advance to N items", 0);
+    // -promoteexp
+    psMetadata *promoteexpArgs = psMetadataAlloc();
+    psMetadataAddS64(promoteexpArgs, PS_LIST_TAIL, "-fake_id", 0,      "search by fake ID", 0);
+    psMetadataAddStr(promoteexpArgs, PS_LIST_TAIL, "-label",  0,       "search by label ", NULL);
+    psMetadataAddU64(promoteexpArgs, PS_LIST_TAIL, "-limit",  0,       "limit exposures to promote to N items", 0);
 
     // -block
@@ -301,4 +301,15 @@
     psMetadataAddStr(topurgedimfileArgs, PS_LIST_TAIL, "-class_id",  0,        "class ID to update", NULL);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-fake_id", 0,          "export this fake ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
 
 
@@ -314,5 +325,5 @@
     PXOPT_ADD_MODE("-updateprocessedimfile","change procesed imfile properties",     FAKETOOL_MODE_UPDATEPROCESSEDIMFILE,    updateprocessedimfileArgs);
     PXOPT_ADD_MODE("-revertprocessedimfile", "undo a processed imfile",              FAKETOOL_MODE_REVERTPROCESSEDIMFILE,    revertprocessedimfileArgs);
-    PXOPT_ADD_MODE("-advanceexp",            "advance completed exposoures",         FAKETOOL_MODE_ADVANCEEXP,          advanceexpArgs);
+    PXOPT_ADD_MODE("-promoteexp",            "promote completed exposoures",         FAKETOOL_MODE_PROMOTEEXP,          promoteexpArgs);
     PXOPT_ADD_MODE("-block",                 "set a label block",                    FAKETOOL_MODE_BLOCK,          blockArgs);
     PXOPT_ADD_MODE("-masked",                "show blocked labels",                  FAKETOOL_MODE_MASKED,         maskedArgs);
@@ -325,4 +336,6 @@
     PXOPT_ADD_MODE("-tofullimfile",        "set imfile state to full",               FAKETOOL_MODE_TOFULLIMFILE,         tofullimfileArgs);
     PXOPT_ADD_MODE("-topurgedimfile",      "set imfile state to purged",             FAKETOOL_MODE_TOPURGEDIMFILE,       topurgedimfileArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", FAKETOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           FAKETOOL_MODE_IMPORTRUN, importrunArgs);
 
 
Index: trunk/ippTools/src/flatcorr.c
===================================================================
--- trunk/ippTools/src/flatcorr.c	(revision 23281)
+++ trunk/ippTools/src/flatcorr.c	(revision 23310)
@@ -46,4 +46,6 @@
 static bool inputexpMode(pxConfig *config);
 static bool inputimfileMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 static bool setflatcorrRunState(pxConfig *config, psS64 corr_id, const char *state);
@@ -78,4 +80,6 @@
         MODECASE(FLATCORR_MODE_INPUTEXP,       inputexpMode);
         MODECASE(FLATCORR_MODE_INPUTIMFILE,    inputimfileMode);
+        MODECASE(FLATCORR_MODE_EXPORTRUN,      exportrunMode);
+        MODECASE(FLATCORR_MODE_IMPORTRUN,      importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -734,2 +738,144 @@
     return true;
 }
+
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+  
+  int numExportTables = 3;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-corr_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-coor_id", "corr_id", "==");
+
+  ExportTable tables [] = {
+    {"flatcorrRun", "flatcorrtool_export_run.sql"},
+    {"flatcorrCamLink", "flatcorrtool_export_cam_link.sql"},
+    {"flatcorrChipLink", "flatcorr_export_chip_link.sql"},
+  };
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    // we must write the export table in non-simple (true) format
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+  }
+
+    fclose (f);
+
+    return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+  psMetadataItem *item, *entry;
+  
+  int numImportTables = 3;
+  
+  char tables[3] [80] = {"flatcorrRun", "flatcorrCamLink", "flatcorrChipLink"};
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  for (int i = 0; i < numImportTables; i++) {
+    item = psMetadataLookup (input, tables[i]);
+    psAssert (item, "entry not in input?");
+    psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+    
+    entry = psListGet (item->data.list, 0);
+    assert (entry);
+    assert (entry->type == PS_DATA_METADATA);
+  
+    switch (i) {
+      case 0:
+      {
+        flatcorrRunRow *flatcorrRun = flatcorrRunObjectFromMetadata (entry->data.md);
+        flatcorrRunInsertObject (config->dbh, flatcorrRun);
+
+        // fprintf (stdout, "---- flatcorr run ----\n");
+        // psMetadataPrint (stderr, entry->data.md, 1);
+        break;
+      } 
+      case 1:
+      {
+        flatcorrCamLinkRow *flatcorrCamLink = flatcorrCamLinkObjectFromMetadata (entry->data.md);
+        flatcorrCamLinkInsertObject (config->dbh, flatcorrCamLink);
+
+        // fprintf (stdout, "---- flatcorr cam link ----\n");
+        // psMetadataPrint (stderr, entry->data.md, 1);
+        break;
+      }
+      case 2:
+      {
+        flatcorrChipLinkRow *flatcorrChipLink = flatcorrChipLinkObjectFromMetadata (entry->data.md);
+        flatcorrChipLinkInsertObject (config->dbh, flatcorrChipLink);
+
+        // fprintf (stdout, "---- flatcorr chip link ----\n");
+        // psMetadataPrint (stderr, entry->data.md, 1);
+        break;
+      }
+    }
+  }
+  return true;
+}
Index: trunk/ippTools/src/flatcorr.h
===================================================================
--- trunk/ippTools/src/flatcorr.h	(revision 23281)
+++ trunk/ippTools/src/flatcorr.h	(revision 23310)
@@ -35,5 +35,7 @@
     FLATCORR_MODE_UPDATERUN,
     FLATCORR_MODE_INPUTEXP,
-    FLATCORR_MODE_INPUTIMFILE
+    FLATCORR_MODE_INPUTIMFILE,
+    FLATCORR_MODE_EXPORTRUN,
+    FLATCORR_MODE_IMPORTRUN
 } flatcorrMode;
 
Index: trunk/ippTools/src/flatcorrConfig.c
===================================================================
--- trunk/ippTools/src/flatcorrConfig.c	(revision 23281)
+++ trunk/ippTools/src/flatcorrConfig.c	(revision 23310)
@@ -125,4 +125,15 @@
     psMetadataAddU64(inputimfileArgs, PS_LIST_TAIL, "-limit",   0, "limit result set to N items", 0);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-corr_id", 0,          "export this correction ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
     psFree(now);
 
@@ -141,4 +152,6 @@
     PXOPT_ADD_MODE("-inputexp",       "list exposures for a correction run",               FLATCORR_MODE_INPUTEXP,       inputexpArgs);
     PXOPT_ADD_MODE("-inputimfile",    "list imfiles for a chip run",                       FLATCORR_MODE_INPUTIMFILE,    inputimfileArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", FLATCORR_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           FLATCORR_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: trunk/ippTools/src/pxadmin.c
===================================================================
--- trunk/ippTools/src/pxadmin.c	(revision 23281)
+++ trunk/ippTools/src/pxadmin.c	(revision 23310)
@@ -29,4 +29,5 @@
 
 bool createMode(pxConfig *config);
+bool createMirrorMode(pxConfig *config);
 bool deleteMode(pxConfig *config);
 static bool runMultipleStatments(pxConfig *config, const char *query);
@@ -53,4 +54,9 @@
             }
             break;
+        case PXADMIN_MODE_CREATE_MIRROR:
+            if (!createMirrorMode(config)) {
+                goto FAIL;
+            }
+            break;
         case PXADMIN_MODE_DELETE:
             if (!deleteMode(config)) {
@@ -86,4 +92,40 @@
 
     psString query = pxDataGet("pxadmin_create_tables.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    // BEGIN
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!runMultipleStatments(config, query)) {
+        if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    // COMMIT
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool createMirrorMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psString query = pxDataGet("pxadmin_create_mirror_tables.sql");
     if (!query) {
         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
Index: trunk/ippTools/src/pxadmin.h
===================================================================
--- trunk/ippTools/src/pxadmin.h	(revision 23281)
+++ trunk/ippTools/src/pxadmin.h	(revision 23310)
@@ -26,4 +26,5 @@
     PXADMIN_MODE_NONE      = 0x0,
     PXADMIN_MODE_CREATE,
+    PXADMIN_MODE_CREATE_MIRROR,
     PXADMIN_MODE_DELETE,
     PXADMIN_MODE_RECREATE
Index: trunk/ippTools/src/pxadminConfig.c
===================================================================
--- trunk/ippTools/src/pxadminConfig.c	(revision 23281)
+++ trunk/ippTools/src/pxadminConfig.c	(revision 23310)
@@ -31,5 +31,5 @@
     fprintf (stderr, "\nPan-STARRS DataBase Admin Tool\n\n");
     fprintf (stderr, "Usage: %s [mode]\n", program);
-    fprintf (stderr, " [mode] : -create | -delete\n\n");
+    fprintf (stderr, " [mode] : -create | -create-mirror | -delete\n\n");
 
     psMetadataItem *server = pmConfigUserSite(config->modules, "DBSERVER",   PS_DATA_STRING);
@@ -87,4 +87,11 @@
         config->mode = PXADMIN_MODE_CREATE;
     }
+    if ((N = psArgumentGet(argc, argv, "-create-mirror"))) {
+        psArgumentRemove(N, &argc, argv);
+        if (config->mode) {
+            psAbort("only one mode selection is allowed");
+        }
+        config->mode = PXADMIN_MODE_CREATE_MIRROR;
+    }
     if ((N = psArgumentGet(argc, argv, "-delete"))) {
         psArgumentRemove(N, &argc, argv);
@@ -105,4 +112,6 @@
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-create", 0,
             "create all IPP tables", "");
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-create-mirror", 0,
+            "mirror all IPP tables", "");
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-delete", 0,
             "delete all IPP tables", "");
Index: trunk/ippTools/src/regtool.c
===================================================================
--- trunk/ippTools/src/regtool.c	(revision 23281)
+++ trunk/ippTools/src/regtool.c	(revision 23310)
@@ -44,4 +44,6 @@
 static bool updateprocessedexpMode(pxConfig *config);
 static bool cleardupexpMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -76,4 +78,6 @@
         MODECASE(REGTOOL_MODE_UPDATEPROCESSEDEXP,    updateprocessedexpMode);
         MODECASE(REGTOOL_MODE_CLEARDUPEXP,           cleardupexpMode);
+        MODECASE(CHIPTOOL_MODE_EXPORTRUN,            exportrunMode);
+        MODECASE(CHIPTOOL_MODE_IMPORTRUN,            importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -1107,2 +1111,128 @@
     return true;
 }
+
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+  
+  int numExportTables = 2;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-exp_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+    psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+    return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-exp_id", "exp_id", "==");
+
+  ExportTable tables [] = {
+    {"rawExp", "regtool_export_raw__exp.sql"},
+    {"rawImfile", "regtool_export_raw_imfile.sql"},
+  };
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+
+    // we must write the export table in non-simple (true) format
+    if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+      psError(PS_ERR_UNKNOWN, false, "failed to print array");
+      psFree(output);
+      return false;
+    }
+    psFree(output);
+  }
+
+  fclose (f);
+
+  return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  psMetadataItem *item = psMetadataLookup (input, "rawExp");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  rawExpRow *rawExp = rawExpObjectFromMetadata (entry->data.md);
+  rawExpInsertObject (config->dbh, rawExp);
+
+  // fprintf (stdout, "---- raw exp ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+
+  item = psMetadataLookup (input, "rawImfile");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  for (int i = 0; i < item->data.list->n; i++) {
+    psMetadataItem *entry = psListGet (item->data.list, i);
+    assert (entry);
+    assert (entry->type == PS_DATA_METADATA);
+    rawImfileRow *rawImfile = rawImfileObjectFromMetadata (entry->data.md);
+    rawImfileInsertObject (config->dbh, rawImfile);
+
+    // fprintf (stdout, "---- row %d ----\n", i);
+    // psMetadataPrint (stderr, entry->data.md, 1);
+  }
+
+  return true;
+}
+
Index: trunk/ippTools/src/regtool.h
===================================================================
--- trunk/ippTools/src/regtool.h	(revision 23281)
+++ trunk/ippTools/src/regtool.h	(revision 23310)
@@ -36,4 +36,6 @@
     REGTOOL_MODE_UPDATEPROCESSEDEXP,
     REGTOOL_MODE_CLEARDUPEXP,
+    REGTOOL_MODE_EXPORTRUN,
+    REGTOOL_MODE_IMPORTRUN
 } regtoolMode;
 
Index: trunk/ippTools/src/regtoolConfig.c
===================================================================
--- trunk/ippTools/src/regtoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/regtoolConfig.c	(revision 23310)
@@ -278,4 +278,15 @@
     psMetadataAddS16(updatedprocessedexpArgs, PS_LIST_TAIL, "-code",    0,            "set fault code (required)", INT16_MAX);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-exp_id", 0,          "export this exposure ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
     // -cleardupexp
     psMetadata *cleardupexpArgs = psMetadataAlloc();
@@ -295,4 +306,6 @@
     PXOPT_ADD_MODE("-updateprocessedexp",      "", REGTOOL_MODE_UPDATEPROCESSEDEXP,      updatedprocessedexpArgs);
     PXOPT_ADD_MODE("-cleardupexp",             "", REGTOOL_MODE_CLEARDUPEXP,      cleardupexpArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", REGTOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           REGTOOL_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: trunk/ippTools/src/stacktool.c
===================================================================
--- trunk/ippTools/src/stacktool.c	(revision 23281)
+++ trunk/ippTools/src/stacktool.c	(revision 23310)
@@ -44,4 +44,6 @@
 static bool donecleanupMode(pxConfig *config);
 static bool updatesumskyfileMode(pxConfig *config);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
 
 static bool setstackRunState(pxConfig *config, psS64 stack_id, const char *state);
@@ -78,4 +80,6 @@
         MODECASE(STACKTOOL_MODE_DONECLEANUP,           donecleanupMode);
         MODECASE(STACKTOOL_MODE_UPDATESUMSKYFILE,      updatesumskyfileMode);
+        MODECASE(STACKTOOL_MODE_EXPORTRUN,             exportrunMode);
+        MODECASE(STACKTOOL_MODE_IMPORTRUN,             importrunMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -1180,2 +1184,143 @@
 }
 
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+
+  int numExportTables = 3;
+  
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+  PXOPT_LOOKUP_S64(det_id, config->args, "-stack_id", true,  false);
+  PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+  PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+  FILE *f = fopen (outfile, "w");
+  if (f == NULL) {
+      psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+      return false;
+  }
+
+  psMetadata *where = psMetadataAlloc();
+  PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
+
+  ExportTable tables [] = {
+    {"stackRun", "stacktool_export_run.sql"},
+    {"stackInputSkyfile", "stacktool_export_input_skyfile.sql"},
+    {"stackSumSkyfile", "stacktool_export_sum_skyfile.sql"},
+  };
+
+  for (int i=0; i < numExportTables; i++) {
+    psString query = pxDataGet(tables[i].sqlFilename);
+    if (!query) {
+      psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+      return false;
+    }
+
+    if (where && psListLength(where->list)) {
+      psString whereClause = psDBGenerateWhereSQL(where, NULL);
+      psStringAppend(&query, " %s", whereClause);
+      psFree(whereClause);
+    }
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+      psString limitString = psDBGenerateLimitSQL(limit);
+      psStringAppend(&query, " %s", limitString);
+      psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      psFree(query);
+      return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+      psError(PS_ERR_UNKNOWN, false, "database error");
+      return false;
+    }
+    if (!psArrayLength(output)) {
+      psTrace("regtool", PS_LOG_INFO, "no rows found");
+      psFree(output);
+      return true;
+    }
+    psFree(output);
+  }
+
+    fclose (f);
+
+    return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+  
+  int numImportTables = 2;
+  
+  char tables[2] [80] = {"stackInputSkyfile", "stackSumSkyfile"};
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  psMetadataItem *item = psMetadataLookup (input, "stackRun");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  stackRunRow *stackRun = stackRunObjectFromMetadata (entry->data.md);
+  stackRunInsertObject (config->dbh, stackRun);
+
+  // fprintf (stdout, "---- stack run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+
+  for (int i = 0; i < numImportTables; i++) {
+    psMetadataItem *item = psMetadataLookup (input, tables[i]);
+    psAssert (item, "entry not in input?");
+    psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+    switch (i) {
+      case 0:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          stackInputSkyfileRow *stackInputSkyfile = stackInputSkyfileObjectFromMetadata (entry->data.md);
+          stackInputSkyfileInsertObject (config->dbh, stackInputSkyfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 1:
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          stackSumSkyfileRow *stackSumSkyfile = stackSumSkyfileObjectFromMetadata (entry->data.md);
+          stackSumSkyfileInsertObject (config->dbh, stackSumSkyfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+    }
+  }
+  
+  return true;
+}
Index: trunk/ippTools/src/stacktool.h
===================================================================
--- trunk/ippTools/src/stacktool.h	(revision 23281)
+++ trunk/ippTools/src/stacktool.h	(revision 23310)
@@ -38,4 +38,6 @@
     STACKTOOL_MODE_DONECLEANUP,
     STACKTOOL_MODE_UPDATESUMSKYFILE,
+    STACKTOOL_MODE_EXPORTRUN,
+    STACKTOOL_MODE_IMPORTRUN
 } stacktoolMode;
 
Index: trunk/ippTools/src/stacktoolConfig.c
===================================================================
--- trunk/ippTools/src/stacktoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/stacktoolConfig.c	(revision 23310)
@@ -187,4 +187,15 @@
     psMetadataAddS16(updatesumskyfileArgs, PS_LIST_TAIL, "-code", 0,            "set fault code (required)", 0);
 
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-stack_id", 0,          "export this stack ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
+
     psFree(now);
 
@@ -205,4 +216,6 @@
     PXOPT_ADD_MODE("-donecleanup",           "show runs that have been cleaned",     STACKTOOL_MODE_DONECLEANUP,          donecleanupArgs);
     PXOPT_ADD_MODE("-updatesumskyfile",      "update fault code for sumskyfile",     STACKTOOL_MODE_UPDATESUMSKYFILE,          updatesumskyfileArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", STACKTOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           STACKTOOL_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
Index: trunk/ippTools/src/warptool.c
===================================================================
--- trunk/ippTools/src/warptool.c	(revision 23281)
+++ trunk/ippTools/src/warptool.c	(revision 23310)
@@ -54,6 +54,7 @@
 static bool tofullskyfileMode(pxConfig *config);
 static bool updateskyfileMode(pxConfig *config);
-
-static bool change_skyfile_data_state(pxConfig *config, psString data_state, psString run_state);
+static bool exportrunMode(pxConfig *config);
+static bool importrunMode(pxConfig *config);
+
 static bool parseAndInsertSkyCellMap(pxConfig *config, const char *mapfile);
 static bool isValidMode(pxConfig *config, const char *mode);
@@ -100,4 +101,6 @@
         MODECASE(WARPTOOL_MODE_TOFULLSKYFILE,      tofullskyfileMode);
         MODECASE(WARPTOOL_MODE_UPDATESKYFILE,      updateskyfileMode);
+        MODECASE(WARPTOOL_MODE_EXPORTRUN,          exportrunMode);
+        MODECASE(WARPTOOL_MODE_IMPORTRUN,          importrunMode);
 
         default:
@@ -1271,5 +1274,5 @@
 
         if (numUpdated < 1) {
-            psError(PS_ERR_UNKNOWN, false, "should have affected at least 1 row");
+            psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
             if (!psDBRollback(config->dbh)) {
                 psError(PS_ERR_UNKNOWN, false, "database error");
@@ -1605,9 +1608,4 @@
 // shared code for the modes -tocleanedskyfile -tofullskyfile -topurgedskyfile
 
-// XXX EAM : this function was enforcing only certain transitions with the SQL.  However,
-// this is getting fairly messy now that we have added a few additional target and
-// destination states.  I'm disabling these restrictions for now; is there are better way
-// to enforce the allowed state transitions?
-
 static bool change_skyfile_data_state(pxConfig *config, psString data_state, psString run_state)
 {
@@ -1625,8 +1623,6 @@
     }
 
-    // XXX this feature is disabled (run_state is ignored)
     // note only updates if warpRun.state = run_state
-
-    if (!p_psDBRunQueryF(config->dbh, query, data_state, warp_id, skycell_id)) {
+    if (!p_psDBRunQueryF(config->dbh, query, data_state, warp_id, skycell_id, run_state)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
         // rollback
@@ -1676,37 +1672,175 @@
     PXOPT_LOOKUP_S64(warp_id, config->args, "-warp_id", true, false);
     PXOPT_LOOKUP_STR(skycell_id, config->args, "-skycell_id", true, false);
-    PXOPT_LOOKUP_STR(state, config->args, "-set_state", false, false);
     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
 
-    if (state && code) {
-        psError(PS_ERR_UNKNOWN, true, "only one of -set_state and -code may be supplied");
-        return false;
-    }
-
-    if (state) {
-      // make sure that the state string is valid
-      if (!pxIsValidState(state)) {
-        psError(PXTOOLS_ERR_DATA, false, "%s is not a valid state", state);
-        return false;
+    psString query = pxDataGet("warptool_updateskyfile.sql");
+
+    if (!p_psDBRunQueryF(config->dbh, query, code, warp_id, skycell_id)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    psFree(query);
+
+    return true;
+}
+
+bool exportrunMode(pxConfig *config)
+{
+  typedef struct ExportTable {
+    char tableName[80];
+    char sqlFilename[80];
+  } ExportTable;
+
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_S64(det_id, config->args, "-warp_id", true,  false);
+    PXOPT_LOOKUP_STR(outfile, config->args, "-outfile", true,  false);
+    PXOPT_LOOKUP_U64(limit,   config->args, "-limit",   false, false);
+
+    FILE *f = fopen (outfile, "w");
+    if (f == NULL) {
+        psError(PS_ERR_UNKNOWN, false, "failed to open output file");
+        return false;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
+
+    ExportTable tables [] = {
+      {"warpRun", "warptool_export_run.sql"},
+      {"warpImfile", "warptool_export_imfile.sql"},
+      {"warpSkyfile", "warptool_export_skyfile.sql"},
+      {"warpSkyCellMap", "warptool_export_sky_cell_map.sql"},
+    };
+
+
+    for (int i=0; i < sizeof(tables); i++) {
+      psString query = pxDataGet(tables[i].sqlFilename);
+      if (!query) {
+          psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+          return false;
       }
-      if (!change_skyfile_data_state(config, state, "unknown")) {
-        psError(PS_ERR_UNKNOWN, false, "failed to set set fault flag");
-        return false;
+
+      if (where && psListLength(where->list)) {
+          psString whereClause = psDBGenerateWhereSQL(where, NULL);
+          psStringAppend(&query, " %s", whereClause);
+          psFree(whereClause);
       }
-      return true;
-    }
-
-    if (code) {
-      psString query = pxDataGet("warptool_updateskyfile.sql");
-
-      if (!p_psDBRunQueryF(config->dbh, query, code, warp_id, skycell_id)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
+
+      // treat limit == 0 as "no limit"
+      if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+      }
+
+      if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
         return false;
       }
       psFree(query);
-      return true;
-    }
-
-    psError(PS_ERR_UNKNOWN, true, "one of -set_state or -code must be supplied");
-    return false;
-}
+
+      psArray *output = p_psDBFetchResult(config->dbh);
+      if (!output) {
+          psError(PS_ERR_UNKNOWN, false, "database error");
+          return false;
+      }
+      if (!psArrayLength(output)) {
+        psTrace("regtool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+      }
+
+      // we must write the export table in non-simple (true) format
+      if (!ippdbPrintMetadatas(f, output, tables[i].tableName, true)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+      }
+      psFree(output);
+    }
+
+    fclose (f);
+
+    return true;
+}
+
+bool importrunMode(pxConfig *config)
+{
+  unsigned int nFail;
+
+  int numImportTables = 3;
+  
+  char tables[3] [80] = {"warpImfile", "warpSkyfile", "warpSkyCellMap"};
+
+  PS_ASSERT_PTR_NON_NULL(config, NULL);
+  
+  PXOPT_LOOKUP_STR(infile, config->args, "-infile", true,  false);
+
+  psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
+
+  fprintf (stdout, "---- input ----\n");
+  psMetadataPrint (stderr, input, 1);
+
+  psMetadataItem *item = psMetadataLookup (input, "warpRun");
+  psAssert (item, "entry not in input?");
+  psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+  
+  psMetadataItem *entry = psListGet (item->data.list, 0);
+  assert (entry);
+  assert (entry->type == PS_DATA_METADATA);
+  warpRunRow *warpRun = warpRunObjectFromMetadata (entry->data.md);
+  warpRunInsertObject (config->dbh, warpRun);
+
+  // fprintf (stdout, "---- warp run ----\n");
+  // psMetadataPrint (stderr, entry->data.md, 1);
+
+  for (int i = 0; i < numImportTables; i++) {
+    item = psMetadataLookup (input, tables[i]);
+    psAssert (item, "entry not in input?");
+    psAssert (item->type == PS_DATA_METADATA_MULTI, "entry not multi?");
+    
+    switch (i) {
+      case 0:  
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          warpImfileRow *warpImfile = warpImfileObjectFromMetadata (entry->data.md);
+          warpImfileInsertObject (config->dbh, warpImfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 1:  
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          warpSkyfileRow *warpSkyfile = warpSkyfileObjectFromMetadata (entry->data.md);
+          warpSkyfileInsertObject (config->dbh, warpSkyfile);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+        
+      case 2:  
+        for (int i = 0; i < item->data.list->n; i++) {
+          entry = psListGet (item->data.list, i);
+          assert (entry);
+          assert (entry->type == PS_DATA_METADATA);
+          warpSkyCellMapRow *warpSkyCellMap = warpSkyCellMapObjectFromMetadata (entry->data.md);
+          warpSkyCellMapInsertObject (config->dbh, warpSkyCellMap);
+
+          // fprintf (stdout, "---- row %d ----\n", i);
+          // psMetadataPrint (stderr, entry->data.md, 1);
+        }
+        break;
+    }
+  }
+  return true;
+}
Index: trunk/ippTools/src/warptool.h
===================================================================
--- trunk/ippTools/src/warptool.h	(revision 23281)
+++ trunk/ippTools/src/warptool.h	(revision 23310)
@@ -49,4 +49,6 @@
     WARPTOOL_MODE_TOFULLSKYFILE,
     WARPTOOL_MODE_UPDATESKYFILE,
+    WARPTOOL_MODE_EXPORTRUN,
+    WARPTOOL_MODE_IMPORTRUN
 } warptoolMode;
 
Index: trunk/ippTools/src/warptoolConfig.c
===================================================================
--- trunk/ippTools/src/warptoolConfig.c	(revision 23281)
+++ trunk/ippTools/src/warptoolConfig.c	(revision 23310)
@@ -348,10 +348,20 @@
     psMetadataAddStr(tofullskyfileArgs, PS_LIST_TAIL, "-skycell_id", 0, "skycell ID to update", NULL);
 
-    // -updateskyfile
+    // -toupdateskyfile
     psMetadata *updateskyfileArgs = psMetadataAlloc();
-    psMetadataAddS64(updateskyfileArgs, PS_LIST_TAIL, "-warp_id",    0, "warptool ID to update", 0);
+    psMetadataAddS64(updateskyfileArgs, PS_LIST_TAIL, "-warp_id", 0,    "warptool ID to update", 0);
     psMetadataAddStr(updateskyfileArgs, PS_LIST_TAIL, "-skycell_id", 0, "skycell ID to update", NULL);
-    psMetadataAddS16(updateskyfileArgs, PS_LIST_TAIL, "-code",       0, "set fault code", 0);
-    psMetadataAddStr(updateskyfileArgs, PS_LIST_TAIL, "-set_state",  0, "set state", NULL);
+    psMetadataAddS16(updateskyfileArgs, PS_LIST_TAIL, "-code",  0,      "new fault code", 0);
+
+    // -exportrun
+    psMetadata *exportrunArgs = psMetadataAlloc();
+    psMetadataAddS64(exportrunArgs, PS_LIST_TAIL, "-warp_id", 0,          "export this warp ID (required)", 0);
+    psMetadataAddStr(exportrunArgs, PS_LIST_TAIL, "-outfile", 0,          "export to this file (required)", NULL);
+    psMetadataAddU64(exportrunArgs, PS_LIST_TAIL, "-limit",   0,          "limit result set to N items", 0);
+
+    // -importrun
+    psMetadata *importrunArgs = psMetadataAlloc();
+    psMetadataAddStr(importrunArgs, PS_LIST_TAIL, "-infile",  0,          "import from this file (required)", NULL);
+
 
     psFree(now);
@@ -381,4 +391,6 @@
     PXOPT_ADD_MODE("-tofullskyfile", "set skyfile as full (updated)", WARPTOOL_MODE_TOFULLSKYFILE, tofullskyfileArgs);
     PXOPT_ADD_MODE("-updateskyfile", "update fault code for skyfile", WARPTOOL_MODE_UPDATESKYFILE, updateskyfileArgs);
+    PXOPT_ADD_MODE("-exportrun",            "export run for import on other database", WARPTOOL_MODE_EXPORTRUN, exportrunArgs);
+    PXOPT_ADD_MODE("-importrun",            "import run from metadata file",           WARPTOOL_MODE_IMPORTRUN, importrunArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
