Index: trunk/ippTools/configure.ac
===================================================================
--- trunk/ippTools/configure.ac	(revision 25844)
+++ trunk/ippTools/configure.ac	(revision 25851)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.61)
 
-AC_INIT([ipptools], [1.1.37], [ipp-support@ifa.hawaii.edu])
+AC_INIT([ipptools], [1.1.56], [ipp-support@ifa.hawaii.edu])
 AC_CONFIG_SRCDIR([autogen.sh])
 
@@ -58,4 +58,7 @@
 CFLAGS="${CFLAGS=} -Wall -Werror"
 
+IPPDB_VERSION=`$PKG_CONFIG --modversion ippdb`
+AC_DEFINE_UNQUOTED(IPPDB_VERSION, $IPPDB_VERSION, [Version of ippdb])
+
 AC_CONFIG_FILES([
   Makefile
Index: trunk/ippTools/share/Makefile.am
===================================================================
--- trunk/ippTools/share/Makefile.am	(revision 25844)
+++ trunk/ippTools/share/Makefile.am	(revision 25851)
@@ -216,4 +216,5 @@
      pxadmin_create_mirror_tables.sql \
      pxadmin_drop_tables.sql \
+     pxadmin_update_version.sql \
      pubtool_definerun.sql \
      pubtool_pending.sql \
Index: trunk/ippTools/share/pxadmin_create_tables.sql
===================================================================
--- trunk/ippTools/share/pxadmin_create_tables.sql	(revision 25844)
+++ trunk/ippTools/share/pxadmin_create_tables.sql	(revision 25851)
@@ -1,2 +1,7 @@
+CREATE TABLE dbversion (
+    schema_version VARCHAR(64),
+    updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
 CREATE TABLE pzDataStore (
     camera VARCHAR(64),
Index: trunk/ippTools/share/pxadmin_drop_tables.sql
===================================================================
--- trunk/ippTools/share/pxadmin_drop_tables.sql	(revision 25844)
+++ trunk/ippTools/share/pxadmin_drop_tables.sql	(revision 25851)
@@ -1,4 +1,5 @@
 SET FOREIGN_KEY_CHECKS=0;
 
+DROP TABLE IF EXISTS dbversion;
 DROP TABLE IF EXISTS pzDataStore;
 DROP TABLE IF EXISTS summitExp;
Index: trunk/ippTools/share/pxadmin_update_version.sql
===================================================================
--- trunk/ippTools/share/pxadmin_update_version.sql	(revision 25851)
+++ trunk/ippTools/share/pxadmin_update_version.sql	(revision 25851)
@@ -0,0 +1,1 @@
+UPDATE dbversion SET schema_version = '%s', updated = current_timestamp()
Index: trunk/ippTools/src/camtool.c
===================================================================
--- trunk/ippTools/src/camtool.c	(revision 25844)
+++ trunk/ippTools/src/camtool.c	(revision 25851)
@@ -1147,4 +1147,9 @@
   }
 
+  if (!pxExportVersion(config, f)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to write dbversion output file");
+    return false;
+  }
+
   psMetadata *where = psMetadataAlloc();
   PXOPT_COPY_S64(config->args, where, "-cam_id", "cam_id", "==");
@@ -1227,6 +1232,13 @@
   psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
 
-  fprintf (stdout, "---- input ----\n");
+#ifdef notdef
+  fprintf (stderr, "---- input ----\n");
   psMetadataPrint (stderr, input, 1);
+#endif
+
+  if (!pxCheckImportVersion(config, input)) {
+      psError(PS_ERR_UNKNOWN, false, "pxCheckImportVersion failed");
+      return false;
+  }
 
   psMetadataItem *item = psMetadataLookup (input, "camRun");
Index: trunk/ippTools/src/chiptool.c
===================================================================
--- trunk/ippTools/src/chiptool.c	(revision 25844)
+++ trunk/ippTools/src/chiptool.c	(revision 25851)
@@ -1377,4 +1377,9 @@
   }
 
+  if (!pxExportVersion(config, f)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to write dbversion output file");
+    return false;
+  }
+
   psMetadata *where = psMetadataAlloc();
   PXOPT_COPY_S64(config->args, where, "-chip_id", "chip_id", "==");
@@ -1468,4 +1473,14 @@
     psVector *identifiers = psVectorAllocEmpty(16, PS_TYPE_U64); // Identifiers inserted
 
+    psMetadataIterator *iter = psMetadataIteratorAlloc(input, PS_LIST_HEAD, NULL);       // Iterator
+
+    if (!pxCheckImportVersion(config, input)) {
+        psError(PS_ERR_UNKNOWN, false, "pxCheckImportVersion failed");
+        return false;
+    }
+    // first item is the dbversion, skip it
+    psMetadataItem *dbversion =  psMetadataGetAndIncrement(iter);
+    (void) dbversion;
+
     if (!psDBTransaction(config->dbh)) {
         psError(PS_ERR_UNKNOWN, false, "database error");
@@ -1473,5 +1488,4 @@
     }
 
-    psMetadataIterator *iter = psMetadataIteratorAlloc(input, PS_LIST_HEAD, NULL);       // Iterator
     psMetadataItem *item;               // Item from iteration
     while ((item = psMetadataGetAndIncrement(iter))) {
Index: trunk/ippTools/src/difftool.c
===================================================================
--- trunk/ippTools/src/difftool.c	(revision 25844)
+++ trunk/ippTools/src/difftool.c	(revision 25851)
@@ -2099,4 +2099,8 @@
   }
 
+  if (!pxExportVersion(config, f)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to write dbversion output file");
+    return false;
+  }
   psMetadata *where = psMetadataAlloc();
   PXOPT_COPY_S64(config->args, where, "-diff_id", "diff_id", "==");
@@ -2190,7 +2194,13 @@
   psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
 
-  fprintf (stdout, "---- input ----\n");
+#ifdef notdef
+  fprintf (stderr, "---- input ----\n");
   psMetadataPrint (stderr, input, 1);
-
+#endif
+
+  if (!pxCheckImportVersion(config, input)) {
+      psError(PS_ERR_UNKNOWN, false, "pxCheckImportVersion failed");
+      return false;
+  }
   psMetadataItem *item = psMetadataLookup (input, "diffRun");
   psAssert (item, "entry not in input?");
Index: trunk/ippTools/src/faketool.c
===================================================================
--- trunk/ippTools/src/faketool.c	(revision 25844)
+++ trunk/ippTools/src/faketool.c	(revision 25851)
@@ -1270,5 +1270,8 @@
     return false;
   }
-
+  if (!pxExportVersion(config, f)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to write dbversion output file");
+    return false;
+  }
   psMetadata *where = psMetadataAlloc();
   PXOPT_COPY_S64(config->args, where, "-fake_id", "fake_id", "==");
@@ -1351,7 +1354,13 @@
   psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
 
-  fprintf (stdout, "---- input ----\n");
+#ifdef notdef
+  fprintf (stderr, "---- input ----\n");
   psMetadataPrint (stderr, input, 1);
-
+#endif
+
+  if (!pxCheckImportVersion(config, input)) {
+      psError(PS_ERR_UNKNOWN, false, "pxCheckImportVersion failed");
+      return false;
+  }
   psMetadataItem *item = psMetadataLookup (input, "fakeRun");
   psAssert (item, "entry not in input?");
Index: trunk/ippTools/src/pxadmin.c
===================================================================
--- trunk/ippTools/src/pxadmin.c	(revision 25844)
+++ trunk/ippTools/src/pxadmin.c	(revision 25851)
@@ -2,5 +2,5 @@
  * pxadmin.c
  *
- * Copyright (C) 2006-2008  Joshua Hoblitt
+ * Copyright (C) 2006-2009  Joshua Hoblitt
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -31,4 +31,5 @@
 bool createMirrorMode(pxConfig *config);
 bool deleteMode(pxConfig *config);
+static bool insert_dbversion(pxConfig * config, const char *versionString);
 static bool runMultipleStatments(pxConfig *config, const char *query);
 
@@ -113,4 +114,9 @@
     psFree(query);
 
+    if (!insert_dbversion(config, PACKAGE_VERSION)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set database version");
+        return false;
+    }
+
     // COMMIT
     if (!psDBCommit(config->dbh)) {
@@ -148,4 +154,9 @@
     }
     psFree(query);
+
+    if (!insert_dbversion(config, PACKAGE_VERSION)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to set database version");
+        return false;
+    }
 
     // COMMIT
@@ -262,2 +273,35 @@
     return true;
 }
