IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 15, 2008, 10:30:59 AM (18 years ago)
Author:
eugene
Message:

completely deprecate config->where; make all command-line handling consistent; move nearly all sql into share/*.sql; ensure consistency between args supplied and used

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ippTools/src/dettool.c

    r18336 r18561  
    1818 */
    1919
    20 #ifdef HAVB_CONFIG_H
    21 #include <config.h>
    22 #endif
    23 
    24 #include <stdio.h>
    25 #include <string.h>
    26 #include <stdlib.h>
    27 #include <stdint.h>
    28 #include <inttypes.h>
    29 
    30 #include <ippdb.h>
    31 
    32 #include "pxtools.h"
    3320#include "dettool.h"
    3421
     
    9885//static psArray *searchInputImfiles(pxConfig *config, const char *det_id);
    9986static detInputExpRow *rawDetrenTodetInputExpRow(rawExpRow *rawExp, psS64 det_id, psS32 iteration);
    100 static psArray *searchRawImfiles(pxConfig *config, psMetadata *where);
     87static psArray *searchRawImfiles(pxConfig *config);
    10188static bool startNewIteration(pxConfig *config, psS64 det_id);
    10289static psS32 incrementIteration(pxConfig *config, psS64 det_id);
     
    214201    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    215202
    216     psString query = psStringCopy(
    217         "SELECT"
    218         "   rawExp.*"
    219         " FROM rawExp"
    220         " LEFT JOIN detInputExp"
    221         "   ON rawExp.exp_id = detInputExp.exp_id"
    222         " WHERE"
    223         "    detInputExp.exp_id IS NULL"
    224         "    AND rawExp.object != 'object'"
    225     );
    226 
    227     if (config->where) {
    228         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "rawExp");
     203    psString query = pxDataGet("dettool_pending.sql");
     204    if (!query) {
     205        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     206        return false;
     207    }
     208   
     209    psMetadata *where = psMetadataAlloc();
     210    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     211    PXOPT_COPY_STR(config->args, where, "-exp_type", "exp_type", "==");
     212    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
     213    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
     214    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
     215
     216    if (psListLength(where->list)) {
     217        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawExp");
    229218        psStringAppend(&query, " AND %s", whereClause);
    230219        psFree(whereClause);
    231220    }
     221    psFree(where);
    232222
    233223    if (!p_psDBRunQuery(config->dbh, query)) {
     
    315305    // make sure that -exp_id was parsed correctly
    316306    // XXX this can be removed someday
     307    // XXX Special case for a multi : move into a macro?
    317308    if (item->type == PS_DATA_METADATA_MULTI) {
    318309        psListIterator *iter = psListIteratorAlloc(item->data.list, 0, false);
     
    472463#if 0
    473464// This function is used to convert the det_id from an int, as it is used
    474 // internally, to be a string for external use.  The rational being that we may
     465// internally, to be a string for external use.  The rationale being that we may
    475466// want to change how det_id is generated in the future and don't want to
    476467// external programs to become depending on this value being an int.
     
    543534    psMetadata *where = psMetadataAlloc();
    544535    PXOPT_COPY_STR(config->args, where, "-select_exp_type", "exp_type", "==");
    545     // map -inst -> camera
    546536    PXOPT_COPY_STR(config->args, where, "-select_inst", "camera", "==");
    547537    PXOPT_COPY_STR(config->args, where, "-select_telescope", "telescope", "==");
     
    555545    PXOPT_COPY_F32(config->args, where, "-select_exp_time_min", "exp_time", ">=");
    556546    PXOPT_COPY_F32(config->args, where, "-select_exp_time_max", "exp_time", "<=");
    557     PXOPT_COPY_F32(config->args, where, "-select_ccd_temp_min", "ccd_temp", ">=");
    558     PXOPT_COPY_F32(config->args, where, "-select_ccd_temp_max", "ccd_temp", "<=");
    559     PXOPT_COPY_F32(config->args, where, "-select_pon_time_min", "pon_time", ">=");
    560     PXOPT_COPY_F32(config->args, where, "-select_pon_time_max", "pon_time", "<=");
    561     PXOPT_COPY_F32(config->args, where, "-select_posang_min", "posang", ">=");
    562     PXOPT_COPY_F32(config->args, where, "-select_posang_max", "posang", "<=");
    563     PXOPT_COPY_F32(config->args, where, "-select_solang_min", "solang", ">=");
    564     PXOPT_COPY_F32(config->args, where, "-select_solang_max", "solang", "<=");
     547    PXOPT_COPY_F64(config->args, where, "-select_ccd_temp_min", "ccd_temp", ">=");
     548    PXOPT_COPY_F64(config->args, where, "-select_ccd_temp_max", "ccd_temp", "<=");
     549    PXOPT_COPY_F64(config->args, where, "-select_pon_time_min", "pon_time", ">=");
     550    PXOPT_COPY_F64(config->args, where, "-select_pon_time_max", "pon_time", "<=");
     551    PXOPT_COPY_F64(config->args, where, "-select_posang_min", "posang", ">=");
     552    PXOPT_COPY_F64(config->args, where, "-select_posang_max", "posang", "<=");
     553    PXOPT_COPY_F64(config->args, where, "-select_solang_min", "solang", ">=");
     554    PXOPT_COPY_F64(config->args, where, "-select_solang_max", "solang", "<=");
    565555
    566556    if (!psListLength(where->list)) {
     
    571561    // there is some namespace overlap between the names of the fields we'd
    572562    // like to search by to setup a detrun and the names of the fields we'd
    573     // like to assign values to so I've seperated them but prepending set- to
     563    // like to assign values to so I've separated them but prepending set- to
    574564    // the assigned values
    575565
     
    731721    PS_ASSERT_PTR_NON_NULL(config, false);
    732722
    733     // required
    734     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    735 
    736     // optional
    737     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    738     PXOPT_LOOKUP_STR(det_type, config->args, "-set_det_type", false, false);
    739     PXOPT_LOOKUP_STR(mode, config->args, "-set_mode", false, false);
    740     // check mode
    741     if (mode && !isValidMode(config, mode)) {
    742         psError(PS_ERR_UNKNOWN, false, "invalud mode");
    743         return false;
    744     }
    745     PXOPT_LOOKUP_STR(camera, config->args, "-set_inst", false, false);
    746     PXOPT_LOOKUP_STR(telescope, config->args, "-set_telescope", false, false);
     723   
     724    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     725    PXOPT_LOOKUP_STR(det_type, config->args, "-set_det_type", false, false); // optional
     726    PXOPT_LOOKUP_STR(mode, config->args, "-set_mode", false, false); // optional
    747727    PXOPT_LOOKUP_STR(exp_type, config->args, "-set_exp_type", false, false);
    748728    PXOPT_LOOKUP_STR(filelevel, config->args, "-set_filelevel", false, false);
    749729    PXOPT_LOOKUP_STR(workdir, config->args, "-set_workdir", false, false);
    750730    PXOPT_LOOKUP_STR(filter, config->args, "-set_filter", false, false);
    751 
    752731    PXOPT_LOOKUP_F32(airmass_min, config->args, "-set_airmass_min", false, false);
    753732    PXOPT_LOOKUP_F32(airmass_max, config->args, "-set_airmass_max", false, false);
    754733    PXOPT_LOOKUP_F32(exp_time_min, config->args, "-set_exp_time_min", false, false);
    755734    PXOPT_LOOKUP_F32(exp_time_max, config->args, "-set_exp_time_max", false, false);
    756     PXOPT_LOOKUP_F32(ccd_temp_min, config->args, "-set_ccd_temp_min", false, false);
    757     PXOPT_LOOKUP_F32(ccd_temp_max, config->args, "-set_ccd_temp_max", false, false);
    758     PXOPT_LOOKUP_F32(posang_min, config->args, "-set_posang_min", false, false);
    759     PXOPT_LOOKUP_F32(posang_max, config->args, "-set_posang_max", false, false);
    760     PXOPT_LOOKUP_F32(solang_min, config->args, "-set_solang_min", false, false);
    761     PXOPT_LOOKUP_F32(solang_max, config->args, "-set_solang_max", false, false);
    762     PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
     735    PXOPT_LOOKUP_F64(ccd_temp_min, config->args, "-set_ccd_temp_min", false, false);
     736    PXOPT_LOOKUP_F64(ccd_temp_max, config->args, "-set_ccd_temp_max", false, false);
     737    PXOPT_LOOKUP_F64(posang_min, config->args, "-set_posang_min", false, false);
     738    PXOPT_LOOKUP_F64(posang_max, config->args, "-set_posang_max", false, false);
     739    PXOPT_LOOKUP_F64(solang_min, config->args, "-set_solang_min", false, false);
     740    PXOPT_LOOKUP_F64(solang_max, config->args, "-set_solang_max", false, false);
    763741    PXOPT_LOOKUP_TIME(registered, config->args, "-set_registered", false, false);
    764742    PXOPT_LOOKUP_TIME(time_begin, config->args, "-set_time_begin", false, false);
     
    767745    PXOPT_LOOKUP_TIME(use_end, config->args, "-use_end", false, false);
    768746    PXOPT_LOOKUP_STR(reduction, config->args, "-set_reduction", false, false);
    769 
     747    PXOPT_LOOKUP_STR(label, config->args, "-set_label", false, false);
     748    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false); // optional
     749
     750    // check mode
     751    if (mode && !isValidMode(config, mode)) {
     752        psError(PS_ERR_UNKNOWN, false, "invalud mode");
     753        return false;
     754    }
    770755
    771756    // lookup the detRun that we will be basing this one on
     
    814799    }
    815800
    816     if (camera) {
    817         psFree(detRun->camera);
    818         detRun->camera = psStringCopy(camera);
    819     }
    820 
    821     if (telescope) {
    822         psFree(detRun->telescope);
    823         detRun->telescope = psStringCopy(telescope);
    824     }
    825 
    826801    if (exp_type) {
    827802        psFree(detRun->exp_type);
     
    925900    // XXX: possible mem leak: PXOPT_COPY* will free time_filter but NOTHING
    926901    // that has previously been allocated
    927     PXOPT_COPY_TIME(config->args, time_filter, "-filter_input_begin", "dateobs", ">=");
    928     PXOPT_COPY_TIME(config->args, time_filter, "-filter_input_end", "dateobs", "<");
     902    PXOPT_COPY_TIME(config->args, time_filter, "-set_input_begin", "dateobs", ">=");
     903    PXOPT_COPY_TIME(config->args, time_filter, "-set_input_end", "dateobs", "<");
    929904
    930905    // start a transaction so we don't end up with childlessed det_ids
     
    951926    psS64 newDet_id = psDBLastInsertID(config->dbh);
    952927
    953     psString query = psStringCopy(
    954         "INSERT INTO detInputExp"
    955         "   SELECT"
    956         "       %d,"
    957         "       0,"
    958         "       detResidExp.exp_id,"
    959         "       detResidExp.accept"
    960         "   FROM detResidExp"
    961         "   JOIN rawExp"
    962         "       USING(exp_id)"
    963         "   WHERE det_id = %d"
    964     );
     928    psString query = pxDataGet("dettool_definebydetrun.sql");
     929    if (!query) {
     930        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     931        return false;
     932    }
    965933
    966934    if (time_filter->list->n) {
     
    1017985    PS_ASSERT_PTR_NON_NULL(config, false);
    1018986
     987    psMetadata *where = psMetadataAlloc();
     988    PXOPT_COPY_STR(config->args, where, "-det_type", "det_type", "==");
     989    PXOPT_COPY_STR(config->args, where, "-det_id",   "det_id", "==");
     990
     991    PXOPT_COPY_STR(config->args, where, "-inst", "camera", "==");
     992    PXOPT_COPY_STR(config->args, where, "-telescope", "telescope", "==");
     993    PXOPT_COPY_STR(config->args, where, "-filter", "filter", "==");
     994
     995    // airmass_min  < airmass  < airmass_max
     996    PXOPT_COPY_F32(config->args, where, "-airmass", "airmass_min", "<=");
     997    PXOPT_COPY_F32(config->args, where, "-airmass", "airmass_max", ">=");
     998
     999    // exp_time_min < exp_time < exp_time_max
     1000    PXOPT_COPY_F32(config->args, where, "-exp_time", "exp_time_min", "<=");
     1001    PXOPT_COPY_F32(config->args, where, "-exp_time", "exp_time_max", ">=");
     1002
     1003    // ccd_temp_min < ccd_temp < ccd_temp_max
     1004    PXOPT_COPY_F32(config->args, where, "-ccd_temp", "ccd_temp_min", "<=");
     1005    PXOPT_COPY_F32(config->args, where, "-ccd_temp", "ccd_temp_max", ">=");
     1006
     1007    PXOPT_COPY_F64(config->args, where, "-posang", "posang_min", "<=");
     1008    PXOPT_COPY_F64(config->args, where, "-posang", "posang_max", ">=");
     1009
    10191010    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    10201011    PXOPT_LOOKUP_BOOL(active, config->args, "-active", false);
    10211012    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    10221013
    1023     PXOPT_COPY_STR(config->args, config->where, "-inst", "camera", "==");
    1024     PXOPT_COPY_STR(config->args, config->where, "-telescope", "telescope", "==");
    1025     PXOPT_COPY_STR(config->args, config->where, "-filter", "filter", "==");
    1026 
    1027     // airmass_min  < airmass  < airmass_max
    1028     PXOPT_COPY_F32(config->args, config->where, "-airmass", "airmass_min", "<=");
    1029     PXOPT_COPY_F32(config->args, config->where, "-airmass", "airmass_max", ">=");
    1030 
    1031     // exp_time_min < exp_time < exp_time_max
    1032     PXOPT_COPY_F32(config->args, config->where, "-exp_time", "exp_time_min", "<=");
    1033     PXOPT_COPY_F32(config->args, config->where, "-exp_time", "exp_time_max", ">=");
    1034 
    1035     // ccd_temp_min < ccd_temp < ccd_temp_max
    1036     PXOPT_COPY_F32(config->args, config->where, "-ccd_temp", "ccd_temp_min", "<=");
    1037     PXOPT_COPY_F32(config->args, config->where, "-ccd_temp", "ccd_temp_max", ">=");
    1038 
    1039     PXOPT_COPY_F64(config->args, config->where, "-posang", "posang_min", "<=");
    1040     PXOPT_COPY_F64(config->args, config->where, "-posang", "posang_max", ">=");
    1041 
    10421014    psString query = pxDataGet("dettool_runs.sql");
    10431015    if (!query) {
     
    10461018    }
    10471019
    1048     if (config->where && active) {
    1049         psString whereClause = psDBGenerateWhereSQL(config->where, "detRun");
     1020    if (psListLength(where->list) && active) {
     1021        psString whereClause = psDBGenerateWhereSQL(where, "detRun");
    10501022        psStringAppend(&query, " %s AND (detRun.state = 'run' OR detRun.state = 'stop' OR detRun.state = 'register')", whereClause);
    10511023        psFree(whereClause);
    10521024    }
    1053     if (config->where && !active) {
    1054         psString whereClause = psDBGenerateWhereSQL(config->where, "detRun");
     1025    if (psListLength(where->list) && !active) {
     1026        psString whereClause = psDBGenerateWhereSQL(where, "detRun");
    10551027        psStringAppend(&query, " %s", whereClause);
    10561028        psFree(whereClause);
    10571029    }
    1058     if (!config->where && active) {
     1030    if (!psListLength(where->list) && active) {
    10591031        psStringAppend(&query, " WHERE (detRun.state = 'run' OR detRun.state = 'stop' OR detRun.state = 'register')");
    10601032    }
     1033    psFree (where);
    10611034
    10621035    // treat limit == 0 as "no limit"
     
    10801053    }
    10811054
    1082 // XXX old version
    1083 # if 0
    1084     // XXX fix the hard coding of the table name
    1085     psArray *runs = psDBSelectRows(config->dbh, "detRun", config->where, 0);
    1086     if (!runs) {
    1087         psError(PS_ERR_UNKNOWN, false, "database error");
    1088         return false;
    1089     }
    1090 # endif
    1091 
    10921055    if (!psArrayLength(runs)) {
    10931056        psTrace("dettool", PS_LOG_INFO, "no rows found");
     
    11121075    PS_ASSERT_PTR_NON_NULL(config, false);
    11131076
     1077    psMetadata *where = psMetadataAlloc();
     1078    PXOPT_COPY_STR(config->args, where, "-det_type", "det_type", "==");
     1079
    11141080    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    11151081    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    11161082
    1117     psString query = psStringCopy(
    1118             "SELECT DISTINCT\n"
    1119             "   detRun.*\n"
    1120             " FROM detRun\n"
    1121             " LEFT JOIN detRun as foo\n"
    1122             "   ON foo.parent = detRun.det_id\n"
    1123             " WHERE\n"
    1124             "   detRun.state = 'stop'\n"
    1125             "   AND detRun.mode = 'master'\n"
    1126             "   AND foo.det_id IS NULL\n"
    1127         );
    1128 
    1129     if (config->where) {
    1130         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detRun");
     1083    // find the exp_id of all the exposures that we want to queue up.
     1084    psString query = pxDataGet("dettool_childlessrun.sql");
     1085    if (!query) {
     1086        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1087        psFree(where);
     1088        return false;
     1089    }
     1090
     1091    if (psListLength(where->list)) {
     1092        psString whereClause = psDBGenerateWhereConditionSQL(where, "detRun");
    11311093        psStringAppend(&query, " AND %s", whereClause);
    11321094        psFree(whereClause);
    11331095    }
     1096    psFree (where);
    11341097
    11351098    // treat limit == 0 as "no limit"
     
    11881151    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    11891152
    1190     // select detInputExp.*
    1191     // select rawExp.*
    1192     // by:
    1193     // exp_id
    1194 
    1195     psString query = psStringCopy(
    1196         "SELECT DISTINCT *"
    1197         " FROM detInputExp"
    1198         " JOIN rawExp"
    1199         " USING(exp_id)"
    1200         );
    1201 
    1202     if (config->where) {
    1203         psString whereClause = psDBGenerateWhereSQL(config->where, "detInputExp");
     1153    psMetadata *where = psMetadataAlloc();
     1154    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     1155    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     1156    PXOPT_COPY_S64(config->args, where, "-exp_id",    "exp_id", "==");
     1157
     1158    psString query = pxDataGet("dettool_input.sql");
     1159    if (!query) {
     1160        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1161        psFree(where);
     1162        return false;
     1163    }
     1164
     1165    if (psListLength(where->list)) {
     1166        psString whereClause = psDBGenerateWhereSQL(where, "detInputExp");
    12041167        psStringAppend(&query, " %s", whereClause);
    12051168        psFree(whereClause);
    12061169    }
     1170    psFree (where);
    12071171
    12081172    if (!p_psDBRunQuery(config->dbh, query)) {
     
    12421206    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    12431207
     1208    psMetadata *where = psMetadataAlloc();
     1209
    12441210    psString query = pxDataGet("dettool_raw.sql");
    12451211    if (!query) {
     
    12481214    }
    12491215
    1250     if (config->where) {
    1251         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "rawImfile");
     1216    if (psListLength(where->list)) {
     1217        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
    12521218        psStringAppend(&query, " AND %s", whereClause);
    12531219        psFree(whereClause);
    12541220    }
     1221    psFree (where);
    12551222
    12561223    if (!p_psDBRunQuery(config->dbh, query)) {
     
    12881255    PS_ASSERT_PTR_NON_NULL(config, false);
    12891256
     1257    psMetadata *where = psMetadataAlloc();
     1258    PXOPT_COPY_STR(config->args, where, "-det_id",   "det_id", "==");
     1259    PXOPT_COPY_STR(config->args, where, "-exp_id",   "exp_id", "==");
     1260    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
     1261
    12901262    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    12911263    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     
    12971269    }
    12981270
    1299     if (config->where) {
    1300         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "rawImfile");
     1271    if (psListLength(where->list)) {
     1272        psString whereClause = psDBGenerateWhereConditionSQL(where, "rawImfile");
    13011273        psStringAppend(&query, " AND %s", whereClause);
    13021274        psFree(whereClause);
    13031275    }
     1276    psFree (where);
    13041277
    13051278    // treat limit == 0 as "no limit"
     
    13401313}
    13411314
    1342 static psArray *searchRawImfiles(pxConfig *config, psMetadata *where)
    1343 {
    1344     PS_ASSERT_PTR_NON_NULL(config, NULL);
    1345 
    1346     // use the default where if "where" is NULL
    1347     if (!where) {
    1348         where = config->where;
    1349     }
    1350 
    1351     // select exp_ids from detInputExp matching det_idp
    1352     // where query should be pre-generated
    1353     psArray *detInputExp =
    1354         detInputExpSelectRowObjects(config->dbh, where, 0);
    1355     if (!detInputExp) {
    1356         psError(PS_ERR_UNKNOWN, false, "no rawExp rows found");
    1357         return NULL;
    1358     }
    1359 
    1360     // generate where query with just the exp_ids
    1361     psMetadata *where_exp_ids = psMetadataAlloc();
    1362     for (long i = 0; i < psArrayLength(detInputExp); i++) {
    1363         detInputExpRow *row = detInputExp->data[i];
    1364         if (!psMetadataAddS64(where_exp_ids, PS_LIST_TAIL, "exp_id",
    1365                 PS_META_DUPLICATE_OK, "==", row->exp_id)
    1366         ) {
    1367             psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1368             psFree(detInputExp);
    1369             psFree(where_exp_ids);
    1370             return NULL;
    1371         }
    1372     }
    1373     psFree(detInputExp);
    1374 
    1375     // select rawImfiles with matching exp_ids
    1376     psArray *rawImfiles =
    1377         rawImfileSelectRowObjects(config->dbh, where_exp_ids, 0);
    1378     psFree(where_exp_ids);
    1379     if (!rawImfiles) {
    1380         psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
    1381         return NULL;
    1382     }
    1383 
    1384     return rawImfiles;
    1385 }
    1386 
    13871315static bool addprocessedimfileMode(pxConfig *config)
    13881316{
    13891317    PS_ASSERT_PTR_NON_NULL(config, false);
    13901318
    1391     // det_id, exp_id, class_id, uri, recipe, -bg, -bg_stdev
    1392     // are required
     1319    // det_id, exp_id, class_id, uri, recipe, -bg, -bg_stdev are required
    13931320    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    13941321    PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false);
     
    14161343    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    14171344
    1418 
    14191345    // find the matching rawImfile by exp_id/class_id
    14201346    psMetadata *where = psMetadataAlloc();
    1421     if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id", 0, "==", exp_id)) {
    1422         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1423         psFree(where);
    1424         return false;
    1425     }
    1426     if (!psMetadataAddStr(where, PS_LIST_TAIL, "class_id", 0, "==", class_id)) {
    1427         psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    1428         psFree(where);
    1429         return false;
    1430     }
     1347    PXOPT_COPY_STR(config->args, where, "-exp_id",   "exp_id", "==");
     1348    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
    14311349
    14321350    psArray *rawImfiles = rawImfileSelectRowObjects(config->dbh, where, 0);
    14331351    psFree(where);
     1352
    14341353    if (!rawImfiles) {
    14351354        psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found ");
    14361355        return false;
    14371356    }
    1438 
    14391357
    14401358    // create a new detProcessedImfile object
     
    14731391}
    14741392
     1393static bool processedimfileMode(pxConfig *config)
     1394{
     1395    PS_ASSERT_PTR_NON_NULL(config, false);
     1396
     1397    char *value = NULL;
     1398
     1399    PXOPT_LOOKUP_BOOL(included, config->args, "-included", false);
     1400    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
     1401    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     1402    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     1403
     1404    psMetadata *where = psMetadataAlloc();
     1405    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
     1406    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     1407    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
     1408
     1409    psString query = pxDataGet("dettool_processedimfile.sql");
     1410    if (!query) {
     1411        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1412        psFree(where);
     1413        return false;
     1414    }
     1415
     1416    // add the two required restrictions: detRun.state and detRun.mode
     1417    // NOTE the above query requires one of the following two WHERE statements
     1418    {
     1419        bool status;
     1420        if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
     1421            psStringAppend(&query, " WHERE detRun.state = '%s'", value);
     1422        } else {
     1423            psStringAppend(&query, " WHERE detRun.state = 'run'");
     1424        }
     1425        if ((value = psMetadataLookupStr(&status, config->args, "-select_mode"))) {
     1426            psStringAppend(&query, " AND detRun.mode = '%s'", value);
     1427        } else {
     1428            psStringAppend(&query, " AND detRun.mode = 'master'");
     1429        }
     1430    }
     1431
     1432    if (psListLength(where->list)) {
     1433        psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedImfile");
     1434        psStringAppend(&query, " AND %s", whereClause);
     1435        psFree(whereClause);
     1436    }
     1437    psFree (where);
     1438
     1439    // restrict search to included imfiles
     1440    if (included) {
     1441        psStringAppend(&query, " AND detInputExp.include = 1");
     1442    }
     1443
     1444    if (faulted) {
     1445        // list only faulted rows
     1446        psStringAppend(&query, " %s", "AND detProcessedImfile.fault != 0");
     1447    } else {
     1448        // don't list faulted rows
     1449        psStringAppend(&query, " %s", "AND detProcessedImfile.fault = 0");
     1450    }
     1451
     1452    // treat limit == 0 as "no limit"
     1453    if (limit) {
     1454        psString limitString = psDBGenerateLimitSQL(limit);
     1455        psStringAppend(&query, " %s", limitString);
     1456        psFree(limitString);
     1457    }
     1458
     1459    if (!p_psDBRunQuery(config->dbh, query)) {
     1460        psError(PS_ERR_UNKNOWN, false, "database error");
     1461        psFree(query);
     1462        return false;
     1463    }
     1464    psFree(query);
     1465
     1466    psArray *output = p_psDBFetchResult(config->dbh);
     1467    if (!output) {
     1468        psError(PS_ERR_UNKNOWN, false, "database error");
     1469        return false;
     1470    }
     1471    if (!psArrayLength(output)) {
     1472        psTrace("dettool", PS_LOG_INFO, "no rows found");
     1473        psFree(output);
     1474        return true;
     1475    }
     1476
     1477    // negative simple so the default is true
     1478    if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
     1479        psError(PS_ERR_UNKNOWN, false, "failed to print array");
     1480        psFree(output);
     1481        return false;
     1482    }
     1483
     1484    psFree(output);
     1485
     1486    return true;
     1487}
     1488
     1489static bool revertprocessedimfileMode(pxConfig *config)
     1490{
     1491    PS_ASSERT_PTR_NON_NULL(config, false);
     1492
     1493    psMetadata *where = psMetadataAlloc();
     1494    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
     1495    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     1496    PXOPT_COPY_STR(config->args, where, "-class_id", "class_id", "==");
     1497    PXOPT_COPY_S16(config->args, where, "-code", "fault", "==");
     1498
     1499    psString query = pxDataGet("dettool_revertprocessedimfile.sql");
     1500    if (!query) {
     1501        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1502        return false;
     1503    }
     1504
     1505    if (psListLength(where->list)) {
     1506        psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedImfile");
     1507        psStringAppend(&query, " AND %s", whereClause);
     1508        psFree(whereClause);
     1509    }
     1510    psFree(where);
     1511
     1512    if (!p_psDBRunQuery(config->dbh, query)) {
     1513        psError(PS_ERR_UNKNOWN, false, "database error");
     1514        psFree(query);
     1515        return false;
     1516    }
     1517    psFree(query);
     1518
     1519    if (psDBAffectedRows(config->dbh) < 1) {
     1520        psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
     1521        return false;
     1522    }
     1523
     1524    return true;
     1525}
     1526
    14751527static bool toprocessedexpMode(pxConfig *config)
    14761528{
     
    14851537        return false;
    14861538    }
    1487 
    1488     // XXX does it make sense to accept any search params?
    1489 #if 0
    1490     if (config->where) {
    1491         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    1492         psStringAppend(&query, " AND %s", whereClause);
    1493         psFree(whereClause);
    1494     }
    1495 #endif
    14961539
    14971540    // treat limit == 0 as "no limit"
     
    15611604    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", true, false);
    15621605
    1563 
    1564     psString query = psStringCopy(
    1565         " SELECT DISTINCT"
    1566         "    detProcessedImfile.det_id,"
    1567         "    detRun.iteration,"
    1568         "    detRun.det_type,"
    1569         "    detProcessedImfile.exp_id"
    1570         " FROM detRun"
    1571         " JOIN detInputExp"
    1572         "    ON detRun.det_id = detInputExp.det_id"
    1573         "    AND detRun.iteration = detInputExp.iteration"
    1574         " JOIN rawExp"
    1575         "    ON detInputExp.exp_id = rawExp.exp_id"
    1576         " JOIN detProcessedImfile"
    1577         "    ON detInputExp.det_id = detProcessedImfile.det_id"
    1578         "    AND detInputExp.exp_id = detProcessedImfile.exp_id"
    1579         " LEFT JOIN detProcessedExp"
    1580         "    ON detInputExp.det_id = detProcessedExp.det_id"
    1581         "    AND detProcessedImfile.exp_id= detProcessedExp.exp_id"
    1582         " LEFT JOIN rawImfile"
    1583         "    ON detInputExp.exp_id = rawImfile.exp_id"
    1584         "    AND detProcessedImfile.class_id = rawImfile.class_id"
    1585         " WHERE"
    1586         "   detRun.state = 'run'"
    1587         "   AND detRun.mode = 'master'"
    1588         "   AND detProcessedExp.det_id IS NULL"
    1589         "   AND detProcessedExp.exp_id IS NULL"
    1590         "   AND detInputExp.include = 1"
    1591         "   AND detRun.det_id = %s"
    1592         "   AND detProcessedImfile.exp_id = '%s'"
    1593         " GROUP BY"
    1594         "    detProcessedImfile.class_id,"
    1595         "    rawImfile.class_id,"
    1596         "    detRun.det_id"
    1597         " HAVING"
    1598         "    COUNT(detProcessedImfile.class_id) = COUNT(rawImfile.class_id)"
    1599         );
     1606    psString query = pxDataGet("dettool_addprocessedexp.sql");
     1607    if (!query) {
     1608        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1609        return false;
     1610    }
    16001611
    16011612    if (!p_psDBRunQuery(config->dbh, query, det_id, exp_id)) {
     
    16541665    PS_ASSERT_PTR_NON_NULL(config, false);
    16551666
     1667    psMetadata *where = psMetadataAlloc();
     1668    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
     1669    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     1670
    16561671    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     1672    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    16571673    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1658     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    16591674
    16601675    psString query = psStringCopy("SELECT * FROM detProcessedExp");
    16611676
    1662     if (config->where) {
    1663         psString whereClause = psDBGenerateWhereSQL(config->where, NULL);
     1677    if (psListLength(where->list)) {
     1678        psString whereClause = psDBGenerateWhereSQL(where, NULL);
    16641679        psStringAppend(&query, " %s", whereClause);
    16651680        psFree(whereClause);
    16661681    }
     1682    psFree(where);
    16671683
    16681684    if (faulted) {
     
    17161732    PS_ASSERT_PTR_NON_NULL(config, false);
    17171733
     1734    psMetadata *where = psMetadataAlloc();
     1735    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
     1736    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     1737    PXOPT_COPY_S16(config->args, where, "-code",   "fault", "==");
     1738
    17181739    psString query = pxDataGet("dettool_revertprocessedexp.sql");
    17191740    if (!query) {
     
    17221743    }
    17231744
    1724     if (config->where) {
    1725         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detProcessedExp");
     1745    if (psListLength(where->list)) {
     1746        psString whereClause = psDBGenerateWhereConditionSQL(where, "detProcessedExp");
    17261747        psStringAppend(&query, " AND %s", whereClause);
    17271748        psFree(whereClause);
    17281749    }
     1750    psFree(where);
    17291751
    17301752    if (!p_psDBRunQuery(config->dbh, query)) {
     
    17561778        return false;
    17571779    }
    1758 
    1759     // XXX does it make sense to accept any search params?
    1760 #if 0
    1761     if (config->where) {
    1762         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    1763         psStringAppend(&query, " AND %s", whereClause);
    1764         psFree(whereClause);
    1765     }
    1766 #endif
    17671780
    17681781    // treat limit == 0 as "no limit"
     
    18031816}
    18041817
    1805 static bool processedimfileMode(pxConfig *config)
    1806 {
    1807     PS_ASSERT_PTR_NON_NULL(config, false);
    1808 
    1809     char *value = NULL;
    1810 
    1811     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    1812     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    1813     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    1814 
    1815     psString query = psStringCopy(
    1816         " SELECT DISTINCT"
    1817         "   detRun.det_type,"
    1818         "   rawExp.exp_time,"
    1819         "   detProcessedImfile.*"
    1820         " FROM detProcessedImfile"
    1821         " JOIN detRun"
    1822         "   USING(det_id)"
    1823         " JOIN detInputExp"
    1824         "   ON detRun.det_id = detInputExp.det_id"
    1825         "   AND detRun.iteration = detInputExp.iteration"
    1826         "   AND detProcessedImfile.exp_id = detInputExp.exp_id"
    1827         " JOIN rawExp"
    1828         "   ON rawExp.exp_id = detProcessedImfile.exp_id"
    1829         " WHERE"
    1830     );
    1831     // NOTE the above WHERE is completed with the following line:
    1832 
    1833     // add the two required restrictions: detRun.state and detRun.mode
    1834     {
    1835         bool status;
    1836         if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
    1837             psStringAppend(&query, " detRun.state = '%s'", value);
    1838         } else {
    1839             psStringAppend(&query, " detRun.state = 'run'");
     1818// this is NOT a command-line mode : it is used by 'addstackedMode'
     1819static psArray *searchRawImfiles(pxConfig *config)
     1820{
     1821    PS_ASSERT_PTR_NON_NULL(config, NULL);
     1822
     1823    psMetadata *where = psMetadataAlloc();
     1824    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     1825    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     1826
     1827    // select exp_ids from detInputExp matching det_id & iteration
     1828    // where query should be pre-generated
     1829    psArray *detInputExp = detInputExpSelectRowObjects(config->dbh, where, 0);
     1830    psFree (where);
     1831
     1832    if (!detInputExp) {
     1833        psError(PS_ERR_UNKNOWN, false, "no rawExp rows found");
     1834        return NULL;
     1835    }
     1836
     1837    // generate where query with just the exp_ids
     1838    psMetadata *where_exp_ids = psMetadataAlloc();
     1839    for (long i = 0; i < psArrayLength(detInputExp); i++) {
     1840        detInputExpRow *row = detInputExp->data[i];
     1841        if (!psMetadataAddS64(where_exp_ids, PS_LIST_TAIL, "exp_id",
     1842                PS_META_DUPLICATE_OK, "==", row->exp_id)
     1843        ) {
     1844            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     1845            psFree(detInputExp);
     1846            psFree(where_exp_ids);
     1847            return NULL;
    18401848        }
    1841         if ((value = psMetadataLookupStr(&status, config->args, "-select_mode"))) {
    1842             psStringAppend(&query, " AND detRun.mode = '%s'", value);
    1843         } else {
    1844             psStringAppend(&query, " AND detRun.mode = 'master'");
    1845         }
    1846     }
    1847 
    1848     if (config->where) {
    1849         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detProcessedImfile");
    1850         psStringAppend(&query, " AND %s", whereClause);
    1851         psFree(whereClause);
    1852     }
    1853 
    1854     {
    1855         bool status = false;
    1856         bool included = psMetadataLookupBool(&status, config->args, "-included");
    1857         if (!status) {
    1858             psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -simple");
    1859             return false;
    1860         }
    1861         // restrict search to included imfiles
    1862         if (included) {
    1863             psStringAppend(&query, " AND detInputExp.include = 1");
    1864         }
    1865     }
    1866 
    1867     if (faulted) {
    1868         // list only faulted rows
    1869         psStringAppend(&query, " %s", "AND detProcessedImfile.fault != 0");
    1870     } else {
    1871         // don't list faulted rows
    1872         psStringAppend(&query, " %s", "AND detProcessedImfile.fault = 0");
    1873     }
    1874 
    1875     // treat limit == 0 as "no limit"
    1876     if (limit) {
    1877         psString limitString = psDBGenerateLimitSQL(limit);
    1878         psStringAppend(&query, " %s", limitString);
    1879         psFree(limitString);
    1880     }
    1881 
    1882     if (!p_psDBRunQuery(config->dbh, query)) {
    1883         psError(PS_ERR_UNKNOWN, false, "database error");
    1884         psFree(query);
    1885         return false;
    1886     }
    1887     psFree(query);
    1888 
    1889     psArray *output = p_psDBFetchResult(config->dbh);
    1890     if (!output) {
    1891         psError(PS_ERR_UNKNOWN, false, "database error");
    1892         return false;
    1893     }
    1894     if (!psArrayLength(output)) {
    1895         psTrace("dettool", PS_LOG_INFO, "no rows found");
    1896         psFree(output);
    1897         return true;
    1898     }
    1899 
    1900     // negative simple so the default is true
    1901     if (!ippdbPrintMetadatas(stdout, output, "rawImfile", !simple)) {
    1902         psError(PS_ERR_UNKNOWN, false, "failed to print array");
    1903         psFree(output);
    1904         return false;
    1905     }
    1906 
    1907     psFree(output);
    1908 
    1909     return true;
    1910 }
    1911 
    1912 
    1913 static bool revertprocessedimfileMode(pxConfig *config)
    1914 {
    1915     PS_ASSERT_PTR_NON_NULL(config, false);
    1916 
    1917     psString query = pxDataGet("dettool_revertprocessedimfile.sql");
    1918     if (!query) {
    1919         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
    1920         return false;
    1921     }
    1922 
    1923     if (config->where) {
    1924         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detProcessedImfile");
    1925         psStringAppend(&query, " AND %s", whereClause);
    1926         psFree(whereClause);
    1927     }
    1928 
    1929     if (!p_psDBRunQuery(config->dbh, query)) {
    1930         psError(PS_ERR_UNKNOWN, false, "database error");
    1931         psFree(query);
    1932         return false;
    1933     }
    1934     psFree(query);
    1935 
    1936     if (psDBAffectedRows(config->dbh) < 1) {
    1937         psError(PS_ERR_UNKNOWN, false, "should have affected atleast 1 row");
    1938         return false;
    1939     }
    1940 
    1941     return true;
    1942 }
    1943 
     1849    }
     1850    psFree(detInputExp);
     1851
     1852    // select rawImfiles with matching exp_ids
     1853    psArray *rawImfiles =
     1854        rawImfileSelectRowObjects(config->dbh, where_exp_ids, 0);
     1855    psFree(where_exp_ids);
     1856    if (!rawImfiles) {
     1857        psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
     1858        return NULL;
     1859    }
     1860
     1861    return rawImfiles;
     1862}
    19441863
    19451864static bool addstackedMode(pxConfig *config)
     
    19471866    PS_ASSERT_PTR_NON_NULL(config, false);
    19481867
    1949     // det_id, class_id, uri, & recipe are required
     1868    // det_id, iteration, class_id, uri, & recipe are required
    19501869    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
     1870    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", true, false);
    19511871    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    19521872
     
    19671887    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    19681888
    1969     // default values
    1970     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    1971 
    19721889    // correlate the class_id against the input exposure(s)
    1973 
    1974     // we have to generate our own where clause as we want to search only by the
    1975     // det_id
    1976     psMetadata *where = psMetadataAlloc();
    1977     if (!psMetadataAddS64(where, PS_LIST_TAIL, "det_id", 0, "==",
    1978             (psS64)atoll(det_id))) {
    1979         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1980         psFree(where);
    1981         return false;
    1982     }
    1983 
    1984     psArray *rawImfiles = searchRawImfiles(config, where);
    1985     psFree(where);
     1890    // searchRawImfiles defines a where clause to search by det_id and iteration
     1891    psArray *rawImfiles = searchRawImfiles(config);
    19861892
    19871893    if (!rawImfiles) {
     
    20451951    PS_ASSERT_PTR_NON_NULL(config, false);
    20461952
     1953    psMetadata *where = psMetadataAlloc();
     1954    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     1955    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     1956    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     1957    PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
     1958
    20471959    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     1960    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    20481961    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2049     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    2050 
    2051     // select detStackedImfile.*
    2052     // by:
    2053     // where det_id, iteration, class_id is not in detNormalizedImfile
    2054 
    2055     psString query = psStringCopy(
    2056         "SELECT"
    2057         "   detStackedImfile.*"
    2058         " FROM detStackedImfile"
    2059         " JOIN detRun"
    2060         "   USING(det_id, iteration)"
    2061         " WHERE"
    2062         "   detRun.state = 'run'"
    2063         "   AND detRun.mode = 'master'"
    2064     );
    2065 
    2066     if (config->where) {
    2067         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detStackedImfile");
     1962
     1963    psString query = pxDataGet("dettool_stacked.sql");
     1964    if (!query) {
     1965        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     1966        psFree(where);
     1967        return false;
     1968    }
     1969
     1970    if (psListLength(where->list)) {
     1971        psString whereClause = psDBGenerateWhereConditionSQL(where, "detStackedImfile");
    20681972        psStringAppend(&query, " AND %s", whereClause);
    20691973        psFree(whereClause);
    20701974    }
     1975    psFree(where);
    20711976
    20721977    if (faulted) {
     
    21202025    PS_ASSERT_PTR_NON_NULL(config, false);
    21212026
     2027    psMetadata *where = psMetadataAlloc();
     2028    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2029    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2030    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     2031    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
     2032
    21222033    psString query = pxDataGet("dettool_revertstacked.sql");
    21232034    if (!query) {
     
    21262037    }
    21272038
    2128     if (config->where) {
    2129         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detStackedImfile");
     2039    if (psListLength(where->list)) {
     2040        psString whereClause = psDBGenerateWhereConditionSQL(where, "detStackedImfile");
    21302041        psStringAppend(&query, " AND %s", whereClause);
    21312042        psFree(whereClause);
    21322043    }
     2044    psFree(where);
    21332045
    21342046    if (!p_psDBRunQuery(config->dbh, query)) {
     
    21592071        return false;
    21602072    }
    2161 
    2162     // XXX does it make sense to accept any search params?
    2163 #if 0
    2164     if (config->where) {
    2165         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    2166         psStringAppend(&query, " AND %s", whereClause);
    2167         psFree(whereClause);
    2168     }
    2169 #endif
    21702073
    21712074    // treat limit == 0 as "no limit"
     
    22402143    PS_ASSERT_PTR_NON_NULL(config, false);
    22412144
     2145    psMetadata *where = psMetadataAlloc();
     2146    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2147    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2148    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     2149
    22422150    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     2151    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    22432152    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    2244     PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    22452153
    22462154    psString query = pxDataGet("dettool_normalizedstat.sql");
     
    22582166    }
    22592167
    2260     if (config->where) {
    2261         psString whereClause = psDBGenerateWhereConditionSQL(config->where, NULL);
     2168    if (psListLength(where->list)) {
     2169        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    22622170        psStringAppend(&query, " AND %s", whereClause);
    22632171        psFree(whereClause);
    22642172    }
     2173    psFree(where);
    22652174
    22662175    // treat limit == 0 as "no limit"
     
    23052214    PS_ASSERT_PTR_NON_NULL(config, false);
    23062215
     2216    psMetadata *where = psMetadataAlloc();
     2217    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2218    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2219    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     2220    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
     2221
    23072222    psString query = pxDataGet("dettool_revertnormalizedstat.sql");
    23082223    if (!query) {
     
    23112226    }
    23122227
    2313     if (config->where) {
    2314         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detNormalizedStatImfile");
     2228    if (psListLength(where->list)) {
     2229        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedStatImfile");
    23152230        psStringAppend(&query, " AND %s", whereClause);
    23162231        psFree(whereClause);
    23172232    }
     2233    psFree(where);
    23182234
    23192235    if (!p_psDBRunQuery(config->dbh, query)) {
     
    23392255    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    23402256
    2341     // select detNormalizedStatImfile.*
    2342     // by:
    2343     // where det_id, iteration, class_id is not in detNormalizedImfile
    2344 
    2345     psString query = psStringCopy(
    2346         "SELECT DISTINCT"
    2347         "   detRun.det_type,"
    2348         "   detRun.workdir,"
    2349         "   rawExp.camera,"
    2350         "   detStackedImfile.uri,"
    2351         "   detNormalizedStatImfile.*"
    2352         " FROM detRun"
    2353         " JOIN detStackedImfile"
    2354         "   USING(det_id, iteration)"
    2355         " JOIN detInputExp"
    2356         "   USING(det_id, iteration)"
    2357         " JOIN rawExp"
    2358         "   ON detInputExp.exp_id = rawExp.exp_id"
    2359         " JOIN detNormalizedStatImfile"
    2360         "   ON detStackedImfile.det_id = detNormalizedStatImfile.det_id"
    2361         "   AND detStackedImfile.iteration = detNormalizedStatImfile.iteration"
    2362         "   AND detStackedImfile.class_id = detNormalizedStatImfile.class_id"
    2363         " LEFT JOIN detNormalizedImfile"
    2364         "   ON detNormalizedStatImfile.det_id = detNormalizedImfile.det_id"
    2365         "   AND detNormalizedStatImfile.iteration = detNormalizedImfile.iteration"
    2366         "   AND detNormalizedStatImfile.class_id = detNormalizedImfile.class_id"
    2367         " WHERE"
    2368         "   detNormalizedImfile.det_id IS NULL"
    2369         "   AND detNormalizedImfile.iteration IS NULL"
    2370         "   AND detNormalizedImfile.class_id IS NULL"
    2371         "   AND detNormalizedStatImfile.fault = 0"
    2372         "   AND detRun.state = 'run'"
    2373         );
    2374 
    2375     // XXX does it make sense to accept any search params?
    2376 #if 0
    2377     if (config->where) {
    2378         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    2379         psStringAppend(&query, " AND %s", whereClause);
    2380         psFree(whereClause);
    2381     }
    2382 #endif
     2257    psString query = pxDataGet("dettool_tonormalize.sql");
     2258    if (!query) {
     2259        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     2260        return false;
     2261    }
    23832262
    23842263    // treat limit == 0 as "no limit"
     
    24192298}
    24202299
    2421 #if 0
    2422 // XXX this function was left in commented as this method may be useful in the
    2423 // future
    2424 static psArray *validDetInputClassIds(pxConfig *config, const char *det_id)
    2425 {
    2426     PS_ASSERT_PTR_NON_NULL(config, NULL);
    2427     // det_id is input as a string because the fact that it is an integer
    2428     // is just a database impliementation detail.
    2429     PS_ASSERT_PTR_NON_NULL(det_id, NULL);
    2430 
    2431     psArray *rawImfiles = searchInputImfiles(config, det_id);
    2432     if (!rawImfiles) {
    2433         return NULL;
    2434     }
    2435 
    2436     psArray *valid_class_ids = NULL;
    2437     {
    2438         // All this jumping through hoops is so that we end up with unique
    2439         // values. PP thinks that making multiple passes through this array and
    2440         // deleting matched elements would end up being more expensive then a
    2441         // double sort and stagger scheme. JH thinks it would be cheaper to
    2442         // just do a unqiue sort and delete.  So this is really just a cheap
    2443         // hack to avoid implimenting a unique sort function but at least it's
    2444         // stable.
    2445         psHash *hash = psHashAlloc(psArrayLength(rawImfiles));
    2446         for (long i = 0; i < psArrayLength(rawImfiles); i++) {
    2447             psHashAdd(hash,
    2448                 ((rawImfileRow *)rawImfiles->data[i])->class_id,
    2449                 ((rawImfileRow *)rawImfiles->data[i])->class_id
    2450             );
    2451         }
    2452         valid_class_ids = psHashToArray(hash);
    2453         psFree(hash);
    2454     }
    2455     psFree(rawImfiles);
    2456 
    2457     return valid_class_ids;
    2458 }
    2459 
    2460 static psArray *searchInputImfiles(pxConfig *config, const char *det_id)
    2461 {
    2462     PS_ASSERT_PTR_NON_NULL(config, NULL);
    2463     // det_id is input as a string because the fact that it is an integer
    2464     // is just a database impliementation detail.
    2465     PS_ASSERT_PTR_NON_NULL(det_id, NULL);
    2466 
    2467     psArray *inputExps = NULL;
    2468     {
    2469         psMetadata *where = psMetadataAlloc();
    2470         if (!psMetadataAddS32(where, PS_LIST_TAIL, "det_id", 0, "==",
    2471                 (psS32)atoi(det_id))) {
    2472             psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    2473             psFree(where);
    2474             return NULL;
    2475         }
    2476         inputExps = detInputExpSelectRowObjects(config->dbh, where, 0);
    2477         psFree(where);
    2478     }
    2479     if (!inputExps) {
    2480         psError(PS_ERR_UNKNOWN, false, "no detInputExp rows found");
    2481         return NULL;
    2482     }
    2483 
    2484     // find rawImfiles associated with detInputExps
    2485     psArray *rawImfiles = NULL;
    2486     {
    2487         psMetadata *where = psMetadataAlloc();
    2488         for (long i = 0; i < psArrayLength(inputExps); i++) {
    2489             if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id",
    2490                     PS_META_DUPLICATE_OK, "==",
    2491                     ((detInputExpRow *)inputExps->data[i])->exp_id)) {
    2492                 psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    2493                 psFree(inputExps);
    2494                 psFree(where);
    2495                 return NULL;
    2496             }
    2497         }
    2498         psFree(inputExps);
    2499         rawImfiles = rawImfileSelectRowObjects(config->dbh, where, 0);
    2500         // XXX this really should be sorted for uniqueness
    2501         psFree(where);
    2502     }
    2503     if (!rawImfiles) {
    2504         psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
    2505         return NULL;
    2506     }
    2507 
    2508     return rawImfiles;
    2509 }
    2510 #endif
    2511 
    25122300static bool addnormalizedimfileMode(pxConfig *config)
    25132301{
     
    25162304    // required
    25172305    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
     2306    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    25182307    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    25192308
     
    25332322    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    25342323    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    2535 
    2536     // default values
    2537     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    25382324
    25392325    if (!detNormalizedImfileInsert(config->dbh,
     
    25602346}
    25612347
    2562 
    25632348static bool normalizedimfileMode(pxConfig *config)
    25642349{
    25652350    PS_ASSERT_PTR_NON_NULL(config, false);
     2351
     2352    psMetadata *where = psMetadataAlloc();
     2353    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2354    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2355    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     2356    PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
    25662357
    25672358    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     
    25692360    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    25702361
    2571     psString query = psStringCopy(
    2572         "SELECT"
    2573         " detNormalizedImfile.*"
    2574         " FROM detNormalizedImfile"
    2575         " JOIN detRun"
    2576         "   USING(det_id, iteration)"
    2577         " WHERE"
    2578         "   detRun.state = 'run'"
    2579         "   AND detRun.mode = 'master'"
    2580     );
    2581 
    2582     if (config->where) {
    2583         bool status;
    2584         int iteration = psMetadataLookupS32 (&status, config->where, "iteration");
    2585         if (status) {
    2586             psMetadataRemoveKey (config->where, "iteration");
    2587             psMetadataAddS32 (config->where, PS_LIST_TAIL, "iteration", 0, "==", iteration);
    2588         }
    2589         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detNormalizedImfile");
     2362    psString query = pxDataGet("dettool_normalizedimfile.sql");
     2363    if (!query) {
     2364        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     2365        return false;
     2366    }
     2367
     2368    if (psListLength(where->list)) {
     2369        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedImfile");
    25902370        psStringAppend(&query, " AND %s", whereClause);
    25912371        psFree(whereClause);
    25922372    }
     2373    psFree(where);
    25932374
    25942375    if (faulted) {
     
    26422423    PS_ASSERT_PTR_NON_NULL(config, false);
    26432424
     2425    psMetadata *where = psMetadataAlloc();
     2426    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2427    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2428    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     2429    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
     2430
    26442431    psString query = pxDataGet("dettool_revertnormalizedimfile.sql");
    26452432    if (!query) {
     
    26482435    }
    26492436
    2650     if (config->where) {
    2651         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detNormalizedImfile");
     2437    if (psListLength(where->list)) {
     2438        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedImfile");
    26522439        psStringAppend(&query, " AND %s", whereClause);
    26532440        psFree(whereClause);
    26542441    }
     2442    psFree(where);
    26552443
    26562444    if (!p_psDBRunQuery(config->dbh, query)) {
     
    26682456    return true;
    26692457}
    2670 
    26712458
    26722459static bool tonormalizedexpMode(pxConfig *config)
     
    26822469        return false;
    26832470    }
    2684 
    2685     // XXX does it make sense to accept any search params?
    2686 #if 0
    2687     if (config->where) {
    2688         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    2689         psStringAppend(&query, " AND %s", whereClause);
    2690         psFree(whereClause);
    2691     }
    2692 #endif
    26932471
    26942472    // treat limit == 0 as "no limit"
     
    27322510{
    27332511    PS_ASSERT_PTR_NON_NULL(config, false);
    2734 
    2735     // required
    2736     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    2737 
     2512   
     2513    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     2514    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    27382515    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    2739 
    2740     // Required if code == 0
    2741     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
    2742 
    2743     // optional
     2516    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
    27442517    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    27452518    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
     
    27522525    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    27532526
    2754     // default values
    2755     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    2756 
    27572527    psString query = pxDataGet("dettool_tonormalizedexp.sql");
    27582528    if (!query) {
     
    27612531    }
    27622532
    2763     psStringAppend(&query,
    2764             " WHERE det_id = %s"
    2765             " AND iteration = %d", det_id, iteration);
    2766 
     2533    // XXX in some other places, we put the arguments in the .sql and supply them to RunQuery
     2534    psStringAppend(&query, " WHERE det_id = %s AND iteration = %d", det_id, iteration);
    27672535
    27682536    if (!p_psDBRunQuery(config->dbh, query)) {
     
    28132581    PS_ASSERT_PTR_NON_NULL(config, false);
    28142582
     2583    psMetadata *where = psMetadataAlloc();
     2584    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2585    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2586    PXOPT_COPY_STR(config->args, where, "-recip",  "recipe", "==");
     2587
    28152588    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    28162589    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    28172590    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    28182591
    2819     psString query = psStringCopy(
    2820         "SELECT"
    2821         "   detNormalizedExp.*"
    2822         " FROM detNormalizedExp"
    2823         " JOIN detRun"
    2824         "   USING(det_id, iteration)"
    2825         " WHERE"
    2826         "   detRun.state = 'run'"
    2827         "   AND detRun.mode = 'master'"
    2828     );
    2829 
    2830     if (config->where) {
    2831         psString whereClause = psDBGenerateWhereSQL(config->where, NULL);
     2592    psString query = pxDataGet("dettool_normalizedexp.sql");
     2593    if (!query) {
     2594        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     2595        return false;
     2596    }
     2597
     2598    if (psListLength(where->list)) {
     2599        psString whereClause = psDBGenerateWhereSQL(where, NULL);
    28322600        psStringAppend(&query, " %s", whereClause);
    28332601        psFree(whereClause);
    28342602    }
     2603    psFree(where);
    28352604
    28362605    if (faulted) {
     
    28852654    PS_ASSERT_PTR_NON_NULL(config, false);
    28862655
     2656    psMetadata *where = psMetadataAlloc();
     2657    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2658    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2659    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
     2660
    28872661    psString query = pxDataGet("dettool_revertnormalizedexp.sql");
    28882662    if (!query) {
     
    28912665    }
    28922666
    2893     if (config->where) {
    2894         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detNormalizedExp");
     2667    if (psListLength(where->list)) {
     2668        psString whereClause = psDBGenerateWhereConditionSQL(where, "detNormalizedExp");
    28952669        psStringAppend(&query, " AND %s", whereClause);
    28962670        psFree(whereClause);
    28972671    }
     2672    psFree(where);
    28982673
    28992674    if (!p_psDBRunQuery(config->dbh, query)) {
     
    29252700        return false;
    29262701    }
    2927 
    2928     // XXX does it make sense to accept any search params?
    2929 #if 0
    2930     if (config->where) {
    2931         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    2932         psStringAppend(&query, " AND %s", whereClause);
    2933         psFree(whereClause);
    2934     }
    2935 #endif
    29362702
    29372703    // treat limit == 0 as "no limit"
     
    29772743    PS_ASSERT_PTR_NON_NULL(config, false);
    29782744
    2979     // required
    2980     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    2981     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    2982     PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false);
    2983 
     2745   
     2746    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     2747    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
     2748    PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false); // required
     2749    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false); // required
    29842750    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    2985 
    2986     // Required if code == 0
    2987     PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false);
    2988     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
    2989 
    2990     // optional
     2751    PXOPT_LOOKUP_STR(uri, config->args, "-uri", (code == 0), false); // Required if code == 0
     2752    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
    29912753    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    29922754    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
     
    29952757    PXOPT_LOOKUP_F64(bg_kurtosis, config->args, "-bg_kurtosis", false, false);
    29962758    PXOPT_LOOKUP_F64(bin_stdev, config->args, "-bin_stdev", false, false);
    2997 
    29982759    PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
    29992760    PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
     
    30022763    PXOPT_LOOKUP_F64(fringe_resid_1, config->args, "-fringe_resid_1", false, false);
    30032764    PXOPT_LOOKUP_F64(fringe_resid_2, config->args, "-fringe_resid_2", false, false);
    3004 
    30052765    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    30062766    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
     
    30092769    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    30102770    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    3011 
    3012     // default values
    3013     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    30142771
    30152772    if (!detResidImfileInsert(config->dbh,
     
    30522809    PS_ASSERT_PTR_NON_NULL(config, false);
    30532810
     2811    psMetadata *where = psMetadataAlloc();
     2812    PXOPT_COPY_STR(config->args, where, "-det_id",     "det_id", "==");
     2813    PXOPT_COPY_S32(config->args, where, "-iteration",  "iteration", "==");
     2814    PXOPT_COPY_STR(config->args, where, "-exp_id",     "exp_id", "==");
     2815    PXOPT_COPY_STR(config->args, where, "-class_id",   "class_id", "==");
     2816    PXOPT_COPY_STR(config->args, where, "-recip",      "recipe", "==");
     2817
    30542818    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    30552819    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    30562820    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    30572821
    3058     // select detResidImfile.*
    3059     // by:
    3060     // where det_id, iteration, exp_id is not in detResidExp;
    3061 
    3062     psString query = psStringCopy(
    3063         "SELECT"
    3064         "   detRun.det_type,"
    3065         "   detRun.mode,"
    3066         "   detResidImfile.*,"
    3067         "   rawExp.exp_time"
    3068         " FROM detResidImfile"
    3069         " JOIN detRun"
    3070         "   USING(det_id, iteration)"
    3071         " JOIN rawExp"
    3072         "   USING(exp_id)"
    3073         " WHERE"
    3074     );
    3075     // NOTE the above WHERE is completed with the following line:
    3076 
     2822    psString query = pxDataGet("dettool_residimfile.sql");
     2823    if (!query) {
     2824        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     2825        return false;
     2826    }
     2827
     2828    // NOTE: the query ends in a WHERE, add the required restriction on detRun.state
    30772829    char *value = NULL;
    3078 
    3079     // add the two required restrictions: detRun.state and detRun.mode
    30802830    bool status;
    30812831    if ((value = psMetadataLookupStr(&status, config->args, "-select_state"))) {
     
    30852835    }
    30862836
    3087     if (config->where) {
    3088         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detResidImfile");
     2837    if (psListLength(where->list)) {
     2838        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidImfile");
    30892839        psStringAppend(&query, " AND %s", whereClause);
    30902840        psFree(whereClause);
    30912841    }
     2842    psFree(where);
    30922843
    30932844    if (faulted) {
     
    31412892    PS_ASSERT_PTR_NON_NULL(config, false);
    31422893
     2894    psMetadata *where = psMetadataAlloc();
     2895    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     2896    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     2897    PXOPT_COPY_STR(config->args, where, "-exp_id",  "exp_id", "==");
     2898    PXOPT_COPY_STR(config->args, where, "-class_id",  "class_id", "==");
     2899    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
     2900
    31432901    psString query = pxDataGet("dettool_revertresidimfile.sql");
    31442902    if (!query) {
     
    31472905    }
    31482906
    3149     if (config->where) {
    3150         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detResidImfile");
     2907    if (psListLength(where->list)) {
     2908        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidImfile");
    31512909        psStringAppend(&query, " AND %s", whereClause);
    31522910        psFree(whereClause);
    31532911    }
     2912    psFree(where);
    31542913
    31552914    if (!p_psDBRunQuery(config->dbh, query)) {
     
    31692928
    31702929
     2930/*
     2931  The SQL returns a list of exposures for which all component class ids have had residuals
     2932  created.  This list includes the detrend id, iteration, exposure id, detrend type, and
     2933  whether the exposure was included in the stack for this iteration.
     2934*/
     2935
    31712936static bool toresidexpMode(pxConfig *config)
    31722937{
    31732938    PS_ASSERT_PTR_NON_NULL(config, false);
    3174 
    3175     /*
    3176 which returns a list of exposures for which all component class ids
    3177 have had residuals created.  This list includes the detrend id,
    3178 iteration, exposure id, detrend type, and whether the exposure was
    3179 included in the stack for this iteration.
    3180     */
    31812939
    31822940    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     
    31882946        return false;
    31892947    }
    3190 
    3191     // XXX does it make sense to accept any search params?
    3192 #if 0
    3193     if (config->where) {
    3194         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    3195         psStringAppend(&query, " AND %s", whereClause);
    3196         psFree(whereClause);
    3197     }
    3198 #endif
    31992948
    32002949    // treat limit == 0 as "no limit"
     
    32352984}
    32362985
     2986/*
     2987  The SQL returns a list of exposures for which all component class ids have had residuals
     2988  created.  This list includes the detrend id, iteration, exposure id, detrend type, and
     2989  whether the exposure was included in the stack for this iteration.
     2990*/
     2991
    32372992static bool addresidexpMode(pxConfig *config)
    32382993{
    32392994    PS_ASSERT_PTR_NON_NULL(config, false);
    32402995
    3241     // required
    3242     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    3243     PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false);
    3244 
     2996    // limit search by det_id, iteration, exp_id
     2997    psMetadata *where = psMetadataAlloc();
     2998    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
     2999    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     3000    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     3001
     3002    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     3003    PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
     3004    PXOPT_LOOKUP_STR(exp_id, config->args, "-exp_id", true, false); // required
    32453005    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    3246 
    3247     // Required if code == 0
    3248     PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false);
    3249 
    3250     // optional
     3006    PXOPT_LOOKUP_STR(recipe, config->args, "-recip", (code == 0), false); // Required if code == 0
    32513007    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    32523008    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
     
    32553011    PXOPT_LOOKUP_F64(bg_kurtosis, config->args, "-bg_kurtosis", false, false);
    32563012    PXOPT_LOOKUP_F64(bin_stdev, config->args, "-bin_stdev", false, false);
    3257 
    32583013    PXOPT_LOOKUP_F64(fringe_0, config->args, "-fringe_0", false, false);
    32593014    PXOPT_LOOKUP_F64(fringe_1, config->args, "-fringe_1", false, false);
     
    32623017    PXOPT_LOOKUP_F64(fringe_resid_1, config->args, "-fringe_resid_1", false, false);
    32633018    PXOPT_LOOKUP_F64(fringe_resid_2, config->args, "-fringe_resid_2", false, false);
    3264 
    32653019    PXOPT_LOOKUP_F64(user_1, config->args, "-user_1", false, false);
    32663020    PXOPT_LOOKUP_F64(user_2, config->args, "-user_2", false, false);
     
    32693023    PXOPT_LOOKUP_F64(user_5, config->args, "-user_5", false, false);
    32703024    PXOPT_LOOKUP_STR(path_base, config->args, "-path_base", false, false);
    3271 
    3272     // default values
    3273     PXOPT_LOOKUP_S32(iteration, config->args, "-iteration", false, false);
    32743025    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
    3275 
    3276     /*
    3277 which returns a list of exposures for which all component class ids
    3278 have had residuals created.  This list includes the detrend id,
    3279 iteration, exposure id, detrend type, and whether the exposure was
    3280 included in the stack for this iteration.
    3281     */
    32823026
    32833027    psString query = pxDataGet("dettool_toresidexp.sql");
     
    32873031    }
    32883032
    3289     {
    3290         // build a query to search by det_id, iteration, exp_id
    3291         psMetadata *where = psMetadataAlloc();
    3292 
    3293         PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    3294         PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3295         PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    3296 
    3297 
    3298         // there's not
    3299         psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    3300         psFree(where);
    3301         if (whereClause) {
    3302             psStringAppend(&query, " WHERE %s", whereClause);
    3303             psFree(whereClause);
    3304         }
    3305     }
     3033    if (psListLength(where->list)) {
     3034        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
     3035        psStringAppend(&query, " WHERE %s", whereClause);
     3036        psFree(whereClause);
     3037    }
     3038    psFree(where);
    33063039
    33073040    if (!p_psDBRunQuery(config->dbh, query)) {
     
    33623095    PS_ASSERT_PTR_NON_NULL(config, false);
    33633096
    3364     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    3365     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     3097    psMetadata *where = psMetadataAlloc();
     3098    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     3099    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     3100    PXOPT_COPY_STR(config->args, where, "-exp_id",    "exp_id", "==");
     3101    PXOPT_COPY_STR(config->args, where, "-recip",     "recipe", "==");
     3102
     3103    PXOPT_LOOKUP_U64(limit,    config->args, "-limit", false, false);
     3104    PXOPT_LOOKUP_BOOL(simple,  config->args, "-simple", false);
    33663105    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    3367 
    3368     psString query = psStringCopy(
    3369         "SELECT"
    3370         "   detRun.mode,"
    3371         "   detResidExp.*,"
    3372         "   detInputExp.include"
    3373         " FROM detRun"
    3374         " JOIN detInputExp"
    3375         "   USING(det_id, iteration)"
    3376         " JOIN detResidExp"
    3377         "   USING(det_id, iteration, exp_id)"
    3378         " WHERE"
    3379         "   detRun.state = 'run'"
    3380     );
    3381 
    3382     if (config->where) {
    3383         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detResidExp");
     3106    PXOPT_LOOKUP_BOOL(reject,  config->args, "-reject", false);
     3107
     3108    psString query = pxDataGet("dettool_residexp.sql");
     3109    if (!query) {
     3110        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     3111        return false;
     3112    }
     3113
     3114    if (psListLength(where->list)) {
     3115        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidExp");
    33843116        psStringAppend(&query, " AND %s", whereClause);
    33853117        psFree(whereClause);
    33863118    }
     3119    psFree(where);
    33873120
    33883121    if (faulted) {
     
    33943127    }
    33953128
     3129    // list only accepted rows
     3130    // XXX the usage of this flag is unclear : -reject means "accepted"?
     3131    if (reject) {
     3132        psStringAppend(&query, " %s", "AND detResidExp.accept != 0");
     3133    }
     3134
    33963135    // treat limit == 0 as "no limit"
    33973136    if (limit) {
     
    34363175    PS_ASSERT_PTR_NON_NULL(config, false);
    34373176
     3177    psMetadata *where = psMetadataAlloc();
     3178    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     3179    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     3180    PXOPT_COPY_STR(config->args, where, "-exp_id",    "exp_id", "==");
     3181    PXOPT_COPY_S16(config->args, where, "-code",      "fault", "==");
     3182
    34383183    psString query = pxDataGet("dettool_revertresidexp.sql");
    34393184    if (!query) {
     
    34423187    }
    34433188
    3444     if (config->where) {
    3445         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detResidExp");
     3189    if (psListLength(where->list)) {
     3190        psString whereClause = psDBGenerateWhereConditionSQL(where, "detResidExp");
    34463191        psStringAppend(&query, " AND %s", whereClause);
    34473192        psFree(whereClause);
    34483193    }
     3194    psFree(where);
    34493195
    34503196    if (!p_psDBRunQuery(config->dbh, query)) {
     
    34643210
    34653211
     3212static bool updateresidexpMode(pxConfig *config)
     3213{
     3214    PS_ASSERT_PTR_NON_NULL(config, false);
     3215
     3216    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
     3217
     3218    // build a query to search by det_id, iteration, exp_id
     3219    psMetadata *where = psMetadataAlloc();
     3220    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
     3221    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     3222    PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
     3223
     3224    // find the values we're going to set
     3225    // copy everything but det_id, iteration, & exp_id from the args and
     3226    // remove the '-' prefix
     3227    psMetadata *set = psMetadataAlloc();
     3228    PXOPT_COPY_STR(config->args, set, "-recip", "recipe", "==");
     3229    PXOPT_COPY_F64(config->args, set, "-bg", "bg", "==");
     3230    PXOPT_COPY_F64(config->args, set, "-bg_stdev", "bg_stdev", "==");
     3231    PXOPT_COPY_F64(config->args, set, "-bg_mean_stdev", "bg_mean_stdev", "==");
     3232    PXOPT_COPY_STR(config->args, set, "-path_base", "path_base", "==");
     3233
     3234    // this can't be PXOPT_ macro-ized as reject is !'d
     3235    if (!psMetadataAddBool(set, PS_LIST_TAIL, "accept", 0, "==", !reject)) {
     3236        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
     3237        psFree(set);
     3238        psFree(where);
     3239        return false;
     3240    }
     3241
     3242    long changed = psDBUpdateRows(config->dbh, "detResidExp", where, set);
     3243    psFree(set);
     3244    psFree(where);
     3245
     3246    if (changed < 0) {
     3247        psError(PS_ERR_UNKNOWN, false, "no rows were updated");
     3248        return false;
     3249    }
     3250
     3251    return true;
     3252}
     3253
     3254/* The SQL returns a list of detrend runs (with detrend id, iteration and detrend type) which
     3255 * have completed all residexps.
     3256 */
     3257
    34663258static bool todetrunsummaryMode(pxConfig *config)
    34673259{
     
    34703262    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
    34713263    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    3472 
    3473     /* which returns a list of detrend runs (with detrend id, iteration and
    3474      * detrend type) which have completed all residexps.
    3475      */
    34763264
    34773265    psString query = pxDataGet("dettool_todetrunsummary.sql");
     
    34803268        return false;
    34813269    }
    3482 
    3483     // XXX does it make sense to accept any search params?
    3484 #if 0
    3485     if (config->where) {
    3486         psString whereClause = psDBGenerateWhereConditionSQL(config->where);
    3487         psStringAppend(&query, " AND %s", whereClause);
    3488         psFree(whereClause);
    3489     }
    3490 #endif
    34913270
    34923271    // treat limit == 0 as "no limit"
     
    35273306}
    35283307
    3529 static bool updateresidexpMode(pxConfig *config)
    3530 {
    3531     PS_ASSERT_PTR_NON_NULL(config, false);
    3532 
    3533     PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
    3534 
     3308// this function is used to generate the detrunSummary entries used below
     3309// XXX why is this a separate function?  roll it back into adddetrunsummary?
     3310static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row)
     3311{
     3312    PS_ASSERT_PTR_NON_NULL(config, false);
     3313
     3314    bool status = false;
     3315    // from row
     3316    psS64 det_id = psMetadataLookupS64(&status, row, "det_id");
     3317    if (!status) {
     3318        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
     3319        return false;
     3320    }
     3321    psS32 iteration = psMetadataLookupS32(&status, row, "iteration");
     3322    if (!status) {
     3323        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for iteration");
     3324        return false;
     3325    }
     3326
     3327    // optional
     3328    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
     3329    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
     3330    PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
     3331
     3332    // default values
     3333    PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
     3334    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
     3335
     3336    return detRunSummaryRowAlloc(
     3337            det_id,
     3338            iteration,
     3339            bg,
     3340            bg_stdev,
     3341            bg_mean_stdev,
     3342            accept,
     3343            code
     3344        );
     3345}
     3346
     3347static bool adddetrunsummaryMode(pxConfig *config)
     3348{
     3349    PS_ASSERT_PTR_NON_NULL(config, false);
     3350   
    35353351    // build a query to search by det_id, iteration, exp_id
    35363352    psMetadata *where = psMetadataAlloc();
    35373353    PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    35383354    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3539     PXOPT_COPY_STR(config->args, where, "-exp_id", "exp_id", "==");
    3540 
    3541     // find the values we're going to set
    3542     // copy everything but det_id, iteration, & exp_id from the args and
    3543     // remove the '-' prefix
    3544     psMetadata *set = psMetadataAlloc();
    3545     // XXX if PXOPT_COPY_* errors here the where md will leak
    3546     PXOPT_COPY_STR(config->args, set, "-recip", "recipe", "==");
    3547     PXOPT_COPY_F64(config->args, set, "-bg", "bg", "==");
    3548     PXOPT_COPY_F64(config->args, set, "-bg_stdev", "bg_stdev", "==");
    3549     PXOPT_COPY_F64(config->args, set, "-bg_mean_stdev", "bg_mean_stdev", "==");
    3550     PXOPT_COPY_STR(config->args, set, "-path_base", "path_base", "==");
    3551 
    3552     // this can't be PXOPT_ macro-ized as reject is !'d
    3553     if (!psMetadataAddBool(set, PS_LIST_TAIL, "accept", 0, "==", !reject)) {
    3554         psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
    3555         psFree(set);
    3556         psFree(where);
    3557         return false;
    3558     }
    3559 
    3560     long changed = psDBUpdateRows(config->dbh, "detResidExp", where, set);
    3561     psFree(set);
    3562     psFree(where);
    3563 
    3564     if (changed < 0) {
    3565         psError(PS_ERR_UNKNOWN, false, "no rows were updated");
    3566         return false;
    3567     }
    3568 
    3569     return true;
    3570 }
    3571 
    3572 static bool adddetrunsummaryMode(pxConfig *config)
    3573 {
    3574     PS_ASSERT_PTR_NON_NULL(config, false);
    3575 
    3576     // required
    3577     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    3578 
    3579     // optional
     3355
     3356    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    35803357    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
     3358
     3359    // The values supplied as arguments on the command (eg, -bg) are parsed
     3360    // by mdToDetRunSummary below.
     3361    // XXX why is there ever more than one?
    35813362
    35823363    psString query = pxDataGet("dettool_find_completed_runs.sql");
     
    35863367    }
    35873368
    3588     // build a query to search by det_id, iteration, exp_id
    3589     psMetadata *where = psMetadataAlloc();
    3590     PXOPT_COPY_STR(config->args, where, "-det_id", "det_id", "==");
    3591     PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    3592 
    3593     {
    3594         // there's not
     3369    if (psListLength(where->list)) {
    35953370        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
    3596         psFree(where);
    3597         if (whereClause) {
    3598             psStringAppend(&query, " WHERE %s", whereClause);
    3599             psFree(whereClause);
    3600         }
    3601     }
     3371        psStringAppend(&query, " WHERE %s", whereClause);
     3372        psFree(whereClause);
     3373    }
     3374    psFree(where);
    36023375
    36033376    if (!p_psDBRunQuery(config->dbh, query)) {
     
    36263399    }
    36273400
     3401    // XXX why is there ever more than one result here?
    36283402    for (long i = 0; i < psArrayLength(output); i++) {
    36293403        psMetadata *row = output->data[i];
     
    36543428
    36553429    // XXX this logic does not deal with the case of -code being set
     3430    // XXX it should be an error for -again and -code to both be set
    36563431    if (again) {
    36573432        if (!startNewIteration(config, (psS64)atoll(det_id))) {
     
    36803455}
    36813456
    3682 static detRunSummaryRow *mdToDetRunSummary(pxConfig *config, psMetadata *row)
    3683 {
    3684     PS_ASSERT_PTR_NON_NULL(config, false);
    3685 
    3686     bool status = false;
    3687     // from row
    3688     psS64 det_id = psMetadataLookupS64(&status, row, "det_id");
    3689     if (!status) {
    3690         psError(PS_ERR_UNKNOWN, false, "failed to lookup value for det_id");
    3691         return false;
    3692     }
    3693     psS32 iteration = psMetadataLookupS32(&status, row, "iteration");
    3694     if (!status) {
    3695         psError(PS_ERR_UNKNOWN, false, "failed to lookup value for iteration");
    3696         return false;
    3697     }
    3698 
    3699     // optional
    3700     PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    3701     PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
    3702     PXOPT_LOOKUP_F64(bg_mean_stdev, config->args, "-bg_mean_stdev", false, false);
    3703     // default values
    3704     PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
    3705     PXOPT_LOOKUP_S16(code, config->args, "-code", false, false);
    3706 
    3707     return detRunSummaryRowAlloc(
    3708             det_id,
    3709             iteration,
    3710             bg,
    3711             bg_stdev,
    3712             bg_mean_stdev,
    3713             accept,
    3714             code
    3715         );
    3716 }
    3717 
    37183457static bool detrunsummaryMode(pxConfig *config)
    37193458{
    37203459    PS_ASSERT_PTR_NON_NULL(config, false);
     3460
     3461    psMetadata *where = psMetadataAlloc();
     3462    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     3463    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
    37213464
    37223465    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     
    37243467    PXOPT_LOOKUP_BOOL(faulted, config->args, "-faulted", false);
    37253468
    3726     psString query = psStringCopy(
    3727         "SELECT DISTINCT\n"
    3728         "   detRunSummary.*,\n"
    3729         "   detRun.det_type,\n"
    3730         "   detRun.mode\n"
    3731         " FROM detRun\n"
    3732         " JOIN detRunSummary\n"
    3733         "   USING(det_id, iteration)\n"
    3734         " WHERE\n"
    3735         "   detRun.state = 'run'\n"
    3736         );
    3737 
    3738     if (config->where) {
    3739         psString whereClause = psDBGenerateWhereConditionSQL(config->where, NULL);
     3469    psString query = pxDataGet("dettool_detrunsummary.sql");
     3470    if (!query) {
     3471        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
     3472        psFree(where);
     3473        return false;
     3474    }
     3475
     3476    if (psListLength(where->list)) {
     3477        psString whereClause = psDBGenerateWhereConditionSQL(where, "NULL");
    37403478        psStringAppend(&query, " AND %s", whereClause);
    37413479        psFree(whereClause);
    37423480    }
     3481    psFree(where);
    37433482
    37443483    if (faulted) {
     
    37923531    PS_ASSERT_PTR_NON_NULL(config, false);
    37933532
     3533    psMetadata *where = psMetadataAlloc();
     3534    PXOPT_COPY_STR(config->args, where, "-det_id",    "det_id", "==");
     3535    PXOPT_COPY_S32(config->args, where, "-iteration", "iteration", "==");
     3536    PXOPT_COPY_STR(config->args, where, "-code",      "fault", "==");
     3537
    37943538    psString query = pxDataGet("dettool_revertdetrunsummary.sql");
    37953539    if (!query) {
     
    37983542    }
    37993543
    3800     if (config->where) {
    3801         psString whereClause = psDBGenerateWhereConditionSQL(config->where, "detRunSummary");
     3544    if (psListLength(where->list)) {
     3545        psString whereClause = psDBGenerateWhereConditionSQL(where, "detRunSummary");
    38023546        psStringAppend(&query, " AND %s", whereClause);
    38033547        psFree(whereClause);
    38043548    }
     3549    psFree(where);
    38053550
    38063551    if (!p_psDBRunQuery(config->dbh, query)) {
     
    38233568{
    38243569    PS_ASSERT_PTR_NON_NULL(config, false);
    3825 
    3826     // required
    3827     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    3828 
     3570   
     3571    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    38293572    PXOPT_LOOKUP_BOOL(accept, config->args, "-accept", false);
    38303573    PXOPT_LOOKUP_BOOL(reject, config->args, "-reject", false);
     
    38543597    PS_ASSERT_PTR_NON_NULL(config, false);
    38553598
    3856     // det_id is required
    3857     // XXX this isn't strictly nessicary but not having the det_id complicates
    3858     // incrementing the iteration number
    3859     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    3860 
     3599    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
    38613600    PXOPT_LOOKUP_BOOL(again, config->args, "-again", false);
    38623601    PXOPT_LOOKUP_STR(state, config->args, "-state", false, false);
     3602
    38633603    // either -rerun or -state must be specified
    38643604    if (!(again || state)) {
     
    38673607    }
    38683608    if (again && state) {
    3869         psError(PS_ERR_UNKNOWN, true, "either -again or -state must be specified");
     3609        psError(PS_ERR_UNKNOWN, true, "-accept and -reject are exclusive");
    38703610        return false;
    38713611    }
     
    38863626}
    38873627
     3628// used by updatedetrunMode
    38883629static bool startNewIteration(pxConfig *config, psS64 det_id)
    38893630{
     
    38963637    }
    38973638
    3898     // XXX this query was not restricted by det_id, resulting
    3899     // in an inconsistent UPDATE below.  I added this AND clause
    3900     // though there may be a cleaner method (EAM 2006.10.08)
     3639    // restrict the update only to the specified det_id
    39013640    psStringAppend(&query, " WHERE det_id = %" PRId64 , det_id);
    39023641
     
    41513890    PS_ASSERT_PTR_NON_NULL(config, false);
    41523891
    4153     // required
    4154     PXOPT_LOOKUP_STR(det_type, config->args, "-det_type", true, false);
    4155     PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", false, false);
    4156 
    4157     // optional
     3892    PXOPT_LOOKUP_STR(det_type, config->args, "-det_type", true, false); // required
     3893    PXOPT_LOOKUP_STR(filelevel, config->args, "-filelevel", true, false); // required
    41583894    PXOPT_LOOKUP_STR(workdir, config->args, "-workdir", false, false);
    41593895    PXOPT_LOOKUP_STR(camera, config->args, "-inst", false, false);
     
    41783914    PXOPT_LOOKUP_STR(parent, config->args, "-parent", false, false);
    41793915    PXOPT_LOOKUP_STR(label, config->args, "-label", false, false);
    4180 
    4181     // default
    41823916    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
    41833917
     
    41913925                      0,            // the iteration is fixed at 0
    41923926                      det_type,
    4193                       "register",   // mode
     3927                      "register",   // mode is required to be "register"
    41943928                      "register",   // state
    41953929                      filelevel,
     
    42623996}
    42633997
     3998// NOTE : this function is also used by addcorrectimfileMode
    42643999bool register_detrend_imfileMode(pxConfig *config)
    42654000{
    42664001    PS_ASSERT_PTR_NON_NULL(config, false);
    4267 
    4268     // required
    4269     PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false);
    4270     PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false);
    4271     PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false);
    4272 
    4273     // optional
     4002   
     4003    PXOPT_LOOKUP_STR(det_id, config->args, "-det_id", true, false); // required
     4004    PXOPT_LOOKUP_STR(class_id, config->args, "-class_id", true, false); // required
     4005    PXOPT_LOOKUP_STR(uri, config->args, "-uri", true, false); // required
    42744006    PXOPT_LOOKUP_F64(bg, config->args, "-bg", false, false);
    42754007    PXOPT_LOOKUP_F64(bg_stdev, config->args, "-bg_stdev", false, false);
     
    43894121    return true;
    43904122}
     4123
     4124
     4125#if 0
     4126// XXX this function was left in commented as this method may be useful in the
     4127// future
     4128static psArray *validDetInputClassIds(pxConfig *config, const char *det_id)
     4129{
     4130    PS_ASSERT_PTR_NON_NULL(config, NULL);
     4131    // det_id is input as a string because the fact that it is an integer
     4132    // is just a database impliementation detail.
     4133    PS_ASSERT_PTR_NON_NULL(det_id, NULL);
     4134
     4135    psArray *rawImfiles = searchInputImfiles(config, det_id);
     4136    if (!rawImfiles) {
     4137        return NULL;
     4138    }
     4139
     4140    psArray *valid_class_ids = NULL;
     4141    {
     4142        // All this jumping through hoops is so that we end up with unique
     4143        // values. PP thinks that making multiple passes through this array and
     4144        // deleting matched elements would end up being more expensive then a
     4145        // double sort and stagger scheme. JH thinks it would be cheaper to
     4146        // just do a unqiue sort and delete.  So this is really just a cheap
     4147        // hack to avoid implimenting a unique sort function but at least it's
     4148        // stable.
     4149        psHash *hash = psHashAlloc(psArrayLength(rawImfiles));
     4150        for (long i = 0; i < psArrayLength(rawImfiles); i++) {
     4151            psHashAdd(hash,
     4152                ((rawImfileRow *)rawImfiles->data[i])->class_id,
     4153                ((rawImfileRow *)rawImfiles->data[i])->class_id
     4154            );
     4155        }
     4156        valid_class_ids = psHashToArray(hash);
     4157        psFree(hash);
     4158    }
     4159    psFree(rawImfiles);
     4160
     4161    return valid_class_ids;
     4162}
     4163
     4164static psArray *searchInputImfiles(pxConfig *config, const char *det_id)
     4165{
     4166    PS_ASSERT_PTR_NON_NULL(config, NULL);
     4167    // det_id is input as a string because the fact that it is an integer
     4168    // is just a database impliementation detail.
     4169    PS_ASSERT_PTR_NON_NULL(det_id, NULL);
     4170
     4171    psArray *inputExps = NULL;
     4172    {
     4173        psMetadata *where = psMetadataAlloc();
     4174        if (!psMetadataAddS32(where, PS_LIST_TAIL, "det_id", 0, "==",
     4175                (psS32)atoi(det_id))) {
     4176            psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     4177            psFree(where);
     4178            return NULL;
     4179        }
     4180        inputExps = detInputExpSelectRowObjects(config->dbh, where, 0);
     4181        psFree(where);
     4182    }
     4183    if (!inputExps) {
     4184        psError(PS_ERR_UNKNOWN, false, "no detInputExp rows found");
     4185        return NULL;
     4186    }
     4187
     4188    // find rawImfiles associated with detInputExps
     4189    psArray *rawImfiles = NULL;
     4190    {
     4191        psMetadata *where = psMetadataAlloc();
     4192        for (long i = 0; i < psArrayLength(inputExps); i++) {
     4193            if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id",
     4194                    PS_META_DUPLICATE_OK, "==",
     4195                    ((detInputExpRow *)inputExps->data[i])->exp_id)) {
     4196                psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     4197                psFree(inputExps);
     4198                psFree(where);
     4199                return NULL;
     4200            }
     4201        }
     4202        psFree(inputExps);
     4203        rawImfiles = rawImfileSelectRowObjects(config->dbh, where, 0);
     4204        // XXX this really should be sorted for uniqueness
     4205        psFree(where);
     4206    }
     4207    if (!rawImfiles) {
     4208        psError(PS_ERR_UNKNOWN, false, "no rawImfile rows found");
     4209        return NULL;
     4210    }
     4211
     4212    return rawImfiles;
     4213}
     4214#endif
     4215
Note: See TracChangeset for help on using the changeset viewer.