Index: trunk/ippTools/src/releasetool.c
===================================================================
--- trunk/ippTools/src/releasetool.c	(revision 37075)
+++ trunk/ippTools/src/releasetool.c	(revision 37095)
@@ -44,4 +44,5 @@
 static bool updaterelexpMode(pxConfig *config);
 static bool listrelexpMode(pxConfig *config);
+static bool deleterelexpMode(pxConfig *config);
 static bool definerelstackMode(pxConfig *config);
 static bool updaterelstackMode(pxConfig *config);
@@ -81,4 +82,5 @@
         MODECASE(RELEASETOOL_MODE_UPDATERELEXP,     updaterelexpMode);
         MODECASE(RELEASETOOL_MODE_LISTRELEXP,       listrelexpMode);
+        MODECASE(RELEASETOOL_MODE_DELETERELEXP,     deleterelexpMode);
 
         MODECASE(RELEASETOOL_MODE_DEFINERELSTACK,   definerelstackMode);
@@ -817,4 +819,62 @@
 
     psFree(output);
+
+    return true;
+}
+
+static bool deleterelexpMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(relexp_id, config->args,   "-relexp_id", false, false);
+    // If relexp_id is supplied that is all that we need
+    if (!relexp_id) {
+        // Otherwise we need to identify the release ...
+        PXOPT_LOOKUP_STR(release_name, config->args, "-release_name", false, false);
+        PXOPT_LOOKUP_S32(rel_id, config->args,      "-rel_id", false, false);
+
+        if (!release_name && !rel_id) {
+            psError(PXTOOLS_ERR_CONFIG, true, "at least one of -relexp_id, -release_name, or -rel_id is required\n");
+            return false;
+        }
+        // ... and the exposure
+        PXOPT_LOOKUP_STR(label, config->args,       "-label", false, false);
+        PXOPT_LOOKUP_S64(cam_id, config->args,      "-cam_id", false, false);
+        PXOPT_LOOKUP_S64(exp_id, config->args,      "-exp_id", false, false);
+        PXOPT_LOOKUP_STR(exp_name, config->args,    "-exp_name", false, false);
+        if (!label && !cam_id && !exp_id && !exp_name) {
+            psError(PXTOOLS_ERR_CONFIG, true, "at least one of -label, -cam_id, -exp_id, -exp_name is required\n");
+            return false;
+        }
+    }
+
+    psMetadata *where = psMetadataAlloc();
+
+    PXOPT_COPY_S32(config->args, where, "-relexp_id", "relExp.relexp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-label",  "camRun.label", "==");
+    PXOPT_COPY_S64(config->args, where, "-cam_id", "relExp.cam_id", "==");
+    PXOPT_COPY_S64(config->args, where, "-exp_id", "relExp.exp_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-exp_name", "rawExp.exp_name", "==");
+
+    PXOPT_COPY_S32(config->args, where, "-rel_id",  "rel_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-release_name", "release_name", "==");
+
+    psString query = pxDataGet("releasetool_deleterelexp.sql");
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, "\n    AND %s", whereClause);
+    psFree(whereClause);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    psU64 affected = psDBAffectedRows(config->dbh);
+    psLogMsg("releasetool", PS_LOG_INFO, "Deleted %" PRIu64 " relExp rows", affected);
+
+
+    psFree(query);
 
     return true;