+
+#ifdef notdef
+static bool update_dbversion(pxConfig * config, const char *versionString)
+{
+    psString query = pxDataGet("pxadmin_update_version.sql");
+    if (!query) {
+        psError(PS_ERR_UNKNOWN, false, "failed to retrieve SQL statement");
+        psFree(query);
+        return false;
+    }
+    if (!p_psDBRunQueryF(config->dbh, query, versionString)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    return true;
+}
+#endif
+static bool insert_dbversion(pxConfig * config, const char *versionString)
+{
+    psString query = "INSERT INTO dbversion VALUES('%s', CURRENT_TIMESTAMP())";
+    if (!query) {
+        psError(PS_ERR_UNKNOWN, false, "failed to retrieve SQL statement");
+        psFree(query);
+        return false;
+    }
+    if (!p_psDBRunQueryF(config->dbh, query, versionString)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    return true;
+}
Index: trunk/ippTools/src/pxtools.c
===================================================================
--- trunk/ippTools/src/pxtools.c	(revision 25844)
+++ trunk/ippTools/src/pxtools.c	(revision 25851)
@@ -177,2 +177,116 @@
     return true;
 }
+
+bool pxLookupVersion(pxConfig *config, psArray **pArray)
+{
+    const char *query = "SELECT * FROM dbversion";
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psFree(output);
+        psError(PS_ERR_UNKNOWN, true, "no rows in dbversion");
+        return false;
+    }
+    if (psArrayLength(output) > 1) {
+        psError(PS_ERR_UNKNOWN, true, "unexpected number of rows found in dbversion: %" PRId64,
+                psArrayLength(output));
+        return false;
+    }
+    *pArray = output;
+
+    return true;
+}
+
+psString pxGetDBVersion(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    psArray *array = NULL;
+    if (!pxLookupVersion(config, &array)) {
+        psError(PS_ERR_UNKNOWN, false, "pxLookupVersion failed");
+        return NULL;
+    }
+    psMetadata *md = array->data[0];
+    if (!md) {
+        psError(PS_ERR_UNKNOWN, true, "output of pxLookupVersion is null");
+        return NULL;
+    }
+    
+    psString version = psMetadataLookupStr(NULL, md, "schema_version");
+
+    return version;
+}
+
+bool pxExportVersion(pxConfig *config, FILE *file)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(file, NULL);
+
+    psArray *array = NULL;
+    if (!pxLookupVersion(config, &array) || !array) {
+        psError(PS_ERR_UNKNOWN, false, "pxLookupVersion failed");
+        return false;
+    }
+    if (!ippdbPrintMetadatas(file, array, "dbversion", true)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(array);
+        return false;
+    }
+    return true;
+}
+
+bool pxCheckImportVersion(pxConfig *config, psMetadata *input)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(input, NULL);
+
+    // This code was adapted from the way camtool parses the structures.
+    // Is this really the way to do it?
+    psMetadataItem *multi_item =  psMetadataLookup(input, "dbversion");
+    if (!multi_item || (multi_item->type != PS_DATA_METADATA_MULTI)) {
+        psError(PS_ERR_UNKNOWN, true, "dbversion multi not found in input");
+        return false;
+    }
+    
+    psMetadataItem *dbversion = psListGet(multi_item->data.list, 0);
+    if (!dbversion) {
+        psError(PS_ERR_UNKNOWN, true, "dbversion not found in input");
+        return false;
+    }
+
+    if (!strcmp(dbversion->name, "dbversion")) {
+        // horray
+        psMetadata *md = dbversion->data.md;
+        psString schema_version = pxGetDBVersion(config);
+        if (!schema_version) {
+            psError(PS_ERR_UNKNOWN, false, "pxGetDBVersion failed");
+            return false;
+        }
+        
+        psString import_version = psMetadataLookupStr(NULL, md, "schema_version");
+        if (import_version && strcmp(import_version, schema_version)) {
+            psError(PS_ERR_UNKNOWN, true, "input file schema_version: %s does not match data base: %s",
+                import_version, schema_version);
+            return false;
+        } else if (!import_version) {
+            psError(PS_ERR_UNKNOWN, true, "input file schema_version is NULL");
+            return false;
+        } else {
+            // YIPPEE this file is the same version
+        }
+    } else {
+        psError(PS_ERR_UNKNOWN, true, "Unexpected config dump format");
+        return false;
+    }
+
+    return true;
+}
Index: trunk/ippTools/src/pxtools.h
===================================================================
--- trunk/ippTools/src/pxtools.h	(revision 25844)
+++ trunk/ippTools/src/pxtools.h	(revision 25851)
@@ -57,4 +57,6 @@
 
 bool pxSetFaultCode(psDB *dbh, const char *tableName, psMetadata *where, psS16 code);
