Index: trunk/ippTools/src/warptool.c
===================================================================
--- trunk/ippTools/src/warptool.c	(revision 23251)
+++ 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;
+}