+bool pxExportVersion(pxConfig *config, FILE *f);
+bool pxCheckImportVersion(pxConfig *config, psMetadata *md);
 
 psExit pxerrorGetExitStatus(void);
Index: trunk/ippTools/src/stacktool.c
===================================================================
--- trunk/ippTools/src/stacktool.c	(revision 25844)
+++ trunk/ippTools/src/stacktool.c	(revision 25851)
@@ -1297,4 +1297,8 @@
   }
 
+  if (!pxExportVersion(config, f)) {
+    psError(PS_ERR_UNKNOWN, false, "failed to write dbversion output file");
+    return false;
+  }
   psMetadata *where = psMetadataAlloc();
   PXOPT_COPY_S64(config->args, where, "-stack_id", "stack_id", "==");
@@ -1383,7 +1387,13 @@
   psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
 
-  fprintf (stdout, "---- input ----\n");
+#ifdef notdef
+  fprintf (stderr, "---- input ----\n");
   psMetadataPrint (stderr, input, 1);
-
+#endif
+
+  if (!pxCheckImportVersion(config, input)) {
+      psError(PS_ERR_UNKNOWN, false, "pxCheckImportVersion failed");
+      return false;
+  }
   psMetadataItem *item = psMetadataLookup (input, "stackRun");
   psAssert (item, "entry not in input?");
Index: trunk/ippTools/src/warptool.c
===================================================================
--- trunk/ippTools/src/warptool.c	(revision 25844)
+++ trunk/ippTools/src/warptool.c	(revision 25851)
@@ -1753,4 +1753,8 @@
     }
 
+    if (!pxExportVersion(config, f)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to write dbversion output file");
+        return false;
+    }
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_S64(config->args, where, "-warp_id", "warp_id", "==");
@@ -1845,6 +1849,13 @@
   psMetadata *input = psMetadataConfigRead (NULL, &nFail, infile, false);
 
-  fprintf (stdout, "---- input ----\n");
+#ifdef notdef
+  fprintf (stderr, "---- input ----\n");
   psMetadataPrint (stderr, input, 1);
+#endif
+
+  if (!pxCheckImportVersion(config, input)) {
+      psError(PS_ERR_UNKNOWN, false, "pxCheckImportVersion failed");
+      return false;
+  }
 
   psMetadataItem *item = psMetadataLookup (input, "warpRun");
