IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 30, 2007, 4:45:31 PM (19 years ago)
Author:
jhoblitt
Message:

update

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ippdb/src/ippdb.c

    r15420 r15421  
    3131#include "ippdb.h"
    3232
     33#define PZDATASTORE_TABLE_NAME "pzDataStore"
    3334#define SUMMITEXP_TABLE_NAME "summitExp"
    3435#define SUMMITIMFILE_TABLE_NAME "summitImfile"
     
    4344#define GUIDEPENDINGEXP_TABLE_NAME "guidePendingExp"
    4445#define CHIPRUN_TABLE_NAME "chipRun"
    45 #define CHIPINPUTIMFILE_TABLE_NAME "chipInputImfile"
    4646#define CHIPPROCESSEDIMFILE_TABLE_NAME "chipProcessedImfile"
    4747#define CHIPMASK_TABLE_NAME "chipMask"
     
    7070#define DETRESIDEXP_TABLE_NAME "detResidExp"
    7171#define DETRUNSUMMARY_TABLE_NAME "detRunSummary"
     72#define DETREGISTEREDIMFILE_TABLE_NAME "detRegisteredImfile"
     73#define DETCORRECTEDEXP_TABLE_NAME "detCorrectedExp"
     74#define DETCORRECTEDIMFILE_TABLE_NAME "detCorrectedImfile"
     75#define MAGICRUN_TABLE_NAME "magicRun"
     76#define MAGICINPUTSKYFILE_TABLE_NAME "magicInputSkyfile"
     77#define MAGICTREE_TABLE_NAME "magicTree"
     78#define MAGICNODERESULT_TABLE_NAME "magicNodeResult"
     79#define MAGICMASK_TABLE_NAME "magicMask"
     80#define MAGICSKYFILEMASK_TABLE_NAME "magicSkyfileMask"
    7281#define MAX_STRING_LENGTH 1024
    7382
     
    246255}
    247256
     257static void pzDataStoreRowFree(pzDataStoreRow *object);
     258
     259pzDataStoreRow *pzDataStoreRowAlloc(const char *camera, const char *telescope, const char *uri)
     260{
     261    pzDataStoreRow  *_object;
     262
     263    _object = psAlloc(sizeof(pzDataStoreRow));
     264    psMemSetDeallocator(_object, (psFreeFunc)pzDataStoreRowFree);
     265
     266    _object->camera = psStringCopy(camera);
     267    _object->telescope = psStringCopy(telescope);
     268    _object->uri = psStringCopy(uri);
     269
     270    return _object;
     271}
     272
     273static void pzDataStoreRowFree(pzDataStoreRow *object)
     274{
     275    psFree(object->camera);
     276    psFree(object->telescope);
     277    psFree(object->uri);
     278}
     279
     280bool pzDataStoreCreateTable(psDB *dbh)
     281{
     282    psMetadata *md = psMetadataAlloc();
     283    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, "Primary Key", "64")) {
     284        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
     285        psFree(md);
     286        return false;
     287    }
     288    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, "Primary Key", "64")) {
     289        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
     290        psFree(md);
     291        return false;
     292    }
     293    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     294        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     295        psFree(md);
     296        return false;
     297    }
     298
     299    bool status = psDBCreateTable(dbh, PZDATASTORE_TABLE_NAME, md);
     300
     301    psFree(md);
     302
     303    return status;
     304}
     305
     306bool pzDataStoreDropTable(psDB *dbh)
     307{
     308    return psDBDropTable(dbh, PZDATASTORE_TABLE_NAME);
     309}
     310
     311bool pzDataStoreInsert(psDB * dbh, const char *camera, const char *telescope, const char *uri)
     312{
     313    psMetadata *md = psMetadataAlloc();
     314    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, camera)) {
     315        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
     316        psFree(md);
     317        return false;
     318    }
     319    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, telescope)) {
     320        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
     321        psFree(md);
     322        return false;
     323    }
     324    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     325        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     326        psFree(md);
     327        return false;
     328    }
     329
     330    bool status = psDBInsertOneRow(dbh, PZDATASTORE_TABLE_NAME, md);
     331    psFree(md);
     332
     333    return status;
     334}
     335
     336long long pzDataStoreDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     337{
     338    long long       deleted = 0;
     339
     340    long long count = psDBDeleteRows(dbh, PZDATASTORE_TABLE_NAME, where, limit);
     341    if (count < 0) {
     342        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDataStore");
     343        return count;
     344
     345        deleted += count;
     346    }
     347
     348    return deleted;
     349}
     350bool pzDataStoreInsertObject(psDB *dbh, pzDataStoreRow *object)
     351{
     352    return pzDataStoreInsert(dbh, object->camera, object->telescope, object->uri);
     353}
     354
     355bool pzDataStoreInsertObjects(psDB *dbh, psArray *objects)
     356{
     357    for (long i = 0; i < psArrayLength(objects); i++) {
     358        if (!pzDataStoreInsertObject(dbh, objects->data[i])) {
     359            return false;
     360        }
     361    }
     362
     363    return true;
     364}
     365
     366bool pzDataStoreInsertFits(psDB *dbh, const psFits *fits)
     367{
     368    psArray         *rowSet;
     369
     370    // move to (the first?) extension named  PZDATASTORE_TABLE_NAME
     371    if (!psFitsMoveExtName(fits, PZDATASTORE_TABLE_NAME)) {
     372        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZDATASTORE_TABLE_NAME);
     373        return false;
     374    }
     375
     376    // check HDU type
     377    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     378        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     379        return false;
     380    }
     381
     382    // read fits table
     383    rowSet = psFitsReadTable(fits);
     384    if (!rowSet) {
     385        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     386        psFree(rowSet);
     387        return false;
     388    }
     389
     390    if (!psDBInsertRows(dbh, PZDATASTORE_TABLE_NAME, rowSet)) {
     391        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     392        psFree(rowSet);
     393        return false;
     394    }
     395
     396    psFree(rowSet);
     397
     398    return true;
     399}
     400
     401bool pzDataStoreSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     402{
     403    psArray         *rowSet;
     404
     405    rowSet = psDBSelectRows(dbh, PZDATASTORE_TABLE_NAME, where, limit);
     406    if (!rowSet) {
     407        return false;
     408    }
     409
     410    // output to fits
     411    if (!psFitsWriteTable(fits, NULL, rowSet, PZDATASTORE_TABLE_NAME)) {
     412        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     413        psFree(rowSet);
     414        return false;
     415    }
     416
     417    psFree(rowSet);
     418
     419    return true;
     420}
     421
     422psMetadata *pzDataStoreMetadataFromObject(const pzDataStoreRow *object)
     423{
     424    psMetadata *md = psMetadataAlloc();
     425    if (!psMetadataAdd(md, PS_LIST_TAIL, "camera", PS_DATA_STRING, NULL, object->camera)) {
     426        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
     427        psFree(md);
     428        return false;
     429    }
     430    if (!psMetadataAdd(md, PS_LIST_TAIL, "telescope", PS_DATA_STRING, NULL, object->telescope)) {
     431        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
     432        psFree(md);
     433        return false;
     434    }
     435    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     436        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     437        psFree(md);
     438        return false;
     439    }
     440
     441
     442    return md;
     443}
     444
     445pzDataStoreRow *pzDataStoreObjectFromMetadata(psMetadata *md)
     446{
     447
     448bool status = false;
     449    char* camera = psMetadataLookupPtr(&status, md, "camera");
     450    if (!status) {
     451        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
     452        return false;
     453    }
     454    char* telescope = psMetadataLookupPtr(&status, md, "telescope");
     455    if (!status) {
     456        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
     457        return false;
     458    }
     459    char* uri = psMetadataLookupPtr(&status, md, "uri");
     460    if (!status) {
     461        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     462        return false;
     463    }
     464
     465    return pzDataStoreRowAlloc(camera, telescope, uri);
     466}
     467psArray *pzDataStoreSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     468{
     469    psArray         *rowSet;
     470    psArray         *returnSet;
     471    psU64           i;
     472
     473    rowSet = psDBSelectRows(dbh, PZDATASTORE_TABLE_NAME, where, limit);
     474    if (!rowSet) {
     475        return NULL;
     476    }
     477
     478    // convert psMetadata rows to row objects
     479
     480    returnSet = psArrayAllocEmpty(rowSet->n);
     481
     482    for (i = 0; i < rowSet->n; i++) {
     483        pzDataStoreRow *object = pzDataStoreObjectFromMetadata(rowSet->data[i]);
     484        psArrayAdd(returnSet, 0, object);
     485        psFree(object);
     486    }
     487
     488    psFree(rowSet);
     489
     490    return returnSet;
     491}
     492bool pzDataStoreDeleteObject(psDB *dbh, const pzDataStoreRow *object)
     493{
     494    psMetadata *where = pzDataStoreMetadataFromObject(object);
     495    long long count = psDBDeleteRows(dbh, PZDATASTORE_TABLE_NAME, where, 0);
     496    psFree(where);
     497    if (count < 0) {
     498        psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDataStore");
     499        return false;
     500    }
     501    if (count > 1) {
     502        // XXX should this be a psAbort() instead?  It is possible that
     503        // having an object match multiple rows was by design.
     504        psError(PS_ERR_UNKNOWN, true, "pzDataStoreRow object matched more then one row.  Check your database schema");
     505        return false;
     506    }
     507
     508    return true;
     509}
     510long long pzDataStoreDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     511{
     512    long long       deleted = 0;
     513
     514    for (long long i = 0; i < objects->n; i++) {
     515        pzDataStoreRow *object = objects->data[i];
     516        psMetadata *where = pzDataStoreMetadataFromObject(object);
     517        long long count = psDBDeleteRows(dbh, PZDATASTORE_TABLE_NAME, where, limit);
     518        psFree(where);
     519        if (count < 0) {
     520            psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzDataStore");
     521            return count;
     522        }
     523
     524        deleted += count;
     525    }
     526
     527    return deleted;
     528}
     529bool pzDataStorePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     530{
     531    PS_ASSERT_PTR_NON_NULL(objects, false);
     532
     533    psMetadata *output = psMetadataAlloc();
     534    for (long i = 0; i < psArrayLength(objects); i++) {
     535        psMetadata *md = pzDataStoreMetadataFromObject(objects->data[i]);
     536        if (!psMetadataAddMetadata(
     537            output,
     538            PS_LIST_TAIL,
     539            PZDATASTORE_TABLE_NAME,
     540            PS_META_DUPLICATE_OK,
     541            NULL,
     542            md
     543        )) {
     544            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     545            psFree(md);
     546            psFree(output);
     547            return false;
     548        }
     549        psFree(md);
     550    }
     551
     552    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     553        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     554        psFree(output);
     555    }
     556    psFree(output);
     557
     558    return true;
     559}
     560bool pzDataStorePrintObject(FILE *stream, pzDataStoreRow *object, bool mdcf)
     561{
     562    PS_ASSERT_PTR_NON_NULL(object, false);
     563
     564    psMetadata *md = pzDataStoreMetadataFromObject(object);
     565
     566    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     567        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     568        psFree(md);
     569    }
     570
     571    psFree(md);
     572
     573    return true;
     574}
    248575static void summitExpRowFree(summitExpRow *object);
    249576
     
    14201747static void pzPendingImfileRowFree(pzPendingImfileRow *object);
    14211748
    1422 pzPendingImfileRow *pzPendingImfileRowAlloc(const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id, psS64 exp_id)
     1749pzPendingImfileRow *pzPendingImfileRowAlloc(const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id)
    14231750{
    14241751    pzPendingImfileRow *_object;
     
    14321759    _object->class = psStringCopy(class);
    14331760    _object->class_id = psStringCopy(class_id);
    1434     _object->exp_id = exp_id;
    14351761
    14361762    return _object;
     
    14741800        return false;
    14751801    }
    1476     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Unique Key", 64)) {
    1477         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1478         psFree(md);
    1479         return false;
    1480     }
    14811802
    14821803    bool status = psDBCreateTable(dbh, PZPENDINGIMFILE_TABLE_NAME, md);
     
    14921813}
    14931814
    1494 bool pzPendingImfileInsert(psDB * dbh, const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id, psS64 exp_id)
     1815bool pzPendingImfileInsert(psDB * dbh, const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id)
    14951816{
    14961817    psMetadata *md = psMetadataAlloc();
     
    15171838    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
    15181839        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    1519         psFree(md);
    1520         return false;
    1521     }
    1522     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, exp_id)) {
    1523         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    15241840        psFree(md);
    15251841        return false;
     
    15481864bool pzPendingImfileInsertObject(psDB *dbh, pzPendingImfileRow *object)
    15491865{
    1550     return pzPendingImfileInsert(dbh, object->exp_name, object->camera, object->telescope, object->class, object->class_id, object->exp_id);
     1866    return pzPendingImfileInsert(dbh, object->exp_name, object->camera, object->telescope, object->class, object->class_id);
    15511867}
    15521868
     
    16461962        return false;
    16471963    }
    1648     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, object->exp_id)) {
    1649         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1650         psFree(md);
    1651         return false;
    1652     }
    16531964
    16541965
     
    16851996        return false;
    16861997    }
    1687     psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
    1688     if (!status) {
    1689         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
    1690         return false;
    1691     }
    1692 
    1693     return pzPendingImfileRowAlloc(exp_name, camera, telescope, class, class_id, exp_id);
     1998
     1999    return pzPendingImfileRowAlloc(exp_name, camera, telescope, class, class_id);
    16942000}
    16952001psArray *pzPendingImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    21212427static void pzDoneImfileRowFree(pzDoneImfileRow *object);
    21222428
    2123 pzDoneImfileRow *pzDoneImfileRowAlloc(const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id, psS64 exp_id, const char *uri)
     2429pzDoneImfileRow *pzDoneImfileRowAlloc(const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id, const char *uri)
    21242430{
    21252431    pzDoneImfileRow *_object;
     
    21332439    _object->class = psStringCopy(class);
    21342440    _object->class_id = psStringCopy(class_id);
    2135     _object->exp_id = exp_id;
    21362441    _object->uri = psStringCopy(uri);
    21372442
     
    21772482        return false;
    21782483    }
    2179     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Unique Key", 64)) {
    2180         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    2181         psFree(md);
    2182         return false;
    2183     }
    21842484    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
    21852485        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     
    22002500}
    22012501
    2202 bool pzDoneImfileInsert(psDB * dbh, const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id, psS64 exp_id, const char *uri)
     2502bool pzDoneImfileInsert(psDB * dbh, const char *exp_name, const char *camera, const char *telescope, const char *class, const char *class_id, const char *uri)
    22032503{
    22042504    psMetadata *md = psMetadataAlloc();
     
    22252525    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
    22262526        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    2227         psFree(md);
    2228         return false;
    2229     }
    2230     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, exp_id)) {
    2231         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    22322527        psFree(md);
    22332528        return false;
     
    22612556bool pzDoneImfileInsertObject(psDB *dbh, pzDoneImfileRow *object)
    22622557{
    2263     return pzDoneImfileInsert(dbh, object->exp_name, object->camera, object->telescope, object->class, object->class_id, object->exp_id, object->uri);
     2558    return pzDoneImfileInsert(dbh, object->exp_name, object->camera, object->telescope, object->class, object->class_id, object->uri);
    22642559}
    22652560
     
    23592654        return false;
    23602655    }
    2361     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, object->exp_id)) {
    2362         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    2363         psFree(md);
    2364         return false;
    2365     }
    23662656    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
    23672657        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     
    24032693        return false;
    24042694    }
    2405     psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
    2406     if (!status) {
    2407         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
    2408         return false;
    2409     }
    24102695    char* uri = psMetadataLookupPtr(&status, md, "uri");
    24112696    if (!status) {
     
    24142699    }
    24152700
    2416     return pzDoneImfileRowAlloc(exp_name, camera, telescope, class, class_id, exp_id, uri);
     2701    return pzDoneImfileRowAlloc(exp_name, camera, telescope, class, class_id, uri);
    24172702}
    24182703psArray *pzDoneImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    25262811static void newExpRowFree(newExpRow *object);
    25272812
    2528 newExpRow *newExpRowAlloc(psS64 exp_id, const char *tmp_exp_name, const char *tmp_camera, const char *tmp_telescope, const char *state, psS32 imfiles, const char *workdir, const char *workdir_state)
     2813newExpRow *newExpRowAlloc(psS64 exp_id, const char *tmp_exp_name, const char *tmp_camera, const char *tmp_telescope, const char *state, const char *workdir, const char *workdir_state, const char *reduction)
    25292814{
    25302815    newExpRow       *_object;
     
    25382823    _object->tmp_telescope = psStringCopy(tmp_telescope);
    25392824    _object->state = psStringCopy(state);
    2540     _object->imfiles = imfiles;
    25412825    _object->workdir = psStringCopy(workdir);
    25422826    _object->workdir_state = psStringCopy(workdir_state);
     2827    _object->reduction = psStringCopy(reduction);
    25432828
    25442829    return _object;
     
    25532838    psFree(object->workdir);
    25542839    psFree(object->workdir_state);
     2840    psFree(object->reduction);
    25552841}
    25562842
     
    25832869        return false;
    25842870    }
    2585     if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, 0)) {
    2586         psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
    2587         psFree(md);
    2588         return false;
    2589     }
    25902871    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, "destination for output files", "255")) {
    25912872        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     
    25982879        return false;
    25992880    }
     2881    if (!psMetadataAdd(md, PS_LIST_TAIL, "reduction", PS_DATA_STRING, "Reduction class", "64")) {
     2882        psError(PS_ERR_UNKNOWN, false, "failed to add item reduction");
     2883        psFree(md);
     2884        return false;
     2885    }
    26002886
    26012887    bool status = psDBCreateTable(dbh, NEWEXP_TABLE_NAME, md);
     
    26112897}
    26122898
    2613 bool newExpInsert(psDB * dbh, psS64 exp_id, const char *tmp_exp_name, const char *tmp_camera, const char *tmp_telescope, const char *state, psS32 imfiles, const char *workdir, const char *workdir_state)
     2899bool newExpInsert(psDB * dbh, psS64 exp_id, const char *tmp_exp_name, const char *tmp_camera, const char *tmp_telescope, const char *state, const char *workdir, const char *workdir_state, const char *reduction)
    26142900{
    26152901    psMetadata *md = psMetadataAlloc();
     
    26392925        return false;
    26402926    }
    2641     if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, imfiles)) {
    2642         psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
    2643         psFree(md);
    2644         return false;
    2645     }
    26462927    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, NULL, workdir)) {
    26472928        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     
    26512932    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir_state", PS_DATA_STRING, NULL, workdir_state)) {
    26522933        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir_state");
     2934        psFree(md);
     2935        return false;
     2936    }
     2937    if (!psMetadataAdd(md, PS_LIST_TAIL, "reduction", PS_DATA_STRING, NULL, reduction)) {
     2938        psError(PS_ERR_UNKNOWN, false, "failed to add item reduction");
    26532939        psFree(md);
    26542940        return false;
     
    26772963bool newExpInsertObject(psDB *dbh, newExpRow *object)
    26782964{
    2679     return newExpInsert(dbh, object->exp_id, object->tmp_exp_name, object->tmp_camera, object->tmp_telescope, object->state, object->imfiles, object->workdir, object->workdir_state);
     2965    return newExpInsert(dbh, object->exp_id, object->tmp_exp_name, object->tmp_camera, object->tmp_telescope, object->state, object->workdir, object->workdir_state, object->reduction);
    26802966}
    26812967
     
    27753061        return false;
    27763062    }
    2777     if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, object->imfiles)) {
    2778         psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
    2779         psFree(md);
    2780         return false;
    2781     }
    27823063    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, NULL, object->workdir)) {
    27833064        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     
    27903071        return false;
    27913072    }
     3073    if (!psMetadataAdd(md, PS_LIST_TAIL, "reduction", PS_DATA_STRING, NULL, object->reduction)) {
     3074        psError(PS_ERR_UNKNOWN, false, "failed to add item reduction");
     3075        psFree(md);
     3076        return false;
     3077    }
    27923078
    27933079
     
    28243110        return false;
    28253111    }
    2826     psS32 imfiles = psMetadataLookupS32(&status, md, "imfiles");
    2827     if (!status) {
    2828         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
    2829         return false;
    2830     }
    28313112    char* workdir = psMetadataLookupPtr(&status, md, "workdir");
    28323113    if (!status) {
     
    28393120        return false;
    28403121    }
    2841 
    2842     return newExpRowAlloc(exp_id, tmp_exp_name, tmp_camera, tmp_telescope, state, imfiles, workdir, workdir_state);
     3122    char* reduction = psMetadataLookupPtr(&status, md, "reduction");
     3123    if (!status) {
     3124        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item reduction");
     3125        return false;
     3126    }
     3127
     3128    return newExpRowAlloc(exp_id, tmp_exp_name, tmp_camera, tmp_telescope, state, workdir, workdir_state, reduction);
    28433129}
    28443130psArray *newExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    32693555static void rawExpRowFree(rawExpRow *object);
    32703556
    3271 rawExpRow *rawExpRowAlloc(psS64 exp_id, const char *exp_name, const char *camera, const char *telescope, psTime* dateobs, const char *exp_tag, const char *exp_type, psS32 imfiles, const char *filelevel, const char *workdir, const char *filter, psF32 airmass, psF64 ra, psF64 decl, psF32 exp_time, psF32 sat_pixel_frac, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 alt, psF64 az, psF32 ccd_temp, psF64 posang, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *object, psF32 solang, psS16 fault)
     3557rawExpRow *rawExpRowAlloc(psS64 exp_id, const char *exp_name, const char *camera, const char *telescope, psTime* dateobs, const char *exp_tag, const char *exp_type, const char *filelevel, const char *workdir, const char *reduction, const char *filter, psF32 airmass, psF64 ra, psF64 decl, psF32 exp_time, psF32 sat_pixel_frac, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 alt, psF64 az, psF32 ccd_temp, psF64 posang, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *object, psF32 solang, psS16 fault)
    32723558{
    32733559    rawExpRow       *_object;
     
    32833569    _object->exp_tag = psStringCopy(exp_tag);
    32843570    _object->exp_type = psStringCopy(exp_type);
    3285     _object->imfiles = imfiles;
    32863571    _object->filelevel = psStringCopy(filelevel);
    32873572    _object->workdir = psStringCopy(workdir);
     3573    _object->reduction = psStringCopy(reduction);
    32883574    _object->filter = psStringCopy(filter);
    32893575    _object->airmass = airmass;
     
    33213607    psFree(object->filelevel);
    33223608    psFree(object->workdir);
     3609    psFree(object->reduction);
    33233610    psFree(object->filter);
    33243611    psFree(object->object);
     
    33633650        return false;
    33643651    }
    3365     if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, 0)) {
    3366         psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
    3367         psFree(md);
    3368         return false;
    3369     }
    33703652    if (!psMetadataAdd(md, PS_LIST_TAIL, "filelevel", PS_DATA_STRING, NULL, "64")) {
    33713653        psError(PS_ERR_UNKNOWN, false, "failed to add item filelevel");
     
    33783660        return false;
    33793661    }
     3662    if (!psMetadataAdd(md, PS_LIST_TAIL, "reduction", PS_DATA_STRING, "Reduction class", "64")) {
     3663        psError(PS_ERR_UNKNOWN, false, "failed to add item reduction");
     3664        psFree(md);
     3665        return false;
     3666    }
    33803667    if (!psMetadataAdd(md, PS_LIST_TAIL, "filter", PS_DATA_STRING, NULL, "64")) {
    33813668        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
     
    34963783}
    34973784
    3498 bool rawExpInsert(psDB * dbh, psS64 exp_id, const char *exp_name, const char *camera, const char *telescope, psTime* dateobs, const char *exp_tag, const char *exp_type, psS32 imfiles, const char *filelevel, const char *workdir, const char *filter, psF32 airmass, psF64 ra, psF64 decl, psF32 exp_time, psF32 sat_pixel_frac, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 alt, psF64 az, psF32 ccd_temp, psF64 posang, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *object, psF32 solang, psS16 fault)
     3785bool rawExpInsert(psDB * dbh, psS64 exp_id, const char *exp_name, const char *camera, const char *telescope, psTime* dateobs, const char *exp_tag, const char *exp_type, const char *filelevel, const char *workdir, const char *reduction, const char *filter, psF32 airmass, psF64 ra, psF64 decl, psF32 exp_time, psF32 sat_pixel_frac, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 alt, psF64 az, psF32 ccd_temp, psF64 posang, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *object, psF32 solang, psS16 fault)
    34993786{
    35003787    psMetadata *md = psMetadataAlloc();
     
    35343821        return false;
    35353822    }
    3536     if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, imfiles)) {
    3537         psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
    3538         psFree(md);
    3539         return false;
    3540     }
    35413823    if (!psMetadataAdd(md, PS_LIST_TAIL, "filelevel", PS_DATA_STRING, NULL, filelevel)) {
    35423824        psError(PS_ERR_UNKNOWN, false, "failed to add item filelevel");
     
    35463828    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, NULL, workdir)) {
    35473829        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     3830        psFree(md);
     3831        return false;
     3832    }
     3833    if (!psMetadataAdd(md, PS_LIST_TAIL, "reduction", PS_DATA_STRING, NULL, reduction)) {
     3834        psError(PS_ERR_UNKNOWN, false, "failed to add item reduction");
    35483835        psFree(md);
    35493836        return false;
     
    36773964bool rawExpInsertObject(psDB *dbh, rawExpRow *object)
    36783965{
    3679     return rawExpInsert(dbh, object->exp_id, object->exp_name, object->camera, object->telescope, object->dateobs, object->exp_tag, object->exp_type, object->imfiles, object->filelevel, object->workdir, object->filter, object->airmass, object->ra, object->decl, object->exp_time, object->sat_pixel_frac, object->bg, object->bg_stdev, object->bg_mean_stdev, object->alt, object->az, object->ccd_temp, object->posang, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->object, object->solang, object->fault);
     3966    return rawExpInsert(dbh, object->exp_id, object->exp_name, object->camera, object->telescope, object->dateobs, object->exp_tag, object->exp_type, object->filelevel, object->workdir, object->reduction, object->filter, object->airmass, object->ra, object->decl, object->exp_time, object->sat_pixel_frac, object->bg, object->bg_stdev, object->bg_mean_stdev, object->alt, object->az, object->ccd_temp, object->posang, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->object, object->solang, object->fault);
    36803967}
    36813968
     
    37854072        return false;
    37864073    }
    3787     if (!psMetadataAdd(md, PS_LIST_TAIL, "imfiles", PS_DATA_S32, NULL, object->imfiles)) {
    3788         psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
    3789         psFree(md);
    3790         return false;
    3791     }
    37924074    if (!psMetadataAdd(md, PS_LIST_TAIL, "filelevel", PS_DATA_STRING, NULL, object->filelevel)) {
    37934075        psError(PS_ERR_UNKNOWN, false, "failed to add item filelevel");
     
    38004082        return false;
    38014083    }
     4084    if (!psMetadataAdd(md, PS_LIST_TAIL, "reduction", PS_DATA_STRING, NULL, object->reduction)) {
     4085        psError(PS_ERR_UNKNOWN, false, "failed to add item reduction");
     4086        psFree(md);
     4087        return false;
     4088    }
    38024089    if (!psMetadataAdd(md, PS_LIST_TAIL, "filter", PS_DATA_STRING, NULL, object->filter)) {
    38034090        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
     
    39494236        return false;
    39504237    }
    3951     psS32 imfiles = psMetadataLookupS32(&status, md, "imfiles");
    3952     if (!status) {
    3953         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
    3954         return false;
    3955     }
    39564238    char* filelevel = psMetadataLookupPtr(&status, md, "filelevel");
    39574239    if (!status) {
     
    39644246        return false;
    39654247    }
     4248    char* reduction = psMetadataLookupPtr(&status, md, "reduction");
     4249    if (!status) {
     4250        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item reduction");
     4251        return false;
     4252    }
    39664253    char* filter = psMetadataLookupPtr(&status, md, "filter");
    39674254    if (!status) {
     
    40704357    }
    40714358
    4072     return rawExpRowAlloc(exp_id, exp_name, camera, telescope, dateobs, exp_tag, exp_type, imfiles, filelevel, workdir, filter, airmass, ra, decl, exp_time, sat_pixel_frac, bg, bg_stdev, bg_mean_stdev, alt, az, ccd_temp, posang, user_1, user_2, user_3, user_4, user_5, object, solang, fault);
     4359    return rawExpRowAlloc(exp_id, exp_name, camera, telescope, dateobs, exp_tag, exp_type, filelevel, workdir, reduction, filter, airmass, ra, decl, exp_time, sat_pixel_frac, bg, bg_stdev, bg_mean_stdev, alt, az, ccd_temp, posang, user_1, user_2, user_3, user_4, user_5, object, solang, fault);
    40734360}
    40744361psArray *rawExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    53915678static void chipRunRowFree(chipRunRow *object);
    53925679
    5393 chipRunRow *chipRunRowAlloc(psS64 chip_id, const char *state, const char *workdir, const char *workdir_state, const char *label, const char *reduction, const char *expgroup, const char *dvodb)
     5680chipRunRow *chipRunRowAlloc(psS64 chip_id, psS64 exp_id, const char *state, const char *workdir, const char *workdir_state, const char *label, const char *reduction, const char *expgroup, const char *dvodb)
    53945681{
    53955682    chipRunRow      *_object;
     
    53995686
    54005687    _object->chip_id = chip_id;
     5688    _object->exp_id = exp_id;
    54015689    _object->state = psStringCopy(state);
    54025690    _object->workdir = psStringCopy(workdir);
     
    54295717        return false;
    54305718    }
    5431     if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, "key", "64")) {
     5719    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Key INDEX(chip_id, exp_id) fkey (exp_id) ref rawExp(exp_id)", 64)) {
     5720        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     5721        psFree(md);
     5722        return false;
     5723    }
     5724    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, "Key", "64")) {
    54325725        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
    54335726        psFree(md);
     
    54395732        return false;
    54405733    }
    5441     if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir_state", PS_DATA_STRING, "key", "64")) {
     5734    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir_state", PS_DATA_STRING, "Key", "64")) {
    54425735        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir_state");
    54435736        psFree(md);
    54445737        return false;
    54455738    }
    5446     if (!psMetadataAdd(md, PS_LIST_TAIL, "label", PS_DATA_STRING, "key", "64")) {
     5739    if (!psMetadataAdd(md, PS_LIST_TAIL, "label", PS_DATA_STRING, "Key", "64")) {
    54475740        psError(PS_ERR_UNKNOWN, false, "failed to add item label");
    54485741        psFree(md);
     
    54545747        return false;
    54555748    }
    5456     if (!psMetadataAdd(md, PS_LIST_TAIL, "expgroup", PS_DATA_STRING, "key", "64")) {
     5749    if (!psMetadataAdd(md, PS_LIST_TAIL, "expgroup", PS_DATA_STRING, "Key", "64")) {
    54575750        psError(PS_ERR_UNKNOWN, false, "failed to add item expgroup");
    54585751        psFree(md);
     
    54775770}
    54785771
    5479 bool chipRunInsert(psDB * dbh, psS64 chip_id, const char *state, const char *workdir, const char *workdir_state, const char *label, const char *reduction, const char *expgroup, const char *dvodb)
     5772bool chipRunInsert(psDB * dbh, psS64 chip_id, psS64 exp_id, const char *state, const char *workdir, const char *workdir_state, const char *label, const char *reduction, const char *expgroup, const char *dvodb)
    54805773{
    54815774    psMetadata *md = psMetadataAlloc();
    54825775    if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, NULL, chip_id)) {
    54835776        psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
     5777        psFree(md);
     5778        return false;
     5779    }
     5780    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, exp_id)) {
     5781        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    54845782        psFree(md);
    54855783        return false;
     
    55435841bool chipRunInsertObject(psDB *dbh, chipRunRow *object)
    55445842{
    5545     return chipRunInsert(dbh, object->chip_id, object->state, object->workdir, object->workdir_state, object->label, object->reduction, object->expgroup, object->dvodb);
     5843    return chipRunInsert(dbh, object->chip_id, object->exp_id, object->state, object->workdir, object->workdir_state, object->label, object->reduction, object->expgroup, object->dvodb);
    55465844}
    55475845
     
    56215919        return false;
    56225920    }
     5921    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, object->exp_id)) {
     5922        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     5923        psFree(md);
     5924        return false;
     5925    }
    56235926    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, NULL, object->state)) {
    56245927        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     
    56705973        return false;
    56715974    }
     5975    psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
     5976    if (!status) {
     5977        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
     5978        return false;
     5979    }
    56725980    char* state = psMetadataLookupPtr(&status, md, "state");
    56735981    if (!status) {
     
    57066014    }
    57076015
    5708     return chipRunRowAlloc(chip_id, state, workdir, workdir_state, label, reduction, expgroup, dvodb);
     6016    return chipRunRowAlloc(chip_id, exp_id, state, workdir, workdir_state, label, reduction, expgroup, dvodb);
    57096017}
    57106018psArray *chipRunSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    58066114
    58076115    psMetadata *md = chipRunMetadataFromObject(object);
    5808 
    5809     if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
    5810         psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
    5811         psFree(md);
    5812     }
    5813 
    5814     psFree(md);
    5815 
    5816     return true;
    5817 }
    5818 static void chipInputImfileRowFree(chipInputImfileRow *object);
    5819 
    5820 chipInputImfileRow *chipInputImfileRowAlloc(psS64 chip_id, psS64 exp_id, const char *class_id)
    5821 {
    5822     chipInputImfileRow *_object;
    5823 
    5824     _object = psAlloc(sizeof(chipInputImfileRow));
    5825     psMemSetDeallocator(_object, (psFreeFunc)chipInputImfileRowFree);
    5826 
    5827     _object->chip_id = chip_id;
    5828     _object->exp_id = exp_id;
    5829     _object->class_id = psStringCopy(class_id);
    5830 
    5831     return _object;
    5832 }
    5833 
    5834 static void chipInputImfileRowFree(chipInputImfileRow *object)
    5835 {
    5836     psFree(object->class_id);
    5837 }
    5838 
    5839 bool chipInputImfileCreateTable(psDB *dbh)
    5840 {
    5841     psMetadata *md = psMetadataAlloc();
    5842     if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, "Primary Key fkey (chip_id) ref chipRun(chip_id)", 0)) {
    5843         psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
    5844         psFree(md);
    5845         return false;
    5846     }
    5847     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey (exp_id, class_id) ref rawImfile (exp_id, class_id)", 64)) {
    5848         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    5849         psFree(md);
    5850         return false;
    5851     }
    5852     if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
    5853         psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    5854         psFree(md);
    5855         return false;
    5856     }
    5857 
    5858     bool status = psDBCreateTable(dbh, CHIPINPUTIMFILE_TABLE_NAME, md);
    5859 
    5860     psFree(md);
    5861 
    5862     return status;
    5863 }
    5864 
    5865 bool chipInputImfileDropTable(psDB *dbh)
    5866 {
    5867     return psDBDropTable(dbh, CHIPINPUTIMFILE_TABLE_NAME);
    5868 }
    5869 
    5870 bool chipInputImfileInsert(psDB * dbh, psS64 chip_id, psS64 exp_id, const char *class_id)
    5871 {
    5872     psMetadata *md = psMetadataAlloc();
    5873     if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, NULL, chip_id)) {
    5874         psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
    5875         psFree(md);
    5876         return false;
    5877     }
    5878     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, exp_id)) {
    5879         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    5880         psFree(md);
    5881         return false;
    5882     }
    5883     if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
    5884         psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    5885         psFree(md);
    5886         return false;
    5887     }
    5888 
    5889     bool status = psDBInsertOneRow(dbh, CHIPINPUTIMFILE_TABLE_NAME, md);
    5890     psFree(md);
    5891 
    5892     return status;
    5893 }
    5894 
    5895 long long chipInputImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
    5896 {
    5897     long long       deleted = 0;
    5898 
    5899     long long count = psDBDeleteRows(dbh, CHIPINPUTIMFILE_TABLE_NAME, where, limit);
    5900     if (count < 0) {
    5901         psError(PS_ERR_UNKNOWN, true, "failed to delete row from chipInputImfile");
    5902         return count;
    5903 
    5904         deleted += count;
    5905     }
    5906 
    5907     return deleted;
    5908 }
    5909 bool chipInputImfileInsertObject(psDB *dbh, chipInputImfileRow *object)
    5910 {
    5911     return chipInputImfileInsert(dbh, object->chip_id, object->exp_id, object->class_id);
    5912 }
    5913 
    5914 bool chipInputImfileInsertObjects(psDB *dbh, psArray *objects)
    5915 {
    5916     for (long i = 0; i < psArrayLength(objects); i++) {
    5917         if (!chipInputImfileInsertObject(dbh, objects->data[i])) {
    5918             return false;
    5919         }
    5920     }
    5921 
    5922     return true;
    5923 }
    5924 
    5925 bool chipInputImfileInsertFits(psDB *dbh, const psFits *fits)
    5926 {
    5927     psArray         *rowSet;
    5928 
    5929     // move to (the first?) extension named  CHIPINPUTIMFILE_TABLE_NAME
    5930     if (!psFitsMoveExtName(fits, CHIPINPUTIMFILE_TABLE_NAME)) {
    5931         psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", CHIPINPUTIMFILE_TABLE_NAME);
    5932         return false;
    5933     }
    5934 
    5935     // check HDU type
    5936     if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
    5937         psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
    5938         return false;
    5939     }
    5940 
    5941     // read fits table
    5942     rowSet = psFitsReadTable(fits);
    5943     if (!rowSet) {
    5944         psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
    5945         psFree(rowSet);
    5946         return false;
    5947     }
    5948 
    5949     if (!psDBInsertRows(dbh, CHIPINPUTIMFILE_TABLE_NAME, rowSet)) {
    5950         psError(PS_ERR_UNKNOWN, false, "databse insert failed");
    5951         psFree(rowSet);
    5952         return false;
    5953     }
    5954 
    5955     psFree(rowSet);
    5956 
    5957     return true;
    5958 }
    5959 
    5960 bool chipInputImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
    5961 {
    5962     psArray         *rowSet;
    5963 
    5964     rowSet = psDBSelectRows(dbh, CHIPINPUTIMFILE_TABLE_NAME, where, limit);
    5965     if (!rowSet) {
    5966         return false;
    5967     }
    5968 
    5969     // output to fits
    5970     if (!psFitsWriteTable(fits, NULL, rowSet, CHIPINPUTIMFILE_TABLE_NAME)) {
    5971         psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
    5972         psFree(rowSet);
    5973         return false;
    5974     }
    5975 
    5976     psFree(rowSet);
    5977 
    5978     return true;
    5979 }
    5980 
    5981 psMetadata *chipInputImfileMetadataFromObject(const chipInputImfileRow *object)
    5982 {
    5983     psMetadata *md = psMetadataAlloc();
    5984     if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, NULL, object->chip_id)) {
    5985         psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
    5986         psFree(md);
    5987         return false;
    5988     }
    5989     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, object->exp_id)) {
    5990         psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    5991         psFree(md);
    5992         return false;
    5993     }
    5994     if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
    5995         psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    5996         psFree(md);
    5997         return false;
    5998     }
    5999 
    6000 
    6001     return md;
    6002 }
    6003 
    6004 chipInputImfileRow *chipInputImfileObjectFromMetadata(psMetadata *md)
    6005 {
    6006 
    6007 bool status = false;
    6008     psS64 chip_id = psMetadataLookupS64(&status, md, "chip_id");
    6009     if (!status) {
    6010         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item chip_id");
    6011         return false;
    6012     }
    6013     psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
    6014     if (!status) {
    6015         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
    6016         return false;
    6017     }
    6018     char* class_id = psMetadataLookupPtr(&status, md, "class_id");
    6019     if (!status) {
    6020         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
    6021         return false;
    6022     }
    6023 
    6024     return chipInputImfileRowAlloc(chip_id, exp_id, class_id);
    6025 }
    6026 psArray *chipInputImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
    6027 {
    6028     psArray         *rowSet;
    6029     psArray         *returnSet;
    6030     psU64           i;
    6031 
    6032     rowSet = psDBSelectRows(dbh, CHIPINPUTIMFILE_TABLE_NAME, where, limit);
    6033     if (!rowSet) {
    6034         return NULL;
    6035     }
    6036 
    6037     // convert psMetadata rows to row objects
    6038 
    6039     returnSet = psArrayAllocEmpty(rowSet->n);
    6040 
    6041     for (i = 0; i < rowSet->n; i++) {
    6042         chipInputImfileRow *object = chipInputImfileObjectFromMetadata(rowSet->data[i]);
    6043         psArrayAdd(returnSet, 0, object);
    6044         psFree(object);
    6045     }
    6046 
    6047     psFree(rowSet);
    6048 
    6049     return returnSet;
    6050 }
    6051 bool chipInputImfileDeleteObject(psDB *dbh, const chipInputImfileRow *object)
    6052 {
    6053     psMetadata *where = chipInputImfileMetadataFromObject(object);
    6054     long long count = psDBDeleteRows(dbh, CHIPINPUTIMFILE_TABLE_NAME, where, 0);
    6055     psFree(where);
    6056     if (count < 0) {
    6057         psError(PS_ERR_UNKNOWN, true, "failed to delete row from chipInputImfile");
    6058         return false;
    6059     }
    6060     if (count > 1) {
    6061         // XXX should this be a psAbort() instead?  It is possible that
    6062         // having an object match multiple rows was by design.
    6063         psError(PS_ERR_UNKNOWN, true, "chipInputImfileRow object matched more then one row.  Check your database schema");
    6064         return false;
    6065     }
    6066 
    6067     return true;
    6068 }
    6069 long long chipInputImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
    6070 {
    6071     long long       deleted = 0;
    6072 
    6073     for (long long i = 0; i < objects->n; i++) {
    6074         chipInputImfileRow *object = objects->data[i];
    6075         psMetadata *where = chipInputImfileMetadataFromObject(object);
    6076         long long count = psDBDeleteRows(dbh, CHIPINPUTIMFILE_TABLE_NAME, where, limit);
    6077         psFree(where);
    6078         if (count < 0) {
    6079             psError(PS_ERR_UNKNOWN, true, "failed to delete row from chipInputImfile");
    6080             return count;
    6081         }
    6082 
    6083         deleted += count;
    6084     }
    6085 
    6086     return deleted;
    6087 }
    6088 bool chipInputImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
    6089 {
    6090     PS_ASSERT_PTR_NON_NULL(objects, false);
    6091 
    6092     psMetadata *output = psMetadataAlloc();
    6093     for (long i = 0; i < psArrayLength(objects); i++) {
    6094         psMetadata *md = chipInputImfileMetadataFromObject(objects->data[i]);
    6095         if (!psMetadataAddMetadata(
    6096             output,
    6097             PS_LIST_TAIL,
    6098             CHIPINPUTIMFILE_TABLE_NAME,
    6099             PS_META_DUPLICATE_OK,
    6100             NULL,
    6101             md
    6102         )) {
    6103             psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
    6104             psFree(md);
    6105             psFree(output);
    6106             return false;
    6107         }
    6108         psFree(md);
    6109     }
    6110 
    6111     if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
    6112         psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
    6113         psFree(output);
    6114     }
    6115     psFree(output);
    6116 
    6117     return true;
    6118 }
    6119 bool chipInputImfilePrintObject(FILE *stream, chipInputImfileRow *object, bool mdcf)
    6120 {
    6121     PS_ASSERT_PTR_NON_NULL(object, false);
    6122 
    6123     psMetadata *md = chipInputImfileMetadataFromObject(object);
    61246116
    61256117    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     
    61796171{
    61806172    psMetadata *md = psMetadataAlloc();
    6181     if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, "Primary Key fkey (chip_id, exp_id, class_id) ref chipInputImfile(chip_id, exp_id, class_id)", 0)) {
     6173    if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, "Primary Key fkey (chip_id, exp_id) ref chipRun(chip_id, exp_id)", 0)) {
    61826174        psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
    61836175        psFree(md);
    61846176        return false;
    61856177    }
    6186     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key", 64)) {
     6178    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey (exp_id, class_id) ref rawImfile(exp_id, class_id)", 64)) {
    61876179        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    61886180        psFree(md);
     
    62596251        return false;
    62606252    }
    6261     if (!psMetadataAdd(md, PS_LIST_TAIL, "fwhm", PS_DATA_F32, NULL, 0.0)) {
     6253    if (!psMetadataAdd(md, PS_LIST_TAIL, "fwhm", PS_DATA_F32, "# replace this with fwhm_major", 0.0)) {
    62626254        psError(PS_ERR_UNKNOWN, false, "failed to add item fwhm");
    62636255        psFree(md);
    62646256        return false;
    62656257    }
    6266     if (!psMetadataAdd(md, PS_LIST_TAIL, "fwhm_range", PS_DATA_F32, NULL, 0.0)) {
     6258    if (!psMetadataAdd(md, PS_LIST_TAIL, "fwhm_range", PS_DATA_F32, "# replace this with fwhm_minor", 0.0)) {
    62676259        psError(PS_ERR_UNKNOWN, false, "failed to add item fwhm_range");
    62686260        psFree(md);
     
    72067198        return false;
    72077199    }
    7208     if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, "Primary Key fkey(chip_id) ref chipRun(chip_id)", 0)) {
     7200    if (!psMetadataAdd(md, PS_LIST_TAIL, "chip_id", PS_DATA_S64, "Key INDEX(cam_id, chip_id) fkey(chip_id) ref chipRun(chip_id)", 0)) {
    72097201        psError(PS_ERR_UNKNOWN, false, "failed to add item chip_id");
    72107202        psFree(md);
     
    96009592static void warpSkyfileRowFree(warpSkyfileRow *object);
    96019593
    9602 warpSkyfileRow *warpSkyfileRowAlloc(psS64 warp_id, const char *skycell_id, const char *tess_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev)
     9594warpSkyfileRow *warpSkyfileRowAlloc(psS64 warp_id, const char *skycell_id, const char *tess_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev, psF64 good_frac, psS16 fault)
    96039595{
    96049596    warpSkyfileRow  *_object;
     
    96149606    _object->bg = bg;
    96159607    _object->bg_stdev = bg_stdev;
     9608    _object->good_frac = good_frac;
     9609    _object->fault = fault;
    96169610
    96179611    return _object;
     
    96649658        return false;
    96659659    }
     9660    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, "Key", 0.0)) {
     9661        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     9662        psFree(md);
     9663        return false;
     9664    }
     9665    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, "Key", 0)) {
     9666        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     9667        psFree(md);
     9668        return false;
     9669    }
    96669670
    96679671    bool status = psDBCreateTable(dbh, WARPSKYFILE_TABLE_NAME, md);
     
    96779681}
    96789682
    9679 bool warpSkyfileInsert(psDB * dbh, psS64 warp_id, const char *skycell_id, const char *tess_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev)
     9683bool warpSkyfileInsert(psDB * dbh, psS64 warp_id, const char *skycell_id, const char *tess_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev, psF64 good_frac, psS16 fault)
    96809684{
    96819685    psMetadata *md = psMetadataAlloc();
     
    97129716    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_stdev", PS_DATA_F64, NULL, bg_stdev)) {
    97139717        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
     9718        psFree(md);
     9719        return false;
     9720    }
     9721    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, NULL, good_frac)) {
     9722        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     9723        psFree(md);
     9724        return false;
     9725    }
     9726    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, fault)) {
     9727        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
    97149728        psFree(md);
    97159729        return false;
     
    97389752bool warpSkyfileInsertObject(psDB *dbh, warpSkyfileRow *object)
    97399753{
    9740     return warpSkyfileInsert(dbh, object->warp_id, object->skycell_id, object->tess_id, object->uri, object->path_base, object->bg, object->bg_stdev);
     9754    return warpSkyfileInsert(dbh, object->warp_id, object->skycell_id, object->tess_id, object->uri, object->path_base, object->bg, object->bg_stdev, object->good_frac, object->fault);
    97419755}
    97429756
     
    98469860        return false;
    98479861    }
     9862    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, NULL, object->good_frac)) {
     9863        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     9864        psFree(md);
     9865        return false;
     9866    }
     9867    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, object->fault)) {
     9868        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     9869        psFree(md);
     9870        return false;
     9871    }
    98489872
    98499873
     
    98909914        return false;
    98919915    }
    9892 
    9893     return warpSkyfileRowAlloc(warp_id, skycell_id, tess_id, uri, path_base, bg, bg_stdev);
     9916    psF64 good_frac = psMetadataLookupF64(&status, md, "good_frac");
     9917    if (!status) {
     9918        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item good_frac");
     9919        return false;
     9920    }
     9921    psS16 fault = psMetadataLookupS16(&status, md, "fault");
     9922    if (!status) {
     9923        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fault");
     9924        return false;
     9925    }
     9926
     9927    return warpSkyfileRowAlloc(warp_id, skycell_id, tess_id, uri, path_base, bg, bg_stdev, good_frac, fault);
    98949928}
    98959929psArray *warpSkyfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    1040810442static void diffInputSkyfileRowFree(diffInputSkyfileRow *object);
    1040910443
    10410 diffInputSkyfileRow *diffInputSkyfileRowAlloc(psS64 diff_id, psS64 warp_id, const char *skycell_id, const char *tess_id, const char *kind, bool template)
     10444diffInputSkyfileRow *diffInputSkyfileRowAlloc(psS64 diff_id, bool template, psS64 stack_id, psS64 warp_id, const char *skycell_id, const char *tess_id, const char *kind)
    1041110445{
    1041210446    diffInputSkyfileRow *_object;
     
    1041610450
    1041710451    _object->diff_id = diff_id;
     10452    _object->template = template;
     10453    _object->stack_id = stack_id;
    1041810454    _object->warp_id = warp_id;
    1041910455    _object->skycell_id = psStringCopy(skycell_id);
    1042010456    _object->tess_id = psStringCopy(tess_id);
    1042110457    _object->kind = psStringCopy(kind);
    10422     _object->template = template;
    1042310458
    1042410459    return _object;
     
    1044010475        return false;
    1044110476    }
    10442     if (!psMetadataAdd(md, PS_LIST_TAIL, "warp_id", PS_DATA_S64, "Primary Key fkey(warp_id, skycell_id, tess_id) ref warpSkyfile(warp_id, skycell_id, tess_id)", 0)) {
     10477    if (!psMetadataAdd(md, PS_LIST_TAIL, "template", PS_DATA_BOOL, "Primary Key", 0)) {
     10478        psError(PS_ERR_UNKNOWN, false, "failed to add item template");
     10479        psFree(md);
     10480        return false;
     10481    }
     10482    if (!psMetadataAdd(md, PS_LIST_TAIL, "stack_id", PS_DATA_S64, "fkey(stack_id) ref stackSumSkyfile(stack_id)", 0)) {
     10483        psError(PS_ERR_UNKNOWN, false, "failed to add item stack_id");
     10484        psFree(md);
     10485        return false;
     10486    }
     10487    if (!psMetadataAdd(md, PS_LIST_TAIL, "warp_id", PS_DATA_S64, "fkey(warp_id, skycell_id, tess_id) ref warpSkyfile(warp_id, skycell_id, tess_id)", 0)) {
    1044310488        psError(PS_ERR_UNKNOWN, false, "failed to add item warp_id");
    1044410489        psFree(md);
    1044510490        return false;
    1044610491    }
    10447     if (!psMetadataAdd(md, PS_LIST_TAIL, "skycell_id", PS_DATA_STRING, "Primary Key", "64")) {
     10492    if (!psMetadataAdd(md, PS_LIST_TAIL, "skycell_id", PS_DATA_STRING, "Key", "64")) {
    1044810493        psError(PS_ERR_UNKNOWN, false, "failed to add item skycell_id");
    1044910494        psFree(md);
    1045010495        return false;
    1045110496    }
    10452     if (!psMetadataAdd(md, PS_LIST_TAIL, "tess_id", PS_DATA_STRING, "Primary Key", "64")) {
     10497    if (!psMetadataAdd(md, PS_LIST_TAIL, "tess_id", PS_DATA_STRING, "Key", "64")) {
    1045310498        psError(PS_ERR_UNKNOWN, false, "failed to add item tess_id");
    1045410499        psFree(md);
     
    1046010505        return false;
    1046110506    }
    10462     if (!psMetadataAdd(md, PS_LIST_TAIL, "template", PS_DATA_BOOL, NULL, 0)) {
    10463         psError(PS_ERR_UNKNOWN, false, "failed to add item template");
    10464         psFree(md);
    10465         return false;
    10466     }
    1046710507
    1046810508    bool status = psDBCreateTable(dbh, DIFFINPUTSKYFILE_TABLE_NAME, md);
     
    1047810518}
    1047910519
    10480 bool diffInputSkyfileInsert(psDB * dbh, psS64 diff_id, psS64 warp_id, const char *skycell_id, const char *tess_id, const char *kind, bool template)
     10520bool diffInputSkyfileInsert(psDB * dbh, psS64 diff_id, bool template, psS64 stack_id, psS64 warp_id, const char *skycell_id, const char *tess_id, const char *kind)
    1048110521{
    1048210522    psMetadata *md = psMetadataAlloc();
     
    1048610526        return false;
    1048710527    }
     10528    if (!psMetadataAdd(md, PS_LIST_TAIL, "template", PS_DATA_BOOL, NULL, template)) {
     10529        psError(PS_ERR_UNKNOWN, false, "failed to add item template");
     10530        psFree(md);
     10531        return false;
     10532    }
     10533    if (!psMetadataAdd(md, PS_LIST_TAIL, "stack_id", PS_DATA_S64, NULL, stack_id)) {
     10534        psError(PS_ERR_UNKNOWN, false, "failed to add item stack_id");
     10535        psFree(md);
     10536        return false;
     10537    }
    1048810538    if (!psMetadataAdd(md, PS_LIST_TAIL, "warp_id", PS_DATA_S64, NULL, warp_id)) {
    1048910539        psError(PS_ERR_UNKNOWN, false, "failed to add item warp_id");
     
    1050310553    if (!psMetadataAdd(md, PS_LIST_TAIL, "kind", PS_DATA_STRING, NULL, kind)) {
    1050410554        psError(PS_ERR_UNKNOWN, false, "failed to add item kind");
    10505         psFree(md);
    10506         return false;
    10507     }
    10508     if (!psMetadataAdd(md, PS_LIST_TAIL, "template", PS_DATA_BOOL, NULL, template)) {
    10509         psError(PS_ERR_UNKNOWN, false, "failed to add item template");
    1051010555        psFree(md);
    1051110556        return false;
     
    1053410579bool diffInputSkyfileInsertObject(psDB *dbh, diffInputSkyfileRow *object)
    1053510580{
    10536     return diffInputSkyfileInsert(dbh, object->diff_id, object->warp_id, object->skycell_id, object->tess_id, object->kind, object->template);
     10581    return diffInputSkyfileInsert(dbh, object->diff_id, object->template, object->stack_id, object->warp_id, object->skycell_id, object->tess_id, object->kind);
    1053710582}
    1053810583
     
    1061210657        return false;
    1061310658    }
     10659    if (!psMetadataAdd(md, PS_LIST_TAIL, "template", PS_DATA_BOOL, NULL, object->template)) {
     10660        psError(PS_ERR_UNKNOWN, false, "failed to add item template");
     10661        psFree(md);
     10662        return false;
     10663    }
     10664    if (!psMetadataAdd(md, PS_LIST_TAIL, "stack_id", PS_DATA_S64, NULL, object->stack_id)) {
     10665        psError(PS_ERR_UNKNOWN, false, "failed to add item stack_id");
     10666        psFree(md);
     10667        return false;
     10668    }
    1061410669    if (!psMetadataAdd(md, PS_LIST_TAIL, "warp_id", PS_DATA_S64, NULL, object->warp_id)) {
    1061510670        psError(PS_ERR_UNKNOWN, false, "failed to add item warp_id");
     
    1063210687        return false;
    1063310688    }
    10634     if (!psMetadataAdd(md, PS_LIST_TAIL, "template", PS_DATA_BOOL, NULL, object->template)) {
    10635         psError(PS_ERR_UNKNOWN, false, "failed to add item template");
    10636         psFree(md);
    10637         return false;
    10638     }
    1063910689
    1064010690
     
    1065110701        return false;
    1065210702    }
     10703    bool template = psMetadataLookupBool(&status, md, "template");
     10704    if (!status) {
     10705        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item template");
     10706        return false;
     10707    }
     10708    psS64 stack_id = psMetadataLookupS64(&status, md, "stack_id");
     10709    if (!status) {
     10710        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stack_id");
     10711        return false;
     10712    }
    1065310713    psS64 warp_id = psMetadataLookupS64(&status, md, "warp_id");
    1065410714    if (!status) {
     
    1067110731        return false;
    1067210732    }
    10673     bool template = psMetadataLookupBool(&status, md, "template");
    10674     if (!status) {
    10675         psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item template");
    10676         return false;
    10677     }
    10678 
    10679     return diffInputSkyfileRowAlloc(diff_id, warp_id, skycell_id, tess_id, kind, template);
     10733
     10734    return diffInputSkyfileRowAlloc(diff_id, template, stack_id, warp_id, skycell_id, tess_id, kind);
    1068010735}
    1068110736psArray *diffInputSkyfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    1078910844static void diffSkyfileRowFree(diffSkyfileRow *object);
    1079010845
    10791 diffSkyfileRow *diffSkyfileRowAlloc(psS64 diff_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev)
     10846diffSkyfileRow *diffSkyfileRowAlloc(psS64 diff_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev, psF64 good_frac, psS16 fault)
    1079210847{
    1079310848    diffSkyfileRow  *_object;
     
    1080110856    _object->bg = bg;
    1080210857    _object->bg_stdev = bg_stdev;
     10858    _object->good_frac = good_frac;
     10859    _object->fault = fault;
    1080310860
    1080410861    return _object;
     
    1083910896        return false;
    1084010897    }
     10898    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, "Key", 0.0)) {
     10899        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     10900        psFree(md);
     10901        return false;
     10902    }
     10903    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, "Key", 0)) {
     10904        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     10905        psFree(md);
     10906        return false;
     10907    }
    1084110908
    1084210909    bool status = psDBCreateTable(dbh, DIFFSKYFILE_TABLE_NAME, md);
     
    1085210919}
    1085310920
    10854 bool diffSkyfileInsert(psDB * dbh, psS64 diff_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev)
     10921bool diffSkyfileInsert(psDB * dbh, psS64 diff_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev, psF64 good_frac, psS16 fault)
    1085510922{
    1085610923    psMetadata *md = psMetadataAlloc();
     
    1087710944    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_stdev", PS_DATA_F64, NULL, bg_stdev)) {
    1087810945        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
     10946        psFree(md);
     10947        return false;
     10948    }
     10949    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, NULL, good_frac)) {
     10950        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     10951        psFree(md);
     10952        return false;
     10953    }
     10954    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, fault)) {
     10955        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
    1087910956        psFree(md);
    1088010957        return false;
     
    1090310980bool diffSkyfileInsertObject(psDB *dbh, diffSkyfileRow *object)
    1090410981{
    10905     return diffSkyfileInsert(dbh, object->diff_id, object->uri, object->path_base, object->bg, object->bg_stdev);
     10982    return diffSkyfileInsert(dbh, object->diff_id, object->uri, object->path_base, object->bg, object->bg_stdev, object->good_frac, object->fault);
    1090610983}
    1090710984
     
    1100111078        return false;
    1100211079    }
     11080    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, NULL, object->good_frac)) {
     11081        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     11082        psFree(md);
     11083        return false;
     11084    }
     11085    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, object->fault)) {
     11086        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     11087        psFree(md);
     11088        return false;
     11089    }
    1100311090
    1100411091
     
    1103511122        return false;
    1103611123    }
    11037 
    11038     return diffSkyfileRowAlloc(diff_id, uri, path_base, bg, bg_stdev);
     11124    psF64 good_frac = psMetadataLookupF64(&status, md, "good_frac");
     11125    if (!status) {
     11126        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item good_frac");
     11127        return false;
     11128    }
     11129    psS16 fault = psMetadataLookupS16(&status, md, "fault");
     11130    if (!status) {
     11131        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fault");
     11132        return false;
     11133    }
     11134
     11135    return diffSkyfileRowAlloc(diff_id, uri, path_base, bg, bg_stdev, good_frac, fault);
    1103911136}
    1104011137psArray *diffSkyfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    1184711944static void stackSumSkyfileRowFree(stackSumSkyfileRow *object);
    1184811945
    11849 stackSumSkyfileRow *stackSumSkyfileRowAlloc(psS64 stack_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev)
     11946stackSumSkyfileRow *stackSumSkyfileRowAlloc(psS64 stack_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev, psF64 good_frac, psS16 fault)
    1185011947{
    1185111948    stackSumSkyfileRow *_object;
     
    1185911956    _object->bg = bg;
    1186011957    _object->bg_stdev = bg_stdev;
     11958    _object->good_frac = good_frac;
     11959    _object->fault = fault;
    1186111960
    1186211961    return _object;
     
    1189711996        return false;
    1189811997    }
     11998    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, "Key", 0.0)) {
     11999        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     12000        psFree(md);
     12001        return false;
     12002    }
     12003    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, "Key", 0)) {
     12004        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     12005        psFree(md);
     12006        return false;
     12007    }
    1189912008
    1190012009    bool status = psDBCreateTable(dbh, STACKSUMSKYFILE_TABLE_NAME, md);
     
    1191012019}
    1191112020
    11912 bool stackSumSkyfileInsert(psDB * dbh, psS64 stack_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev)
     12021bool stackSumSkyfileInsert(psDB * dbh, psS64 stack_id, const char *uri, const char *path_base, psF64 bg, psF64 bg_stdev, psF64 good_frac, psS16 fault)
    1191312022{
    1191412023    psMetadata *md = psMetadataAlloc();
     
    1193512044    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_stdev", PS_DATA_F64, NULL, bg_stdev)) {
    1193612045        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
     12046        psFree(md);
     12047        return false;
     12048    }
     12049    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, NULL, good_frac)) {
     12050        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     12051        psFree(md);
     12052        return false;
     12053    }
     12054    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, fault)) {
     12055        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
    1193712056        psFree(md);
    1193812057        return false;
     
    1196112080bool stackSumSkyfileInsertObject(psDB *dbh, stackSumSkyfileRow *object)
    1196212081{
    11963     return stackSumSkyfileInsert(dbh, object->stack_id, object->uri, object->path_base, object->bg, object->bg_stdev);
     12082    return stackSumSkyfileInsert(dbh, object->stack_id, object->uri, object->path_base, object->bg, object->bg_stdev, object->good_frac, object->fault);
    1196412083}
    1196512084
     
    1205912178        return false;
    1206012179    }
     12180    if (!psMetadataAdd(md, PS_LIST_TAIL, "good_frac", PS_DATA_F64, NULL, object->good_frac)) {
     12181        psError(PS_ERR_UNKNOWN, false, "failed to add item good_frac");
     12182        psFree(md);
     12183        return false;
     12184    }
     12185    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, object->fault)) {
     12186        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     12187        psFree(md);
     12188        return false;
     12189    }
    1206112190
    1206212191
     
    1209312222        return false;
    1209412223    }
    12095 
    12096     return stackSumSkyfileRowAlloc(stack_id, uri, path_base, bg, bg_stdev);
     12224    psF64 good_frac = psMetadataLookupF64(&status, md, "good_frac");
     12225    if (!status) {
     12226        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item good_frac");
     12227        return false;
     12228    }
     12229    psS16 fault = psMetadataLookupS16(&status, md, "fault");
     12230    if (!status) {
     12231        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fault");
     12232        return false;
     12233    }
     12234
     12235    return stackSumSkyfileRowAlloc(stack_id, uri, path_base, bg, bg_stdev, good_frac, fault);
    1209712236}
    1209812237psArray *stackSumSkyfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    1227412413        return false;
    1227512414    }
    12276     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Key", 0)) {
     12415    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Key INDEX(det_id, iteration)", 0)) {
    1227712416        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1227812417        psFree(md);
     
    1310513244{
    1310613245    psMetadata *md = psMetadataAlloc();
    13107     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     13246    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id) ref detRun(det_id)", 0)) {
    1310813247        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1310913248        psFree(md);
    1311013249        return false;
    1311113250    }
    13112     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     13251    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(exp_id) ref rawExp(exp_id)", 0)) {
    1311313252        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1311413253        psFree(md);
    1311513254        return false;
    1311613255    }
    13117     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key", 64)) {
     13256    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key INDEX(det_id, exp_id)", 64)) {
    1311813257        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1311913258        psFree(md);
    1312013259        return false;
    1312113260    }
    13122     if (!psMetadataAdd(md, PS_LIST_TAIL, "include", PS_DATA_BOOL, NULL, 0)) {
     13261    if (!psMetadataAdd(md, PS_LIST_TAIL, "include", PS_DATA_BOOL, "INDEX(det_id, iteration)", 0)) {
    1312313262        psError(PS_ERR_UNKNOWN, false, "failed to add item include");
    1312413263        psFree(md);
     
    1345913598{
    1346013599    psMetadata *md = psMetadataAlloc();
    13461     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     13600    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, exp_id) ref detInputExp(det_id, exp_id)", 0)) {
    1346213601        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1346313602        psFree(md);
    1346413603        return false;
    1346513604    }
    13466     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key", 64)) {
     13605    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey(exp_id, class_id) ref rawImfile(exp_id, class_id)", 64)) {
    1346713606        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1346813607        psFree(md);
    1346913608        return false;
    1347013609    }
    13471     if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     13610    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key INDEX(det_id, class_id)", "64")) {
    1347213611        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    1347313612        psFree(md);
    1347413613        return false;
    1347513614    }
    13476     if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     13615    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, "INDEX(det_id, exp_id)", "255")) {
    1347713616        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
    1347813617        psFree(md);
     
    1408914228{
    1409014229    psMetadata *md = psMetadataAlloc();
    14091     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     14230    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, exp_id) ref detInputExp(det_id, exp_id)", 0)) {
    1409214231        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1409314232        psFree(md);
    1409414233        return false;
    1409514234    }
    14096     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key", 64)) {
     14235    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey(det_id, exp_id) ref detProcessedImfile(det_id, exp_id)", 64)) {
    1409714236        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1409814237        psFree(md);
     
    1467814817{
    1467914818    psMetadata *md = psMetadataAlloc();
    14680     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     14819    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration) ref detInputExp(det_id, iteration)", 0)) {
    1468114820        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1468214821        psFree(md);
    1468314822        return false;
    1468414823    }
    14685     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     14824    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, class_id) ref detProcessedImfile(det_id, class_id)", 0)) {
    1468614825        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1468714826        psFree(md);
     
    1521615355{
    1521715356    psMetadata *md = psMetadataAlloc();
    15218     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     15357    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration) ref detInputExp(det_id, iteration)", 0)) {
    1521915358        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1522015359        psFree(md);
    1522115360        return false;
    1522215361    }
    15223     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     15362    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, iteration, class_id) ref detStackedImfile(det_id, iteration, class_id)", 0)) {
    1522415363        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1522515364        psFree(md);
     
    1558515724{
    1558615725    psMetadata *md = psMetadataAlloc();
    15587     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     15726    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id) ref detInputExp(det_id)", 0)) {
    1558815727        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1558915728        psFree(md);
    1559015729        return false;
    1559115730    }
    15592     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     15731    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, iteration, class_id) ref detNormalizedStatImfile(det_id, iteration, class_id)", 0)) {
    1559315732        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1559415733        psFree(md);
    1559515734        return false;
    1559615735    }
    15597     if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     15736    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key INDEX(det_id, iteration)", "64")) {
    1559815737        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    1559915738        psFree(md);
     
    1613216271{
    1613316272    psMetadata *md = psMetadataAlloc();
    16134     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     16273    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration) ref detInputExp(det_id, iteration)", 0)) {
    1613516274        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1613616275        psFree(md);
    1613716276        return false;
    1613816277    }
    16139     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     16278    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, iteration) ref detNormalizedImfile(det_id, iteration)", 0)) {
    1614016279        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1614116280        psFree(md);
     
    1662616765static void detResidImfileRowFree(detResidImfileRow *object);
    1662716766
    16628 detResidImfileRow *detResidImfileRowAlloc(psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, psS16 fault)
     16767detResidImfileRow *detResidImfileRowAlloc(psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bg_skewness, psF64 bg_kurtosis, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 fringe_resid_0, psF64 fringe_resid_1, psF64 fringe_resid_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, psS16 fault)
    1662916768{
    1663016769    detResidImfileRow *_object;
     
    1664216781    _object->bg_stdev = bg_stdev;
    1664316782    _object->bg_mean_stdev = bg_mean_stdev;
     16783    _object->bg_skewness = bg_skewness;
     16784    _object->bg_kurtosis = bg_kurtosis;
    1664416785    _object->bin_stdev = bin_stdev;
    1664516786    _object->fringe_0 = fringe_0;
    1664616787    _object->fringe_1 = fringe_1;
    1664716788    _object->fringe_2 = fringe_2;
     16789    _object->fringe_resid_0 = fringe_resid_0;
     16790    _object->fringe_resid_1 = fringe_resid_1;
     16791    _object->fringe_resid_2 = fringe_resid_2;
    1664816792    _object->user_1 = user_1;
    1664916793    _object->user_2 = user_2;
     
    1666816812{
    1666916813    psMetadata *md = psMetadataAlloc();
    16670     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     16814    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration, exp_id) ref detInputExp(det_id, iteration, exp_id)", 0)) {
    1667116815        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1667216816        psFree(md);
    1667316817        return false;
    1667416818    }
    16675     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     16819    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, exp_id, class_id) ref detProcessedImfile(det_id, exp_id, class_id)", 0)) {
    1667616820        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1667716821        psFree(md);
    1667816822        return false;
    1667916823    }
    16680     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key", 64)) {
     16824    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration) ref detNormalizedExp(det_id, iteration)", 64)) {
    1668116825        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1668216826        psFree(md);
    1668316827        return false;
    1668416828    }
    16685     if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     16829    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key INDEX(det_id, iteration, exp_id)", "64")) {
    1668616830        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
    1668716831        psFree(md);
     
    1671316857        return false;
    1671416858    }
     16859    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_skewness", PS_DATA_F64, NULL, 0.0)) {
     16860        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_skewness");
     16861        psFree(md);
     16862        return false;
     16863    }
     16864    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_kurtosis", PS_DATA_F64, NULL, 0.0)) {
     16865        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_kurtosis");
     16866        psFree(md);
     16867        return false;
     16868    }
    1671516869    if (!psMetadataAdd(md, PS_LIST_TAIL, "bin_stdev", PS_DATA_F64, NULL, 0.0)) {
    1671616870        psError(PS_ERR_UNKNOWN, false, "failed to add item bin_stdev");
     
    1673316887        return false;
    1673416888    }
     16889    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_0", PS_DATA_F64, NULL, 0.0)) {
     16890        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_0");
     16891        psFree(md);
     16892        return false;
     16893    }
     16894    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_1", PS_DATA_F64, NULL, 0.0)) {
     16895        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_1");
     16896        psFree(md);
     16897        return false;
     16898    }
     16899    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_2", PS_DATA_F64, NULL, 0.0)) {
     16900        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_2");
     16901        psFree(md);
     16902        return false;
     16903    }
    1673516904    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, 0.0)) {
    1673616905        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     
    1678116950}
    1678216951
    16783 bool detResidImfileInsert(psDB * dbh, psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, psS16 fault)
     16952bool detResidImfileInsert(psDB * dbh, psS64 det_id, psS32 iteration, psS64 exp_id, const char *class_id, const char *uri, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bg_skewness, psF64 bg_kurtosis, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 fringe_resid_0, psF64 fringe_resid_1, psF64 fringe_resid_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, psS16 fault)
    1678416953{
    1678516954    psMetadata *md = psMetadataAlloc();
     
    1682916998        return false;
    1683016999    }
     17000    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_skewness", PS_DATA_F64, NULL, bg_skewness)) {
     17001        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_skewness");
     17002        psFree(md);
     17003        return false;
     17004    }
     17005    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_kurtosis", PS_DATA_F64, NULL, bg_kurtosis)) {
     17006        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_kurtosis");
     17007        psFree(md);
     17008        return false;
     17009    }
    1683117010    if (!psMetadataAdd(md, PS_LIST_TAIL, "bin_stdev", PS_DATA_F64, NULL, bin_stdev)) {
    1683217011        psError(PS_ERR_UNKNOWN, false, "failed to add item bin_stdev");
     
    1684617025    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_2", PS_DATA_F64, NULL, fringe_2)) {
    1684717026        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_2");
     17027        psFree(md);
     17028        return false;
     17029    }
     17030    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_0", PS_DATA_F64, NULL, fringe_resid_0)) {
     17031        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_0");
     17032        psFree(md);
     17033        return false;
     17034    }
     17035    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_1", PS_DATA_F64, NULL, fringe_resid_1)) {
     17036        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_1");
     17037        psFree(md);
     17038        return false;
     17039    }
     17040    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_2", PS_DATA_F64, NULL, fringe_resid_2)) {
     17041        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_2");
    1684817042        psFree(md);
    1684917043        return false;
     
    1690717101bool detResidImfileInsertObject(psDB *dbh, detResidImfileRow *object)
    1690817102{
    16909     return detResidImfileInsert(dbh, object->det_id, object->iteration, object->exp_id, object->class_id, object->uri, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev, object->bin_stdev, object->fringe_0, object->fringe_1, object->fringe_2, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->path_base, object->fault);
     17103    return detResidImfileInsert(dbh, object->det_id, object->iteration, object->exp_id, object->class_id, object->uri, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev, object->bg_skewness, object->bg_kurtosis, object->bin_stdev, object->fringe_0, object->fringe_1, object->fringe_2, object->fringe_resid_0, object->fringe_resid_1, object->fringe_resid_2, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->path_base, object->fault);
    1691017104}
    1691117105
     
    1702517219        return false;
    1702617220    }
     17221    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_skewness", PS_DATA_F64, NULL, object->bg_skewness)) {
     17222        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_skewness");
     17223        psFree(md);
     17224        return false;
     17225    }
     17226    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_kurtosis", PS_DATA_F64, NULL, object->bg_kurtosis)) {
     17227        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_kurtosis");
     17228        psFree(md);
     17229        return false;
     17230    }
    1702717231    if (!psMetadataAdd(md, PS_LIST_TAIL, "bin_stdev", PS_DATA_F64, NULL, object->bin_stdev)) {
    1702817232        psError(PS_ERR_UNKNOWN, false, "failed to add item bin_stdev");
     
    1704517249        return false;
    1704617250    }
     17251    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_0", PS_DATA_F64, NULL, object->fringe_resid_0)) {
     17252        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_0");
     17253        psFree(md);
     17254        return false;
     17255    }
     17256    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_1", PS_DATA_F64, NULL, object->fringe_resid_1)) {
     17257        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_1");
     17258        psFree(md);
     17259        return false;
     17260    }
     17261    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_2", PS_DATA_F64, NULL, object->fringe_resid_2)) {
     17262        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_2");
     17263        psFree(md);
     17264        return false;
     17265    }
    1704717266    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, object->user_1)) {
    1704817267        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     
    1713417353        return false;
    1713517354    }
     17355    psF64 bg_skewness = psMetadataLookupF64(&status, md, "bg_skewness");
     17356    if (!status) {
     17357        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_skewness");
     17358        return false;
     17359    }
     17360    psF64 bg_kurtosis = psMetadataLookupF64(&status, md, "bg_kurtosis");
     17361    if (!status) {
     17362        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_kurtosis");
     17363        return false;
     17364    }
    1713617365    psF64 bin_stdev = psMetadataLookupF64(&status, md, "bin_stdev");
    1713717366    if (!status) {
     
    1715417383        return false;
    1715517384    }
     17385    psF64 fringe_resid_0 = psMetadataLookupF64(&status, md, "fringe_resid_0");
     17386    if (!status) {
     17387        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fringe_resid_0");
     17388        return false;
     17389    }
     17390    psF64 fringe_resid_1 = psMetadataLookupF64(&status, md, "fringe_resid_1");
     17391    if (!status) {
     17392        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fringe_resid_1");
     17393        return false;
     17394    }
     17395    psF64 fringe_resid_2 = psMetadataLookupF64(&status, md, "fringe_resid_2");
     17396    if (!status) {
     17397        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fringe_resid_2");
     17398        return false;
     17399    }
    1715617400    psF64 user_1 = psMetadataLookupF64(&status, md, "user_1");
    1715717401    if (!status) {
     
    1719017434    }
    1719117435
    17192     return detResidImfileRowAlloc(det_id, iteration, exp_id, class_id, uri, recipe, bg, bg_stdev, bg_mean_stdev, bin_stdev, fringe_0, fringe_1, fringe_2, user_1, user_2, user_3, user_4, user_5, path_base, fault);
     17436    return detResidImfileRowAlloc(det_id, iteration, exp_id, class_id, uri, recipe, bg, bg_stdev, bg_mean_stdev, bg_skewness, bg_kurtosis, bin_stdev, fringe_0, fringe_1, fringe_2, fringe_resid_0, fringe_resid_1, fringe_resid_2, user_1, user_2, user_3, user_4, user_5, path_base, fault);
    1719317437}
    1719417438psArray *detResidImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    1730217546static void detResidExpRowFree(detResidExpRow *object);
    1730317547
    17304 detResidExpRow *detResidExpRowAlloc(psS64 det_id, psS32 iteration, psS64 exp_id, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, bool accept, psS16 fault)
     17548detResidExpRow *detResidExpRowAlloc(psS64 det_id, psS32 iteration, psS64 exp_id, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bg_skewness, psF64 bg_kurtosis, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 fringe_resid_0, psF64 fringe_resid_1, psF64 fringe_resid_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, bool accept, psS16 fault)
    1730517549{
    1730617550    detResidExpRow  *_object;
     
    1731617560    _object->bg_stdev = bg_stdev;
    1731717561    _object->bg_mean_stdev = bg_mean_stdev;
     17562    _object->bg_skewness = bg_skewness;
     17563    _object->bg_kurtosis = bg_kurtosis;
    1731817564    _object->bin_stdev = bin_stdev;
    1731917565    _object->fringe_0 = fringe_0;
    1732017566    _object->fringe_1 = fringe_1;
    1732117567    _object->fringe_2 = fringe_2;
     17568    _object->fringe_resid_0 = fringe_resid_0;
     17569    _object->fringe_resid_1 = fringe_resid_1;
     17570    _object->fringe_resid_2 = fringe_resid_2;
    1732217571    _object->user_1 = user_1;
    1732317572    _object->user_2 = user_2;
     
    1734117590{
    1734217591    psMetadata *md = psMetadataAlloc();
    17343     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     17592    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration, exp_id) ref detInputExp(det_id, iteration, exp_id)", 0)) {
    1734417593        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1734517594        psFree(md);
    1734617595        return false;
    1734717596    }
    17348     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     17597    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, iteration, exp_id) ref detResidImfile(det_id, iteration, exp_id)", 0)) {
    1734917598        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1735017599        psFree(md);
    1735117600        return false;
    1735217601    }
    17353     if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key", 64)) {
     17602    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key INDEX(det_id, iteration)", 64)) {
    1735417603        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
    1735517604        psFree(md);
     
    1737617625        return false;
    1737717626    }
     17627    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_skewness", PS_DATA_F64, NULL, 0.0)) {
     17628        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_skewness");
     17629        psFree(md);
     17630        return false;
     17631    }
     17632    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_kurtosis", PS_DATA_F64, NULL, 0.0)) {
     17633        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_kurtosis");
     17634        psFree(md);
     17635        return false;
     17636    }
    1737817637    if (!psMetadataAdd(md, PS_LIST_TAIL, "bin_stdev", PS_DATA_F64, NULL, 0.0)) {
    1737917638        psError(PS_ERR_UNKNOWN, false, "failed to add item bin_stdev");
     
    1739617655        return false;
    1739717656    }
     17657    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_0", PS_DATA_F64, NULL, 0.0)) {
     17658        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_0");
     17659        psFree(md);
     17660        return false;
     17661    }
     17662    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_1", PS_DATA_F64, NULL, 0.0)) {
     17663        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_1");
     17664        psFree(md);
     17665        return false;
     17666    }
     17667    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_2", PS_DATA_F64, NULL, 0.0)) {
     17668        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_2");
     17669        psFree(md);
     17670        return false;
     17671    }
    1739817672    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, 0.0)) {
    1739917673        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     
    1744917723}
    1745017724
    17451 bool detResidExpInsert(psDB * dbh, psS64 det_id, psS32 iteration, psS64 exp_id, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, bool accept, psS16 fault)
     17725bool detResidExpInsert(psDB * dbh, psS64 det_id, psS32 iteration, psS64 exp_id, const char *recipe, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 bg_skewness, psF64 bg_kurtosis, psF64 bin_stdev, psF64 fringe_0, psF64 fringe_1, psF64 fringe_2, psF64 fringe_resid_0, psF64 fringe_resid_1, psF64 fringe_resid_2, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, bool accept, psS16 fault)
    1745217726{
    1745317727    psMetadata *md = psMetadataAlloc();
     
    1748717761        return false;
    1748817762    }
     17763    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_skewness", PS_DATA_F64, NULL, bg_skewness)) {
     17764        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_skewness");
     17765        psFree(md);
     17766        return false;
     17767    }
     17768    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_kurtosis", PS_DATA_F64, NULL, bg_kurtosis)) {
     17769        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_kurtosis");
     17770        psFree(md);
     17771        return false;
     17772    }
    1748917773    if (!psMetadataAdd(md, PS_LIST_TAIL, "bin_stdev", PS_DATA_F64, NULL, bin_stdev)) {
    1749017774        psError(PS_ERR_UNKNOWN, false, "failed to add item bin_stdev");
     
    1750417788    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_2", PS_DATA_F64, NULL, fringe_2)) {
    1750517789        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_2");
     17790        psFree(md);
     17791        return false;
     17792    }
     17793    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_0", PS_DATA_F64, NULL, fringe_resid_0)) {
     17794        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_0");
     17795        psFree(md);
     17796        return false;
     17797    }
     17798    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_1", PS_DATA_F64, NULL, fringe_resid_1)) {
     17799        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_1");
     17800        psFree(md);
     17801        return false;
     17802    }
     17803    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_2", PS_DATA_F64, NULL, fringe_resid_2)) {
     17804        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_2");
    1750617805        psFree(md);
    1750717806        return false;
     
    1757017869bool detResidExpInsertObject(psDB *dbh, detResidExpRow *object)
    1757117870{
    17572     return detResidExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev, object->bin_stdev, object->fringe_0, object->fringe_1, object->fringe_2, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->path_base, object->accept, object->fault);
     17871    return detResidExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->recipe, object->bg, object->bg_stdev, object->bg_mean_stdev, object->bg_skewness, object->bg_kurtosis, object->bin_stdev, object->fringe_0, object->fringe_1, object->fringe_2, object->fringe_resid_0, object->fringe_resid_1, object->fringe_resid_2, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->path_base, object->accept, object->fault);
    1757317872}
    1757417873
     
    1767817977        return false;
    1767917978    }
     17979    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_skewness", PS_DATA_F64, NULL, object->bg_skewness)) {
     17980        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_skewness");
     17981        psFree(md);
     17982        return false;
     17983    }
     17984    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_kurtosis", PS_DATA_F64, NULL, object->bg_kurtosis)) {
     17985        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_kurtosis");
     17986        psFree(md);
     17987        return false;
     17988    }
    1768017989    if (!psMetadataAdd(md, PS_LIST_TAIL, "bin_stdev", PS_DATA_F64, NULL, object->bin_stdev)) {
    1768117990        psError(PS_ERR_UNKNOWN, false, "failed to add item bin_stdev");
     
    1769818007        return false;
    1769918008    }
     18009    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_0", PS_DATA_F64, NULL, object->fringe_resid_0)) {
     18010        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_0");
     18011        psFree(md);
     18012        return false;
     18013    }
     18014    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_1", PS_DATA_F64, NULL, object->fringe_resid_1)) {
     18015        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_1");
     18016        psFree(md);
     18017        return false;
     18018    }
     18019    if (!psMetadataAdd(md, PS_LIST_TAIL, "fringe_resid_2", PS_DATA_F64, NULL, object->fringe_resid_2)) {
     18020        psError(PS_ERR_UNKNOWN, false, "failed to add item fringe_resid_2");
     18021        psFree(md);
     18022        return false;
     18023    }
    1770018024    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, object->user_1)) {
    1770118025        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     
    1778218106        return false;
    1778318107    }
     18108    psF64 bg_skewness = psMetadataLookupF64(&status, md, "bg_skewness");
     18109    if (!status) {
     18110        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_skewness");
     18111        return false;
     18112    }
     18113    psF64 bg_kurtosis = psMetadataLookupF64(&status, md, "bg_kurtosis");
     18114    if (!status) {
     18115        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_kurtosis");
     18116        return false;
     18117    }
    1778418118    psF64 bin_stdev = psMetadataLookupF64(&status, md, "bin_stdev");
    1778518119    if (!status) {
     
    1780218136        return false;
    1780318137    }
     18138    psF64 fringe_resid_0 = psMetadataLookupF64(&status, md, "fringe_resid_0");
     18139    if (!status) {
     18140        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fringe_resid_0");
     18141        return false;
     18142    }
     18143    psF64 fringe_resid_1 = psMetadataLookupF64(&status, md, "fringe_resid_1");
     18144    if (!status) {
     18145        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fringe_resid_1");
     18146        return false;
     18147    }
     18148    psF64 fringe_resid_2 = psMetadataLookupF64(&status, md, "fringe_resid_2");
     18149    if (!status) {
     18150        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fringe_resid_2");
     18151        return false;
     18152    }
    1780418153    psF64 user_1 = psMetadataLookupF64(&status, md, "user_1");
    1780518154    if (!status) {
     
    1784318192    }
    1784418193
    17845     return detResidExpRowAlloc(det_id, iteration, exp_id, recipe, bg, bg_stdev, bg_mean_stdev, bin_stdev, fringe_0, fringe_1, fringe_2, user_1, user_2, user_3, user_4, user_5, path_base, accept, fault);
     18194    return detResidExpRowAlloc(det_id, iteration, exp_id, recipe, bg, bg_stdev, bg_mean_stdev, bg_skewness, bg_kurtosis, bin_stdev, fringe_0, fringe_1, fringe_2, fringe_resid_0, fringe_resid_1, fringe_resid_2, user_1, user_2, user_3, user_4, user_5, path_base, accept, fault);
    1784618195}
    1784718196psArray *detResidExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     
    1798018329{
    1798118330    psMetadata *md = psMetadataAlloc();
    17982     if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key", 0)) {
     18331    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration) ref detInputExp(det_id, iteration)", 0)) {
    1798318332        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
    1798418333        psFree(md);
    1798518334        return false;
    1798618335    }
    17987     if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     18336    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key fkey(det_id, iteration) ref detResidExp(det_id, iteration)", 0)) {
    1798818337        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
    1798918338        psFree(md);
     
    1835218701    return true;
    1835318702}
     18703static void detRegisteredImfileRowFree(detRegisteredImfileRow *object);
     18704
     18705detRegisteredImfileRow *detRegisteredImfileRowAlloc(psS64 det_id, psS32 iteration, const char *class_id, const char *uri, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, psS16 fault)
     18706{
     18707    detRegisteredImfileRow *_object;
     18708
     18709    _object = psAlloc(sizeof(detRegisteredImfileRow));
     18710    psMemSetDeallocator(_object, (psFreeFunc)detRegisteredImfileRowFree);
     18711
     18712    _object->det_id = det_id;
     18713    _object->iteration = iteration;
     18714    _object->class_id = psStringCopy(class_id);
     18715    _object->uri = psStringCopy(uri);
     18716    _object->bg = bg;
     18717    _object->bg_stdev = bg_stdev;
     18718    _object->bg_mean_stdev = bg_mean_stdev;
     18719    _object->user_1 = user_1;
     18720    _object->user_2 = user_2;
     18721    _object->user_3 = user_3;
     18722    _object->user_4 = user_4;
     18723    _object->user_5 = user_5;
     18724    _object->path_base = psStringCopy(path_base);
     18725    _object->fault = fault;
     18726
     18727    return _object;
     18728}
     18729
     18730static void detRegisteredImfileRowFree(detRegisteredImfileRow *object)
     18731{
     18732    psFree(object->class_id);
     18733    psFree(object->uri);
     18734    psFree(object->path_base);
     18735}
     18736
     18737bool detRegisteredImfileCreateTable(psDB *dbh)
     18738{
     18739    psMetadata *md = psMetadataAlloc();
     18740    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, iteration) ref detRun(det_id, iteration)", 0)) {
     18741        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     18742        psFree(md);
     18743        return false;
     18744    }
     18745    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, "Primary Key", 0)) {
     18746        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
     18747        psFree(md);
     18748        return false;
     18749    }
     18750    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     18751        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     18752        psFree(md);
     18753        return false;
     18754    }
     18755    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     18756        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     18757        psFree(md);
     18758        return false;
     18759    }
     18760    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg", PS_DATA_F64, NULL, 0.0)) {
     18761        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
     18762        psFree(md);
     18763        return false;
     18764    }
     18765    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_stdev", PS_DATA_F64, NULL, 0.0)) {
     18766        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
     18767        psFree(md);
     18768        return false;
     18769    }
     18770    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_mean_stdev", PS_DATA_F64, NULL, 0.0)) {
     18771        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
     18772        psFree(md);
     18773        return false;
     18774    }
     18775    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, 0.0)) {
     18776        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     18777        psFree(md);
     18778        return false;
     18779    }
     18780    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_2", PS_DATA_F64, NULL, 0.0)) {
     18781        psError(PS_ERR_UNKNOWN, false, "failed to add item user_2");
     18782        psFree(md);
     18783        return false;
     18784    }
     18785    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_3", PS_DATA_F64, NULL, 0.0)) {
     18786        psError(PS_ERR_UNKNOWN, false, "failed to add item user_3");
     18787        psFree(md);
     18788        return false;
     18789    }
     18790    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_4", PS_DATA_F64, NULL, 0.0)) {
     18791        psError(PS_ERR_UNKNOWN, false, "failed to add item user_4");
     18792        psFree(md);
     18793        return false;
     18794    }
     18795    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_5", PS_DATA_F64, NULL, 0.0)) {
     18796        psError(PS_ERR_UNKNOWN, false, "failed to add item user_5");
     18797        psFree(md);
     18798        return false;
     18799    }
     18800    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, "255")) {
     18801        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     18802        psFree(md);
     18803        return false;
     18804    }
     18805    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, "Key NOT NULL", 0)) {
     18806        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     18807        psFree(md);
     18808        return false;
     18809    }
     18810
     18811    bool status = psDBCreateTable(dbh, DETREGISTEREDIMFILE_TABLE_NAME, md);
     18812
     18813    psFree(md);
     18814
     18815    return status;
     18816}
     18817
     18818bool detRegisteredImfileDropTable(psDB *dbh)
     18819{
     18820    return psDBDropTable(dbh, DETREGISTEREDIMFILE_TABLE_NAME);
     18821}
     18822
     18823bool detRegisteredImfileInsert(psDB * dbh, psS64 det_id, psS32 iteration, const char *class_id, const char *uri, psF64 bg, psF64 bg_stdev, psF64 bg_mean_stdev, psF64 user_1, psF64 user_2, psF64 user_3, psF64 user_4, psF64 user_5, const char *path_base, psS16 fault)
     18824{
     18825    psMetadata *md = psMetadataAlloc();
     18826    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, NULL, det_id)) {
     18827        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     18828        psFree(md);
     18829        return false;
     18830    }
     18831    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, NULL, iteration)) {
     18832        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
     18833        psFree(md);
     18834        return false;
     18835    }
     18836    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     18837        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     18838        psFree(md);
     18839        return false;
     18840    }
     18841    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     18842        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     18843        psFree(md);
     18844        return false;
     18845    }
     18846    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg", PS_DATA_F64, NULL, bg)) {
     18847        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
     18848        psFree(md);
     18849        return false;
     18850    }
     18851    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_stdev", PS_DATA_F64, NULL, bg_stdev)) {
     18852        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
     18853        psFree(md);
     18854        return false;
     18855    }
     18856    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_mean_stdev", PS_DATA_F64, NULL, bg_mean_stdev)) {
     18857        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
     18858        psFree(md);
     18859        return false;
     18860    }
     18861    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, user_1)) {
     18862        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     18863        psFree(md);
     18864        return false;
     18865    }
     18866    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_2", PS_DATA_F64, NULL, user_2)) {
     18867        psError(PS_ERR_UNKNOWN, false, "failed to add item user_2");
     18868        psFree(md);
     18869        return false;
     18870    }
     18871    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_3", PS_DATA_F64, NULL, user_3)) {
     18872        psError(PS_ERR_UNKNOWN, false, "failed to add item user_3");
     18873        psFree(md);
     18874        return false;
     18875    }
     18876    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_4", PS_DATA_F64, NULL, user_4)) {
     18877        psError(PS_ERR_UNKNOWN, false, "failed to add item user_4");
     18878        psFree(md);
     18879        return false;
     18880    }
     18881    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_5", PS_DATA_F64, NULL, user_5)) {
     18882        psError(PS_ERR_UNKNOWN, false, "failed to add item user_5");
     18883        psFree(md);
     18884        return false;
     18885    }
     18886    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, path_base)) {
     18887        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     18888        psFree(md);
     18889        return false;
     18890    }
     18891    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, fault)) {
     18892        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     18893        psFree(md);
     18894        return false;
     18895    }
     18896
     18897    bool status = psDBInsertOneRow(dbh, DETREGISTEREDIMFILE_TABLE_NAME, md);
     18898    psFree(md);
     18899
     18900    return status;
     18901}
     18902
     18903long long detRegisteredImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     18904{
     18905    long long       deleted = 0;
     18906
     18907    long long count = psDBDeleteRows(dbh, DETREGISTEREDIMFILE_TABLE_NAME, where, limit);
     18908    if (count < 0) {
     18909        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRegisteredImfile");
     18910        return count;
     18911
     18912        deleted += count;
     18913    }
     18914
     18915    return deleted;
     18916}
     18917bool detRegisteredImfileInsertObject(psDB *dbh, detRegisteredImfileRow *object)
     18918{
     18919    return detRegisteredImfileInsert(dbh, object->det_id, object->iteration, object->class_id, object->uri, object->bg, object->bg_stdev, object->bg_mean_stdev, object->user_1, object->user_2, object->user_3, object->user_4, object->user_5, object->path_base, object->fault);
     18920}
     18921
     18922bool detRegisteredImfileInsertObjects(psDB *dbh, psArray *objects)
     18923{
     18924    for (long i = 0; i < psArrayLength(objects); i++) {
     18925        if (!detRegisteredImfileInsertObject(dbh, objects->data[i])) {
     18926            return false;
     18927        }
     18928    }
     18929
     18930    return true;
     18931}
     18932
     18933bool detRegisteredImfileInsertFits(psDB *dbh, const psFits *fits)
     18934{
     18935    psArray         *rowSet;
     18936
     18937    // move to (the first?) extension named  DETREGISTEREDIMFILE_TABLE_NAME
     18938    if (!psFitsMoveExtName(fits, DETREGISTEREDIMFILE_TABLE_NAME)) {
     18939        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETREGISTEREDIMFILE_TABLE_NAME);
     18940        return false;
     18941    }
     18942
     18943    // check HDU type
     18944    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     18945        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     18946        return false;
     18947    }
     18948
     18949    // read fits table
     18950    rowSet = psFitsReadTable(fits);
     18951    if (!rowSet) {
     18952        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     18953        psFree(rowSet);
     18954        return false;
     18955    }
     18956
     18957    if (!psDBInsertRows(dbh, DETREGISTEREDIMFILE_TABLE_NAME, rowSet)) {
     18958        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     18959        psFree(rowSet);
     18960        return false;
     18961    }
     18962
     18963    psFree(rowSet);
     18964
     18965    return true;
     18966}
     18967
     18968bool detRegisteredImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     18969{
     18970    psArray         *rowSet;
     18971
     18972    rowSet = psDBSelectRows(dbh, DETREGISTEREDIMFILE_TABLE_NAME, where, limit);
     18973    if (!rowSet) {
     18974        return false;
     18975    }
     18976
     18977    // output to fits
     18978    if (!psFitsWriteTable(fits, NULL, rowSet, DETREGISTEREDIMFILE_TABLE_NAME)) {
     18979        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     18980        psFree(rowSet);
     18981        return false;
     18982    }
     18983
     18984    psFree(rowSet);
     18985
     18986    return true;
     18987}
     18988
     18989psMetadata *detRegisteredImfileMetadataFromObject(const detRegisteredImfileRow *object)
     18990{
     18991    psMetadata *md = psMetadataAlloc();
     18992    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, NULL, object->det_id)) {
     18993        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     18994        psFree(md);
     18995        return false;
     18996    }
     18997    if (!psMetadataAdd(md, PS_LIST_TAIL, "iteration", PS_DATA_S32, NULL, object->iteration)) {
     18998        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
     18999        psFree(md);
     19000        return false;
     19001    }
     19002    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     19003        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     19004        psFree(md);
     19005        return false;
     19006    }
     19007    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     19008        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19009        psFree(md);
     19010        return false;
     19011    }
     19012    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg", PS_DATA_F64, NULL, object->bg)) {
     19013        psError(PS_ERR_UNKNOWN, false, "failed to add item bg");
     19014        psFree(md);
     19015        return false;
     19016    }
     19017    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_stdev", PS_DATA_F64, NULL, object->bg_stdev)) {
     19018        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_stdev");
     19019        psFree(md);
     19020        return false;
     19021    }
     19022    if (!psMetadataAdd(md, PS_LIST_TAIL, "bg_mean_stdev", PS_DATA_F64, NULL, object->bg_mean_stdev)) {
     19023        psError(PS_ERR_UNKNOWN, false, "failed to add item bg_mean_stdev");
     19024        psFree(md);
     19025        return false;
     19026    }
     19027    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_1", PS_DATA_F64, NULL, object->user_1)) {
     19028        psError(PS_ERR_UNKNOWN, false, "failed to add item user_1");
     19029        psFree(md);
     19030        return false;
     19031    }
     19032    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_2", PS_DATA_F64, NULL, object->user_2)) {
     19033        psError(PS_ERR_UNKNOWN, false, "failed to add item user_2");
     19034        psFree(md);
     19035        return false;
     19036    }
     19037    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_3", PS_DATA_F64, NULL, object->user_3)) {
     19038        psError(PS_ERR_UNKNOWN, false, "failed to add item user_3");
     19039        psFree(md);
     19040        return false;
     19041    }
     19042    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_4", PS_DATA_F64, NULL, object->user_4)) {
     19043        psError(PS_ERR_UNKNOWN, false, "failed to add item user_4");
     19044        psFree(md);
     19045        return false;
     19046    }
     19047    if (!psMetadataAdd(md, PS_LIST_TAIL, "user_5", PS_DATA_F64, NULL, object->user_5)) {
     19048        psError(PS_ERR_UNKNOWN, false, "failed to add item user_5");
     19049        psFree(md);
     19050        return false;
     19051    }
     19052    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, object->path_base)) {
     19053        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19054        psFree(md);
     19055        return false;
     19056    }
     19057    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, object->fault)) {
     19058        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19059        psFree(md);
     19060        return false;
     19061    }
     19062
     19063
     19064    return md;
     19065}
     19066
     19067detRegisteredImfileRow *detRegisteredImfileObjectFromMetadata(psMetadata *md)
     19068{
     19069
     19070bool status = false;
     19071    psS64 det_id = psMetadataLookupS64(&status, md, "det_id");
     19072    if (!status) {
     19073        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
     19074        return false;
     19075    }
     19076    psS32 iteration = psMetadataLookupS32(&status, md, "iteration");
     19077    if (!status) {
     19078        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
     19079        return false;
     19080    }
     19081    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     19082    if (!status) {
     19083        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     19084        return false;
     19085    }
     19086    char* uri = psMetadataLookupPtr(&status, md, "uri");
     19087    if (!status) {
     19088        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     19089        return false;
     19090    }
     19091    psF64 bg = psMetadataLookupF64(&status, md, "bg");
     19092    if (!status) {
     19093        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg");
     19094        return false;
     19095    }
     19096    psF64 bg_stdev = psMetadataLookupF64(&status, md, "bg_stdev");
     19097    if (!status) {
     19098        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_stdev");
     19099        return false;
     19100    }
     19101    psF64 bg_mean_stdev = psMetadataLookupF64(&status, md, "bg_mean_stdev");
     19102    if (!status) {
     19103        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bg_mean_stdev");
     19104        return false;
     19105    }
     19106    psF64 user_1 = psMetadataLookupF64(&status, md, "user_1");
     19107    if (!status) {
     19108        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item user_1");
     19109        return false;
     19110    }
     19111    psF64 user_2 = psMetadataLookupF64(&status, md, "user_2");
     19112    if (!status) {
     19113        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item user_2");
     19114        return false;
     19115    }
     19116    psF64 user_3 = psMetadataLookupF64(&status, md, "user_3");
     19117    if (!status) {
     19118        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item user_3");
     19119        return false;
     19120    }
     19121    psF64 user_4 = psMetadataLookupF64(&status, md, "user_4");
     19122    if (!status) {
     19123        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item user_4");
     19124        return false;
     19125    }
     19126    psF64 user_5 = psMetadataLookupF64(&status, md, "user_5");
     19127    if (!status) {
     19128        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item user_5");
     19129        return false;
     19130    }
     19131    char* path_base = psMetadataLookupPtr(&status, md, "path_base");
     19132    if (!status) {
     19133        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item path_base");
     19134        return false;
     19135    }
     19136    psS16 fault = psMetadataLookupS16(&status, md, "fault");
     19137    if (!status) {
     19138        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fault");
     19139        return false;
     19140    }
     19141
     19142    return detRegisteredImfileRowAlloc(det_id, iteration, class_id, uri, bg, bg_stdev, bg_mean_stdev, user_1, user_2, user_3, user_4, user_5, path_base, fault);
     19143}
     19144psArray *detRegisteredImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     19145{
     19146    psArray         *rowSet;
     19147    psArray         *returnSet;
     19148    psU64           i;
     19149
     19150    rowSet = psDBSelectRows(dbh, DETREGISTEREDIMFILE_TABLE_NAME, where, limit);
     19151    if (!rowSet) {
     19152        return NULL;
     19153    }
     19154
     19155    // convert psMetadata rows to row objects
     19156
     19157    returnSet = psArrayAllocEmpty(rowSet->n);
     19158
     19159    for (i = 0; i < rowSet->n; i++) {
     19160        detRegisteredImfileRow *object = detRegisteredImfileObjectFromMetadata(rowSet->data[i]);
     19161        psArrayAdd(returnSet, 0, object);
     19162        psFree(object);
     19163    }
     19164
     19165    psFree(rowSet);
     19166
     19167    return returnSet;
     19168}
     19169bool detRegisteredImfileDeleteObject(psDB *dbh, const detRegisteredImfileRow *object)
     19170{
     19171    psMetadata *where = detRegisteredImfileMetadataFromObject(object);
     19172    long long count = psDBDeleteRows(dbh, DETREGISTEREDIMFILE_TABLE_NAME, where, 0);
     19173    psFree(where);
     19174    if (count < 0) {
     19175        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRegisteredImfile");
     19176        return false;
     19177    }
     19178    if (count > 1) {
     19179        // XXX should this be a psAbort() instead?  It is possible that
     19180        // having an object match multiple rows was by design.
     19181        psError(PS_ERR_UNKNOWN, true, "detRegisteredImfileRow object matched more then one row.  Check your database schema");
     19182        return false;
     19183    }
     19184
     19185    return true;
     19186}
     19187long long detRegisteredImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     19188{
     19189    long long       deleted = 0;
     19190
     19191    for (long long i = 0; i < objects->n; i++) {
     19192        detRegisteredImfileRow *object = objects->data[i];
     19193        psMetadata *where = detRegisteredImfileMetadataFromObject(object);
     19194        long long count = psDBDeleteRows(dbh, DETREGISTEREDIMFILE_TABLE_NAME, where, limit);
     19195        psFree(where);
     19196        if (count < 0) {
     19197            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRegisteredImfile");
     19198            return count;
     19199        }
     19200
     19201        deleted += count;
     19202    }
     19203
     19204    return deleted;
     19205}
     19206bool detRegisteredImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     19207{
     19208    PS_ASSERT_PTR_NON_NULL(objects, false);
     19209
     19210    psMetadata *output = psMetadataAlloc();
     19211    for (long i = 0; i < psArrayLength(objects); i++) {
     19212        psMetadata *md = detRegisteredImfileMetadataFromObject(objects->data[i]);
     19213        if (!psMetadataAddMetadata(
     19214            output,
     19215            PS_LIST_TAIL,
     19216            DETREGISTEREDIMFILE_TABLE_NAME,
     19217            PS_META_DUPLICATE_OK,
     19218            NULL,
     19219            md
     19220        )) {
     19221            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     19222            psFree(md);
     19223            psFree(output);
     19224            return false;
     19225        }
     19226        psFree(md);
     19227    }
     19228
     19229    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     19230        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     19231        psFree(output);
     19232    }
     19233    psFree(output);
     19234
     19235    return true;
     19236}
     19237bool detRegisteredImfilePrintObject(FILE *stream, detRegisteredImfileRow *object, bool mdcf)
     19238{
     19239    PS_ASSERT_PTR_NON_NULL(object, false);
     19240
     19241    psMetadata *md = detRegisteredImfileMetadataFromObject(object);
     19242
     19243    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     19244        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     19245        psFree(md);
     19246    }
     19247
     19248    psFree(md);
     19249
     19250    return true;
     19251}
     19252static void detCorrectedExpRowFree(detCorrectedExpRow *object);
     19253
     19254detCorrectedExpRow *detCorrectedExpRowAlloc(psS64 det_id, psS64 exp_id, const char *uri, psS64 corr_id, const char *corr_type, const char *recipe, const char *path_base, psS16 fault)
     19255{
     19256    detCorrectedExpRow *_object;
     19257
     19258    _object = psAlloc(sizeof(detCorrectedExpRow));
     19259    psMemSetDeallocator(_object, (psFreeFunc)detCorrectedExpRowFree);
     19260
     19261    _object->det_id = det_id;
     19262    _object->exp_id = exp_id;
     19263    _object->uri = psStringCopy(uri);
     19264    _object->corr_id = corr_id;
     19265    _object->corr_type = psStringCopy(corr_type);
     19266    _object->recipe = psStringCopy(recipe);
     19267    _object->path_base = psStringCopy(path_base);
     19268    _object->fault = fault;
     19269
     19270    return _object;
     19271}
     19272
     19273static void detCorrectedExpRowFree(detCorrectedExpRow *object)
     19274{
     19275    psFree(object->uri);
     19276    psFree(object->corr_type);
     19277    psFree(object->recipe);
     19278    psFree(object->path_base);
     19279}
     19280
     19281bool detCorrectedExpCreateTable(psDB *dbh)
     19282{
     19283    psMetadata *md = psMetadataAlloc();
     19284    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, exp_id) ref detInputExp(det_id, exp_id)", 0)) {
     19285        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     19286        psFree(md);
     19287        return false;
     19288    }
     19289    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey(exp_id, class_id) ref rawImfile(exp_id, class_id)", 64)) {
     19290        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     19291        psFree(md);
     19292        return false;
     19293    }
     19294    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, "INDEX(det_id, exp_id)", "255")) {
     19295        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19296        psFree(md);
     19297        return false;
     19298    }
     19299    if (!psMetadataAdd(md, PS_LIST_TAIL, "corr_id", PS_DATA_S64, NULL, 0)) {
     19300        psError(PS_ERR_UNKNOWN, false, "failed to add item corr_id");
     19301        psFree(md);
     19302        return false;
     19303    }
     19304    if (!psMetadataAdd(md, PS_LIST_TAIL, "corr_type", PS_DATA_STRING, NULL, "64")) {
     19305        psError(PS_ERR_UNKNOWN, false, "failed to add item corr_type");
     19306        psFree(md);
     19307        return false;
     19308    }
     19309    if (!psMetadataAdd(md, PS_LIST_TAIL, "recipe", PS_DATA_STRING, NULL, "64")) {
     19310        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
     19311        psFree(md);
     19312        return false;
     19313    }
     19314    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, "255")) {
     19315        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19316        psFree(md);
     19317        return false;
     19318    }
     19319    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, "Key NOT NULL", 0)) {
     19320        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19321        psFree(md);
     19322        return false;
     19323    }
     19324
     19325    bool status = psDBCreateTable(dbh, DETCORRECTEDEXP_TABLE_NAME, md);
     19326
     19327    psFree(md);
     19328
     19329    return status;
     19330}
     19331
     19332bool detCorrectedExpDropTable(psDB *dbh)
     19333{
     19334    return psDBDropTable(dbh, DETCORRECTEDEXP_TABLE_NAME);
     19335}
     19336
     19337bool detCorrectedExpInsert(psDB * dbh, psS64 det_id, psS64 exp_id, const char *uri, psS64 corr_id, const char *corr_type, const char *recipe, const char *path_base, psS16 fault)
     19338{
     19339    psMetadata *md = psMetadataAlloc();
     19340    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, NULL, det_id)) {
     19341        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     19342        psFree(md);
     19343        return false;
     19344    }
     19345    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, exp_id)) {
     19346        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     19347        psFree(md);
     19348        return false;
     19349    }
     19350    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     19351        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19352        psFree(md);
     19353        return false;
     19354    }
     19355    if (!psMetadataAdd(md, PS_LIST_TAIL, "corr_id", PS_DATA_S64, NULL, corr_id)) {
     19356        psError(PS_ERR_UNKNOWN, false, "failed to add item corr_id");
     19357        psFree(md);
     19358        return false;
     19359    }
     19360    if (!psMetadataAdd(md, PS_LIST_TAIL, "corr_type", PS_DATA_STRING, NULL, corr_type)) {
     19361        psError(PS_ERR_UNKNOWN, false, "failed to add item corr_type");
     19362        psFree(md);
     19363        return false;
     19364    }
     19365    if (!psMetadataAdd(md, PS_LIST_TAIL, "recipe", PS_DATA_STRING, NULL, recipe)) {
     19366        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
     19367        psFree(md);
     19368        return false;
     19369    }
     19370    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, path_base)) {
     19371        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19372        psFree(md);
     19373        return false;
     19374    }
     19375    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, fault)) {
     19376        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19377        psFree(md);
     19378        return false;
     19379    }
     19380
     19381    bool status = psDBInsertOneRow(dbh, DETCORRECTEDEXP_TABLE_NAME, md);
     19382    psFree(md);
     19383
     19384    return status;
     19385}
     19386
     19387long long detCorrectedExpDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     19388{
     19389    long long       deleted = 0;
     19390
     19391    long long count = psDBDeleteRows(dbh, DETCORRECTEDEXP_TABLE_NAME, where, limit);
     19392    if (count < 0) {
     19393        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detCorrectedExp");
     19394        return count;
     19395
     19396        deleted += count;
     19397    }
     19398
     19399    return deleted;
     19400}
     19401bool detCorrectedExpInsertObject(psDB *dbh, detCorrectedExpRow *object)
     19402{
     19403    return detCorrectedExpInsert(dbh, object->det_id, object->exp_id, object->uri, object->corr_id, object->corr_type, object->recipe, object->path_base, object->fault);
     19404}
     19405
     19406bool detCorrectedExpInsertObjects(psDB *dbh, psArray *objects)
     19407{
     19408    for (long i = 0; i < psArrayLength(objects); i++) {
     19409        if (!detCorrectedExpInsertObject(dbh, objects->data[i])) {
     19410            return false;
     19411        }
     19412    }
     19413
     19414    return true;
     19415}
     19416
     19417bool detCorrectedExpInsertFits(psDB *dbh, const psFits *fits)
     19418{
     19419    psArray         *rowSet;
     19420
     19421    // move to (the first?) extension named  DETCORRECTEDEXP_TABLE_NAME
     19422    if (!psFitsMoveExtName(fits, DETCORRECTEDEXP_TABLE_NAME)) {
     19423        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETCORRECTEDEXP_TABLE_NAME);
     19424        return false;
     19425    }
     19426
     19427    // check HDU type
     19428    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     19429        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     19430        return false;
     19431    }
     19432
     19433    // read fits table
     19434    rowSet = psFitsReadTable(fits);
     19435    if (!rowSet) {
     19436        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     19437        psFree(rowSet);
     19438        return false;
     19439    }
     19440
     19441    if (!psDBInsertRows(dbh, DETCORRECTEDEXP_TABLE_NAME, rowSet)) {
     19442        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     19443        psFree(rowSet);
     19444        return false;
     19445    }
     19446
     19447    psFree(rowSet);
     19448
     19449    return true;
     19450}
     19451
     19452bool detCorrectedExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     19453{
     19454    psArray         *rowSet;
     19455
     19456    rowSet = psDBSelectRows(dbh, DETCORRECTEDEXP_TABLE_NAME, where, limit);
     19457    if (!rowSet) {
     19458        return false;
     19459    }
     19460
     19461    // output to fits
     19462    if (!psFitsWriteTable(fits, NULL, rowSet, DETCORRECTEDEXP_TABLE_NAME)) {
     19463        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     19464        psFree(rowSet);
     19465        return false;
     19466    }
     19467
     19468    psFree(rowSet);
     19469
     19470    return true;
     19471}
     19472
     19473psMetadata *detCorrectedExpMetadataFromObject(const detCorrectedExpRow *object)
     19474{
     19475    psMetadata *md = psMetadataAlloc();
     19476    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, NULL, object->det_id)) {
     19477        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     19478        psFree(md);
     19479        return false;
     19480    }
     19481    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, object->exp_id)) {
     19482        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     19483        psFree(md);
     19484        return false;
     19485    }
     19486    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     19487        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19488        psFree(md);
     19489        return false;
     19490    }
     19491    if (!psMetadataAdd(md, PS_LIST_TAIL, "corr_id", PS_DATA_S64, NULL, object->corr_id)) {
     19492        psError(PS_ERR_UNKNOWN, false, "failed to add item corr_id");
     19493        psFree(md);
     19494        return false;
     19495    }
     19496    if (!psMetadataAdd(md, PS_LIST_TAIL, "corr_type", PS_DATA_STRING, NULL, object->corr_type)) {
     19497        psError(PS_ERR_UNKNOWN, false, "failed to add item corr_type");
     19498        psFree(md);
     19499        return false;
     19500    }
     19501    if (!psMetadataAdd(md, PS_LIST_TAIL, "recipe", PS_DATA_STRING, NULL, object->recipe)) {
     19502        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
     19503        psFree(md);
     19504        return false;
     19505    }
     19506    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, object->path_base)) {
     19507        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19508        psFree(md);
     19509        return false;
     19510    }
     19511    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, object->fault)) {
     19512        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19513        psFree(md);
     19514        return false;
     19515    }
     19516
     19517
     19518    return md;
     19519}
     19520
     19521detCorrectedExpRow *detCorrectedExpObjectFromMetadata(psMetadata *md)
     19522{
     19523
     19524bool status = false;
     19525    psS64 det_id = psMetadataLookupS64(&status, md, "det_id");
     19526    if (!status) {
     19527        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
     19528        return false;
     19529    }
     19530    psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
     19531    if (!status) {
     19532        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
     19533        return false;
     19534    }
     19535    char* uri = psMetadataLookupPtr(&status, md, "uri");
     19536    if (!status) {
     19537        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     19538        return false;
     19539    }
     19540    psS64 corr_id = psMetadataLookupS64(&status, md, "corr_id");
     19541    if (!status) {
     19542        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item corr_id");
     19543        return false;
     19544    }
     19545    char* corr_type = psMetadataLookupPtr(&status, md, "corr_type");
     19546    if (!status) {
     19547        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item corr_type");
     19548        return false;
     19549    }
     19550    char* recipe = psMetadataLookupPtr(&status, md, "recipe");
     19551    if (!status) {
     19552        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
     19553        return false;
     19554    }
     19555    char* path_base = psMetadataLookupPtr(&status, md, "path_base");
     19556    if (!status) {
     19557        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item path_base");
     19558        return false;
     19559    }
     19560    psS16 fault = psMetadataLookupS16(&status, md, "fault");
     19561    if (!status) {
     19562        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fault");
     19563        return false;
     19564    }
     19565
     19566    return detCorrectedExpRowAlloc(det_id, exp_id, uri, corr_id, corr_type, recipe, path_base, fault);
     19567}
     19568psArray *detCorrectedExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     19569{
     19570    psArray         *rowSet;
     19571    psArray         *returnSet;
     19572    psU64           i;
     19573
     19574    rowSet = psDBSelectRows(dbh, DETCORRECTEDEXP_TABLE_NAME, where, limit);
     19575    if (!rowSet) {
     19576        return NULL;
     19577    }
     19578
     19579    // convert psMetadata rows to row objects
     19580
     19581    returnSet = psArrayAllocEmpty(rowSet->n);
     19582
     19583    for (i = 0; i < rowSet->n; i++) {
     19584        detCorrectedExpRow *object = detCorrectedExpObjectFromMetadata(rowSet->data[i]);
     19585        psArrayAdd(returnSet, 0, object);
     19586        psFree(object);
     19587    }
     19588
     19589    psFree(rowSet);
     19590
     19591    return returnSet;
     19592}
     19593bool detCorrectedExpDeleteObject(psDB *dbh, const detCorrectedExpRow *object)
     19594{
     19595    psMetadata *where = detCorrectedExpMetadataFromObject(object);
     19596    long long count = psDBDeleteRows(dbh, DETCORRECTEDEXP_TABLE_NAME, where, 0);
     19597    psFree(where);
     19598    if (count < 0) {
     19599        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detCorrectedExp");
     19600        return false;
     19601    }
     19602    if (count > 1) {
     19603        // XXX should this be a psAbort() instead?  It is possible that
     19604        // having an object match multiple rows was by design.
     19605        psError(PS_ERR_UNKNOWN, true, "detCorrectedExpRow object matched more then one row.  Check your database schema");
     19606        return false;
     19607    }
     19608
     19609    return true;
     19610}
     19611long long detCorrectedExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     19612{
     19613    long long       deleted = 0;
     19614
     19615    for (long long i = 0; i < objects->n; i++) {
     19616        detCorrectedExpRow *object = objects->data[i];
     19617        psMetadata *where = detCorrectedExpMetadataFromObject(object);
     19618        long long count = psDBDeleteRows(dbh, DETCORRECTEDEXP_TABLE_NAME, where, limit);
     19619        psFree(where);
     19620        if (count < 0) {
     19621            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detCorrectedExp");
     19622            return count;
     19623        }
     19624
     19625        deleted += count;
     19626    }
     19627
     19628    return deleted;
     19629}
     19630bool detCorrectedExpPrintObjects(FILE *stream, psArray *objects, bool mdcf)
     19631{
     19632    PS_ASSERT_PTR_NON_NULL(objects, false);
     19633
     19634    psMetadata *output = psMetadataAlloc();
     19635    for (long i = 0; i < psArrayLength(objects); i++) {
     19636        psMetadata *md = detCorrectedExpMetadataFromObject(objects->data[i]);
     19637        if (!psMetadataAddMetadata(
     19638            output,
     19639            PS_LIST_TAIL,
     19640            DETCORRECTEDEXP_TABLE_NAME,
     19641            PS_META_DUPLICATE_OK,
     19642            NULL,
     19643            md
     19644        )) {
     19645            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     19646            psFree(md);
     19647            psFree(output);
     19648            return false;
     19649        }
     19650        psFree(md);
     19651    }
     19652
     19653    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     19654        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     19655        psFree(output);
     19656    }
     19657    psFree(output);
     19658
     19659    return true;
     19660}
     19661bool detCorrectedExpPrintObject(FILE *stream, detCorrectedExpRow *object, bool mdcf)
     19662{
     19663    PS_ASSERT_PTR_NON_NULL(object, false);
     19664
     19665    psMetadata *md = detCorrectedExpMetadataFromObject(object);
     19666
     19667    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     19668        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     19669        psFree(md);
     19670    }
     19671
     19672    psFree(md);
     19673
     19674    return true;
     19675}
     19676static void detCorrectedImfileRowFree(detCorrectedImfileRow *object);
     19677
     19678detCorrectedImfileRow *detCorrectedImfileRowAlloc(psS64 det_id, psS64 exp_id, const char *class_id, const char *uri, const char *path_base, psS16 fault)
     19679{
     19680    detCorrectedImfileRow *_object;
     19681
     19682    _object = psAlloc(sizeof(detCorrectedImfileRow));
     19683    psMemSetDeallocator(_object, (psFreeFunc)detCorrectedImfileRowFree);
     19684
     19685    _object->det_id = det_id;
     19686    _object->exp_id = exp_id;
     19687    _object->class_id = psStringCopy(class_id);
     19688    _object->uri = psStringCopy(uri);
     19689    _object->path_base = psStringCopy(path_base);
     19690    _object->fault = fault;
     19691
     19692    return _object;
     19693}
     19694
     19695static void detCorrectedImfileRowFree(detCorrectedImfileRow *object)
     19696{
     19697    psFree(object->class_id);
     19698    psFree(object->uri);
     19699    psFree(object->path_base);
     19700}
     19701
     19702bool detCorrectedImfileCreateTable(psDB *dbh)
     19703{
     19704    psMetadata *md = psMetadataAlloc();
     19705    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, "Primary Key fkey(det_id, exp_id) ref detInputExp(det_id, exp_id)", 0)) {
     19706        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     19707        psFree(md);
     19708        return false;
     19709    }
     19710    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, "Primary Key fkey(exp_id, class_id) ref rawImfile(exp_id, class_id)", 64)) {
     19711        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     19712        psFree(md);
     19713        return false;
     19714    }
     19715    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key INDEX(det_id, class_id)", "64")) {
     19716        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     19717        psFree(md);
     19718        return false;
     19719    }
     19720    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, "INDEX(det_id, exp_id)", "255")) {
     19721        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19722        psFree(md);
     19723        return false;
     19724    }
     19725    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, "255")) {
     19726        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19727        psFree(md);
     19728        return false;
     19729    }
     19730    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, "Key NOT NULL", 0)) {
     19731        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19732        psFree(md);
     19733        return false;
     19734    }
     19735
     19736    bool status = psDBCreateTable(dbh, DETCORRECTEDIMFILE_TABLE_NAME, md);
     19737
     19738    psFree(md);
     19739
     19740    return status;
     19741}
     19742
     19743bool detCorrectedImfileDropTable(psDB *dbh)
     19744{
     19745    return psDBDropTable(dbh, DETCORRECTEDIMFILE_TABLE_NAME);
     19746}
     19747
     19748bool detCorrectedImfileInsert(psDB * dbh, psS64 det_id, psS64 exp_id, const char *class_id, const char *uri, const char *path_base, psS16 fault)
     19749{
     19750    psMetadata *md = psMetadataAlloc();
     19751    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, NULL, det_id)) {
     19752        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     19753        psFree(md);
     19754        return false;
     19755    }
     19756    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, exp_id)) {
     19757        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     19758        psFree(md);
     19759        return false;
     19760    }
     19761    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     19762        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     19763        psFree(md);
     19764        return false;
     19765    }
     19766    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     19767        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19768        psFree(md);
     19769        return false;
     19770    }
     19771    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, path_base)) {
     19772        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19773        psFree(md);
     19774        return false;
     19775    }
     19776    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, fault)) {
     19777        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19778        psFree(md);
     19779        return false;
     19780    }
     19781
     19782    bool status = psDBInsertOneRow(dbh, DETCORRECTEDIMFILE_TABLE_NAME, md);
     19783    psFree(md);
     19784
     19785    return status;
     19786}
     19787
     19788long long detCorrectedImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     19789{
     19790    long long       deleted = 0;
     19791
     19792    long long count = psDBDeleteRows(dbh, DETCORRECTEDIMFILE_TABLE_NAME, where, limit);
     19793    if (count < 0) {
     19794        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detCorrectedImfile");
     19795        return count;
     19796
     19797        deleted += count;
     19798    }
     19799
     19800    return deleted;
     19801}
     19802bool detCorrectedImfileInsertObject(psDB *dbh, detCorrectedImfileRow *object)
     19803{
     19804    return detCorrectedImfileInsert(dbh, object->det_id, object->exp_id, object->class_id, object->uri, object->path_base, object->fault);
     19805}
     19806
     19807bool detCorrectedImfileInsertObjects(psDB *dbh, psArray *objects)
     19808{
     19809    for (long i = 0; i < psArrayLength(objects); i++) {
     19810        if (!detCorrectedImfileInsertObject(dbh, objects->data[i])) {
     19811            return false;
     19812        }
     19813    }
     19814
     19815    return true;
     19816}
     19817
     19818bool detCorrectedImfileInsertFits(psDB *dbh, const psFits *fits)
     19819{
     19820    psArray         *rowSet;
     19821
     19822    // move to (the first?) extension named  DETCORRECTEDIMFILE_TABLE_NAME
     19823    if (!psFitsMoveExtName(fits, DETCORRECTEDIMFILE_TABLE_NAME)) {
     19824        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETCORRECTEDIMFILE_TABLE_NAME);
     19825        return false;
     19826    }
     19827
     19828    // check HDU type
     19829    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     19830        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     19831        return false;
     19832    }
     19833
     19834    // read fits table
     19835    rowSet = psFitsReadTable(fits);
     19836    if (!rowSet) {
     19837        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     19838        psFree(rowSet);
     19839        return false;
     19840    }
     19841
     19842    if (!psDBInsertRows(dbh, DETCORRECTEDIMFILE_TABLE_NAME, rowSet)) {
     19843        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     19844        psFree(rowSet);
     19845        return false;
     19846    }
     19847
     19848    psFree(rowSet);
     19849
     19850    return true;
     19851}
     19852
     19853bool detCorrectedImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     19854{
     19855    psArray         *rowSet;
     19856
     19857    rowSet = psDBSelectRows(dbh, DETCORRECTEDIMFILE_TABLE_NAME, where, limit);
     19858    if (!rowSet) {
     19859        return false;
     19860    }
     19861
     19862    // output to fits
     19863    if (!psFitsWriteTable(fits, NULL, rowSet, DETCORRECTEDIMFILE_TABLE_NAME)) {
     19864        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     19865        psFree(rowSet);
     19866        return false;
     19867    }
     19868
     19869    psFree(rowSet);
     19870
     19871    return true;
     19872}
     19873
     19874psMetadata *detCorrectedImfileMetadataFromObject(const detCorrectedImfileRow *object)
     19875{
     19876    psMetadata *md = psMetadataAlloc();
     19877    if (!psMetadataAdd(md, PS_LIST_TAIL, "det_id", PS_DATA_S64, NULL, object->det_id)) {
     19878        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
     19879        psFree(md);
     19880        return false;
     19881    }
     19882    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_id", PS_DATA_S64, NULL, object->exp_id)) {
     19883        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
     19884        psFree(md);
     19885        return false;
     19886    }
     19887    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     19888        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     19889        psFree(md);
     19890        return false;
     19891    }
     19892    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     19893        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     19894        psFree(md);
     19895        return false;
     19896    }
     19897    if (!psMetadataAdd(md, PS_LIST_TAIL, "path_base", PS_DATA_STRING, NULL, object->path_base)) {
     19898        psError(PS_ERR_UNKNOWN, false, "failed to add item path_base");
     19899        psFree(md);
     19900        return false;
     19901    }
     19902    if (!psMetadataAdd(md, PS_LIST_TAIL, "fault", PS_DATA_S16, NULL, object->fault)) {
     19903        psError(PS_ERR_UNKNOWN, false, "failed to add item fault");
     19904        psFree(md);
     19905        return false;
     19906    }
     19907
     19908
     19909    return md;
     19910}
     19911
     19912detCorrectedImfileRow *detCorrectedImfileObjectFromMetadata(psMetadata *md)
     19913{
     19914
     19915bool status = false;
     19916    psS64 det_id = psMetadataLookupS64(&status, md, "det_id");
     19917    if (!status) {
     19918        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
     19919        return false;
     19920    }
     19921    psS64 exp_id = psMetadataLookupS64(&status, md, "exp_id");
     19922    if (!status) {
     19923        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
     19924        return false;
     19925    }
     19926    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     19927    if (!status) {
     19928        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     19929        return false;
     19930    }
     19931    char* uri = psMetadataLookupPtr(&status, md, "uri");
     19932    if (!status) {
     19933        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     19934        return false;
     19935    }
     19936    char* path_base = psMetadataLookupPtr(&status, md, "path_base");
     19937    if (!status) {
     19938        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item path_base");
     19939        return false;
     19940    }
     19941    psS16 fault = psMetadataLookupS16(&status, md, "fault");
     19942    if (!status) {
     19943        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fault");
     19944        return false;
     19945    }
     19946
     19947    return detCorrectedImfileRowAlloc(det_id, exp_id, class_id, uri, path_base, fault);
     19948}
     19949psArray *detCorrectedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     19950{
     19951    psArray         *rowSet;
     19952    psArray         *returnSet;
     19953    psU64           i;
     19954
     19955    rowSet = psDBSelectRows(dbh, DETCORRECTEDIMFILE_TABLE_NAME, where, limit);
     19956    if (!rowSet) {
     19957        return NULL;
     19958    }
     19959
     19960    // convert psMetadata rows to row objects
     19961
     19962    returnSet = psArrayAllocEmpty(rowSet->n);
     19963
     19964    for (i = 0; i < rowSet->n; i++) {
     19965        detCorrectedImfileRow *object = detCorrectedImfileObjectFromMetadata(rowSet->data[i]);
     19966        psArrayAdd(returnSet, 0, object);
     19967        psFree(object);
     19968    }
     19969
     19970    psFree(rowSet);
     19971
     19972    return returnSet;
     19973}
     19974bool detCorrectedImfileDeleteObject(psDB *dbh, const detCorrectedImfileRow *object)
     19975{
     19976    psMetadata *where = detCorrectedImfileMetadataFromObject(object);
     19977    long long count = psDBDeleteRows(dbh, DETCORRECTEDIMFILE_TABLE_NAME, where, 0);
     19978    psFree(where);
     19979    if (count < 0) {
     19980        psError(PS_ERR_UNKNOWN, true, "failed to delete row from detCorrectedImfile");
     19981        return false;
     19982    }
     19983    if (count > 1) {
     19984        // XXX should this be a psAbort() instead?  It is possible that
     19985        // having an object match multiple rows was by design.
     19986        psError(PS_ERR_UNKNOWN, true, "detCorrectedImfileRow object matched more then one row.  Check your database schema");
     19987        return false;
     19988    }
     19989
     19990    return true;
     19991}
     19992long long detCorrectedImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     19993{
     19994    long long       deleted = 0;
     19995
     19996    for (long long i = 0; i < objects->n; i++) {
     19997        detCorrectedImfileRow *object = objects->data[i];
     19998        psMetadata *where = detCorrectedImfileMetadataFromObject(object);
     19999        long long count = psDBDeleteRows(dbh, DETCORRECTEDIMFILE_TABLE_NAME, where, limit);
     20000        psFree(where);
     20001        if (count < 0) {
     20002            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detCorrectedImfile");
     20003            return count;
     20004        }
     20005
     20006        deleted += count;
     20007    }
     20008
     20009    return deleted;
     20010}
     20011bool detCorrectedImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     20012{
     20013    PS_ASSERT_PTR_NON_NULL(objects, false);
     20014
     20015    psMetadata *output = psMetadataAlloc();
     20016    for (long i = 0; i < psArrayLength(objects); i++) {
     20017        psMetadata *md = detCorrectedImfileMetadataFromObject(objects->data[i]);
     20018        if (!psMetadataAddMetadata(
     20019            output,
     20020            PS_LIST_TAIL,
     20021            DETCORRECTEDIMFILE_TABLE_NAME,
     20022            PS_META_DUPLICATE_OK,
     20023            NULL,
     20024            md
     20025        )) {
     20026            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     20027            psFree(md);
     20028            psFree(output);
     20029            return false;
     20030        }
     20031        psFree(md);
     20032    }
     20033
     20034    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     20035        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     20036        psFree(output);
     20037    }
     20038    psFree(output);
     20039
     20040    return true;
     20041}
     20042bool detCorrectedImfilePrintObject(FILE *stream, detCorrectedImfileRow *object, bool mdcf)
     20043{
     20044    PS_ASSERT_PTR_NON_NULL(object, false);
     20045
     20046    psMetadata *md = detCorrectedImfileMetadataFromObject(object);
     20047
     20048    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     20049        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     20050        psFree(md);
     20051    }
     20052
     20053    psFree(md);
     20054
     20055    return true;
     20056}
     20057static void magicRunRowFree(magicRunRow *object);
     20058
     20059magicRunRow *magicRunRowAlloc(psS64 magic_id, const char *state, const char *workdir, const char *workdir_state, const char *label, const char *dvodb, psTime* registered)
     20060{
     20061    magicRunRow     *_object;
     20062
     20063    _object = psAlloc(sizeof(magicRunRow));
     20064    psMemSetDeallocator(_object, (psFreeFunc)magicRunRowFree);
     20065
     20066    _object->magic_id = magic_id;
     20067    _object->state = psStringCopy(state);
     20068    _object->workdir = psStringCopy(workdir);
     20069    _object->workdir_state = psStringCopy(workdir_state);
     20070    _object->label = psStringCopy(label);
     20071    _object->dvodb = psStringCopy(dvodb);
     20072    _object->registered = psTimeCopy(registered);
     20073
     20074    return _object;
     20075}
     20076
     20077static void magicRunRowFree(magicRunRow *object)
     20078{
     20079    psFree(object->state);
     20080    psFree(object->workdir);
     20081    psFree(object->workdir_state);
     20082    psFree(object->label);
     20083    psFree(object->dvodb);
     20084    psFree(object->registered);
     20085}
     20086
     20087bool magicRunCreateTable(psDB *dbh)
     20088{
     20089    psMetadata *md = psMetadataAlloc();
     20090    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, "Primary Key AUTO_INCREMENT", 0)) {
     20091        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20092        psFree(md);
     20093        return false;
     20094    }
     20095    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, "Key", "64")) {
     20096        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     20097        psFree(md);
     20098        return false;
     20099    }
     20100    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, NULL, "255")) {
     20101        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     20102        psFree(md);
     20103        return false;
     20104    }
     20105    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir_state", PS_DATA_STRING, "Key", "255")) {
     20106        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir_state");
     20107        psFree(md);
     20108        return false;
     20109    }
     20110    if (!psMetadataAdd(md, PS_LIST_TAIL, "label", PS_DATA_STRING, "key", "64")) {
     20111        psError(PS_ERR_UNKNOWN, false, "failed to add item label");
     20112        psFree(md);
     20113        return false;
     20114    }
     20115    if (!psMetadataAdd(md, PS_LIST_TAIL, "dvodb", PS_DATA_STRING, NULL, "255")) {
     20116        psError(PS_ERR_UNKNOWN, false, "failed to add item dvodb");
     20117        psFree(md);
     20118        return false;
     20119    }
     20120    if (!psMetadataAdd(md, PS_LIST_TAIL, "registered", PS_DATA_TIME, NULL, NULL)) {
     20121        psError(PS_ERR_UNKNOWN, false, "failed to add item registered");
     20122        psFree(md);
     20123        return false;
     20124    }
     20125
     20126    bool status = psDBCreateTable(dbh, MAGICRUN_TABLE_NAME, md);
     20127
     20128    psFree(md);
     20129
     20130    return status;
     20131}
     20132
     20133bool magicRunDropTable(psDB *dbh)
     20134{
     20135    return psDBDropTable(dbh, MAGICRUN_TABLE_NAME);
     20136}
     20137
     20138bool magicRunInsert(psDB * dbh, psS64 magic_id, const char *state, const char *workdir, const char *workdir_state, const char *label, const char *dvodb, psTime* registered)
     20139{
     20140    psMetadata *md = psMetadataAlloc();
     20141    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, magic_id)) {
     20142        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20143        psFree(md);
     20144        return false;
     20145    }
     20146    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, NULL, state)) {
     20147        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     20148        psFree(md);
     20149        return false;
     20150    }
     20151    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, NULL, workdir)) {
     20152        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     20153        psFree(md);
     20154        return false;
     20155    }
     20156    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir_state", PS_DATA_STRING, NULL, workdir_state)) {
     20157        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir_state");
     20158        psFree(md);
     20159        return false;
     20160    }
     20161    if (!psMetadataAdd(md, PS_LIST_TAIL, "label", PS_DATA_STRING, NULL, label)) {
     20162        psError(PS_ERR_UNKNOWN, false, "failed to add item label");
     20163        psFree(md);
     20164        return false;
     20165    }
     20166    if (!psMetadataAdd(md, PS_LIST_TAIL, "dvodb", PS_DATA_STRING, NULL, dvodb)) {
     20167        psError(PS_ERR_UNKNOWN, false, "failed to add item dvodb");
     20168        psFree(md);
     20169        return false;
     20170    }
     20171    if (!psMetadataAdd(md, PS_LIST_TAIL, "registered", PS_DATA_TIME, NULL, registered)) {
     20172        psError(PS_ERR_UNKNOWN, false, "failed to add item registered");
     20173        psFree(md);
     20174        return false;
     20175    }
     20176
     20177    bool status = psDBInsertOneRow(dbh, MAGICRUN_TABLE_NAME, md);
     20178    psFree(md);
     20179
     20180    return status;
     20181}
     20182
     20183long long magicRunDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     20184{
     20185    long long       deleted = 0;
     20186
     20187    long long count = psDBDeleteRows(dbh, MAGICRUN_TABLE_NAME, where, limit);
     20188    if (count < 0) {
     20189        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicRun");
     20190        return count;
     20191
     20192        deleted += count;
     20193    }
     20194
     20195    return deleted;
     20196}
     20197bool magicRunInsertObject(psDB *dbh, magicRunRow *object)
     20198{
     20199    return magicRunInsert(dbh, object->magic_id, object->state, object->workdir, object->workdir_state, object->label, object->dvodb, object->registered);
     20200}
     20201
     20202bool magicRunInsertObjects(psDB *dbh, psArray *objects)
     20203{
     20204    for (long i = 0; i < psArrayLength(objects); i++) {
     20205        if (!magicRunInsertObject(dbh, objects->data[i])) {
     20206            return false;
     20207        }
     20208    }
     20209
     20210    return true;
     20211}
     20212
     20213bool magicRunInsertFits(psDB *dbh, const psFits *fits)
     20214{
     20215    psArray         *rowSet;
     20216
     20217    // move to (the first?) extension named  MAGICRUN_TABLE_NAME
     20218    if (!psFitsMoveExtName(fits, MAGICRUN_TABLE_NAME)) {
     20219        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", MAGICRUN_TABLE_NAME);
     20220        return false;
     20221    }
     20222
     20223    // check HDU type
     20224    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     20225        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     20226        return false;
     20227    }
     20228
     20229    // read fits table
     20230    rowSet = psFitsReadTable(fits);
     20231    if (!rowSet) {
     20232        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     20233        psFree(rowSet);
     20234        return false;
     20235    }
     20236
     20237    if (!psDBInsertRows(dbh, MAGICRUN_TABLE_NAME, rowSet)) {
     20238        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     20239        psFree(rowSet);
     20240        return false;
     20241    }
     20242
     20243    psFree(rowSet);
     20244
     20245    return true;
     20246}
     20247
     20248bool magicRunSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     20249{
     20250    psArray         *rowSet;
     20251
     20252    rowSet = psDBSelectRows(dbh, MAGICRUN_TABLE_NAME, where, limit);
     20253    if (!rowSet) {
     20254        return false;
     20255    }
     20256
     20257    // output to fits
     20258    if (!psFitsWriteTable(fits, NULL, rowSet, MAGICRUN_TABLE_NAME)) {
     20259        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     20260        psFree(rowSet);
     20261        return false;
     20262    }
     20263
     20264    psFree(rowSet);
     20265
     20266    return true;
     20267}
     20268
     20269psMetadata *magicRunMetadataFromObject(const magicRunRow *object)
     20270{
     20271    psMetadata *md = psMetadataAlloc();
     20272    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, object->magic_id)) {
     20273        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20274        psFree(md);
     20275        return false;
     20276    }
     20277    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, NULL, object->state)) {
     20278        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     20279        psFree(md);
     20280        return false;
     20281    }
     20282    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir", PS_DATA_STRING, NULL, object->workdir)) {
     20283        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir");
     20284        psFree(md);
     20285        return false;
     20286    }
     20287    if (!psMetadataAdd(md, PS_LIST_TAIL, "workdir_state", PS_DATA_STRING, NULL, object->workdir_state)) {
     20288        psError(PS_ERR_UNKNOWN, false, "failed to add item workdir_state");
     20289        psFree(md);
     20290        return false;
     20291    }
     20292    if (!psMetadataAdd(md, PS_LIST_TAIL, "label", PS_DATA_STRING, NULL, object->label)) {
     20293        psError(PS_ERR_UNKNOWN, false, "failed to add item label");
     20294        psFree(md);
     20295        return false;
     20296    }
     20297    if (!psMetadataAdd(md, PS_LIST_TAIL, "dvodb", PS_DATA_STRING, NULL, object->dvodb)) {
     20298        psError(PS_ERR_UNKNOWN, false, "failed to add item dvodb");
     20299        psFree(md);
     20300        return false;
     20301    }
     20302    if (!psMetadataAdd(md, PS_LIST_TAIL, "registered", PS_DATA_TIME, NULL, object->registered)) {
     20303        psError(PS_ERR_UNKNOWN, false, "failed to add item registered");
     20304        psFree(md);
     20305        return false;
     20306    }
     20307
     20308
     20309    return md;
     20310}
     20311
     20312magicRunRow *magicRunObjectFromMetadata(psMetadata *md)
     20313{
     20314
     20315bool status = false;
     20316    psS64 magic_id = psMetadataLookupS64(&status, md, "magic_id");
     20317    if (!status) {
     20318        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item magic_id");
     20319        return false;
     20320    }
     20321    char* state = psMetadataLookupPtr(&status, md, "state");
     20322    if (!status) {
     20323        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item state");
     20324        return false;
     20325    }
     20326    char* workdir = psMetadataLookupPtr(&status, md, "workdir");
     20327    if (!status) {
     20328        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item workdir");
     20329        return false;
     20330    }
     20331    char* workdir_state = psMetadataLookupPtr(&status, md, "workdir_state");
     20332    if (!status) {
     20333        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item workdir_state");
     20334        return false;
     20335    }
     20336    char* label = psMetadataLookupPtr(&status, md, "label");
     20337    if (!status) {
     20338        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item label");
     20339        return false;
     20340    }
     20341    char* dvodb = psMetadataLookupPtr(&status, md, "dvodb");
     20342    if (!status) {
     20343        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item dvodb");
     20344        return false;
     20345    }
     20346    psTime* registered = psMetadataLookupPtr(&status, md, "registered");
     20347    if (!status) {
     20348        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item registered");
     20349        return false;
     20350    }
     20351
     20352    return magicRunRowAlloc(magic_id, state, workdir, workdir_state, label, dvodb, registered);
     20353}
     20354psArray *magicRunSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     20355{
     20356    psArray         *rowSet;
     20357    psArray         *returnSet;
     20358    psU64           i;
     20359
     20360    rowSet = psDBSelectRows(dbh, MAGICRUN_TABLE_NAME, where, limit);
     20361    if (!rowSet) {
     20362        return NULL;
     20363    }
     20364
     20365    // convert psMetadata rows to row objects
     20366
     20367    returnSet = psArrayAllocEmpty(rowSet->n);
     20368
     20369    for (i = 0; i < rowSet->n; i++) {
     20370        magicRunRow *object = magicRunObjectFromMetadata(rowSet->data[i]);
     20371        psArrayAdd(returnSet, 0, object);
     20372        psFree(object);
     20373    }
     20374
     20375    psFree(rowSet);
     20376
     20377    return returnSet;
     20378}
     20379bool magicRunDeleteObject(psDB *dbh, const magicRunRow *object)
     20380{
     20381    psMetadata *where = magicRunMetadataFromObject(object);
     20382    long long count = psDBDeleteRows(dbh, MAGICRUN_TABLE_NAME, where, 0);
     20383    psFree(where);
     20384    if (count < 0) {
     20385        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicRun");
     20386        return false;
     20387    }
     20388    if (count > 1) {
     20389        // XXX should this be a psAbort() instead?  It is possible that
     20390        // having an object match multiple rows was by design.
     20391        psError(PS_ERR_UNKNOWN, true, "magicRunRow object matched more then one row.  Check your database schema");
     20392        return false;
     20393    }
     20394
     20395    return true;
     20396}
     20397long long magicRunDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     20398{
     20399    long long       deleted = 0;
     20400
     20401    for (long long i = 0; i < objects->n; i++) {
     20402        magicRunRow *object = objects->data[i];
     20403        psMetadata *where = magicRunMetadataFromObject(object);
     20404        long long count = psDBDeleteRows(dbh, MAGICRUN_TABLE_NAME, where, limit);
     20405        psFree(where);
     20406        if (count < 0) {
     20407            psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicRun");
     20408            return count;
     20409        }
     20410
     20411        deleted += count;
     20412    }
     20413
     20414    return deleted;
     20415}
     20416bool magicRunPrintObjects(FILE *stream, psArray *objects, bool mdcf)
     20417{
     20418    PS_ASSERT_PTR_NON_NULL(objects, false);
     20419
     20420    psMetadata *output = psMetadataAlloc();
     20421    for (long i = 0; i < psArrayLength(objects); i++) {
     20422        psMetadata *md = magicRunMetadataFromObject(objects->data[i]);
     20423        if (!psMetadataAddMetadata(
     20424            output,
     20425            PS_LIST_TAIL,
     20426            MAGICRUN_TABLE_NAME,
     20427            PS_META_DUPLICATE_OK,
     20428            NULL,
     20429            md
     20430        )) {
     20431            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     20432            psFree(md);
     20433            psFree(output);
     20434            return false;
     20435        }
     20436        psFree(md);
     20437    }
     20438
     20439    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     20440        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     20441        psFree(output);
     20442    }
     20443    psFree(output);
     20444
     20445    return true;
     20446}
     20447bool magicRunPrintObject(FILE *stream, magicRunRow *object, bool mdcf)
     20448{
     20449    PS_ASSERT_PTR_NON_NULL(object, false);
     20450
     20451    psMetadata *md = magicRunMetadataFromObject(object);
     20452
     20453    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     20454        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     20455        psFree(md);
     20456    }
     20457
     20458    psFree(md);
     20459
     20460    return true;
     20461}
     20462static void magicInputSkyfileRowFree(magicInputSkyfileRow *object);
     20463
     20464magicInputSkyfileRow *magicInputSkyfileRowAlloc(psS64 magic_id, psS64 diff_id, const char *node)
     20465{
     20466    magicInputSkyfileRow *_object;
     20467
     20468    _object = psAlloc(sizeof(magicInputSkyfileRow));
     20469    psMemSetDeallocator(_object, (psFreeFunc)magicInputSkyfileRowFree);
     20470
     20471    _object->magic_id = magic_id;
     20472    _object->diff_id = diff_id;
     20473    _object->node = psStringCopy(node);
     20474
     20475    return _object;
     20476}
     20477
     20478static void magicInputSkyfileRowFree(magicInputSkyfileRow *object)
     20479{
     20480    psFree(object->node);
     20481}
     20482
     20483bool magicInputSkyfileCreateTable(psDB *dbh)
     20484{
     20485    psMetadata *md = psMetadataAlloc();
     20486    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, "Primary Key fkey(magic_id) ref magicRun(magic_id)", 0)) {
     20487        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20488        psFree(md);
     20489        return false;
     20490    }
     20491    if (!psMetadataAdd(md, PS_LIST_TAIL, "diff_id", PS_DATA_S64, "Primary Key fkey(diff_id) ref diffRun(diff_id)", 0)) {
     20492        psError(PS_ERR_UNKNOWN, false, "failed to add item diff_id");
     20493        psFree(md);
     20494        return false;
     20495    }
     20496    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, "64")) {
     20497        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     20498        psFree(md);
     20499        return false;
     20500    }
     20501
     20502    bool status = psDBCreateTable(dbh, MAGICINPUTSKYFILE_TABLE_NAME, md);
     20503
     20504    psFree(md);
     20505
     20506    return status;
     20507}
     20508
     20509bool magicInputSkyfileDropTable(psDB *dbh)
     20510{
     20511    return psDBDropTable(dbh, MAGICINPUTSKYFILE_TABLE_NAME);
     20512}
     20513
     20514bool magicInputSkyfileInsert(psDB * dbh, psS64 magic_id, psS64 diff_id, const char *node)
     20515{
     20516    psMetadata *md = psMetadataAlloc();
     20517    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, magic_id)) {
     20518        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20519        psFree(md);
     20520        return false;
     20521    }
     20522    if (!psMetadataAdd(md, PS_LIST_TAIL, "diff_id", PS_DATA_S64, NULL, diff_id)) {
     20523        psError(PS_ERR_UNKNOWN, false, "failed to add item diff_id");
     20524        psFree(md);
     20525        return false;
     20526    }
     20527    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, node)) {
     20528        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     20529        psFree(md);
     20530        return false;
     20531    }
     20532
     20533    bool status = psDBInsertOneRow(dbh, MAGICINPUTSKYFILE_TABLE_NAME, md);
     20534    psFree(md);
     20535
     20536    return status;
     20537}
     20538
     20539long long magicInputSkyfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     20540{
     20541    long long       deleted = 0;
     20542
     20543    long long count = psDBDeleteRows(dbh, MAGICINPUTSKYFILE_TABLE_NAME, where, limit);
     20544    if (count < 0) {
     20545        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicInputSkyfile");
     20546        return count;
     20547
     20548        deleted += count;
     20549    }
     20550
     20551    return deleted;
     20552}
     20553bool magicInputSkyfileInsertObject(psDB *dbh, magicInputSkyfileRow *object)
     20554{
     20555    return magicInputSkyfileInsert(dbh, object->magic_id, object->diff_id, object->node);
     20556}
     20557
     20558bool magicInputSkyfileInsertObjects(psDB *dbh, psArray *objects)
     20559{
     20560    for (long i = 0; i < psArrayLength(objects); i++) {
     20561        if (!magicInputSkyfileInsertObject(dbh, objects->data[i])) {
     20562            return false;
     20563        }
     20564    }
     20565
     20566    return true;
     20567}
     20568
     20569bool magicInputSkyfileInsertFits(psDB *dbh, const psFits *fits)
     20570{
     20571    psArray         *rowSet;
     20572
     20573    // move to (the first?) extension named  MAGICINPUTSKYFILE_TABLE_NAME
     20574    if (!psFitsMoveExtName(fits, MAGICINPUTSKYFILE_TABLE_NAME)) {
     20575        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", MAGICINPUTSKYFILE_TABLE_NAME);
     20576        return false;
     20577    }
     20578
     20579    // check HDU type
     20580    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     20581        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     20582        return false;
     20583    }
     20584
     20585    // read fits table
     20586    rowSet = psFitsReadTable(fits);
     20587    if (!rowSet) {
     20588        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     20589        psFree(rowSet);
     20590        return false;
     20591    }
     20592
     20593    if (!psDBInsertRows(dbh, MAGICINPUTSKYFILE_TABLE_NAME, rowSet)) {
     20594        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     20595        psFree(rowSet);
     20596        return false;
     20597    }
     20598
     20599    psFree(rowSet);
     20600
     20601    return true;
     20602}
     20603
     20604bool magicInputSkyfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     20605{
     20606    psArray         *rowSet;
     20607
     20608    rowSet = psDBSelectRows(dbh, MAGICINPUTSKYFILE_TABLE_NAME, where, limit);
     20609    if (!rowSet) {
     20610        return false;
     20611    }
     20612
     20613    // output to fits
     20614    if (!psFitsWriteTable(fits, NULL, rowSet, MAGICINPUTSKYFILE_TABLE_NAME)) {
     20615        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     20616        psFree(rowSet);
     20617        return false;
     20618    }
     20619
     20620    psFree(rowSet);
     20621
     20622    return true;
     20623}
     20624
     20625psMetadata *magicInputSkyfileMetadataFromObject(const magicInputSkyfileRow *object)
     20626{
     20627    psMetadata *md = psMetadataAlloc();
     20628    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, object->magic_id)) {
     20629        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20630        psFree(md);
     20631        return false;
     20632    }
     20633    if (!psMetadataAdd(md, PS_LIST_TAIL, "diff_id", PS_DATA_S64, NULL, object->diff_id)) {
     20634        psError(PS_ERR_UNKNOWN, false, "failed to add item diff_id");
     20635        psFree(md);
     20636        return false;
     20637    }
     20638    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, object->node)) {
     20639        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     20640        psFree(md);
     20641        return false;
     20642    }
     20643
     20644
     20645    return md;
     20646}
     20647
     20648magicInputSkyfileRow *magicInputSkyfileObjectFromMetadata(psMetadata *md)
     20649{
     20650
     20651bool status = false;
     20652    psS64 magic_id = psMetadataLookupS64(&status, md, "magic_id");
     20653    if (!status) {
     20654        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item magic_id");
     20655        return false;
     20656    }
     20657    psS64 diff_id = psMetadataLookupS64(&status, md, "diff_id");
     20658    if (!status) {
     20659        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item diff_id");
     20660        return false;
     20661    }
     20662    char* node = psMetadataLookupPtr(&status, md, "node");
     20663    if (!status) {
     20664        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item node");
     20665        return false;
     20666    }
     20667
     20668    return magicInputSkyfileRowAlloc(magic_id, diff_id, node);
     20669}
     20670psArray *magicInputSkyfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     20671{
     20672    psArray         *rowSet;
     20673    psArray         *returnSet;
     20674    psU64           i;
     20675
     20676    rowSet = psDBSelectRows(dbh, MAGICINPUTSKYFILE_TABLE_NAME, where, limit);
     20677    if (!rowSet) {
     20678        return NULL;
     20679    }
     20680
     20681    // convert psMetadata rows to row objects
     20682
     20683    returnSet = psArrayAllocEmpty(rowSet->n);
     20684
     20685    for (i = 0; i < rowSet->n; i++) {
     20686        magicInputSkyfileRow *object = magicInputSkyfileObjectFromMetadata(rowSet->data[i]);
     20687        psArrayAdd(returnSet, 0, object);
     20688        psFree(object);
     20689    }
     20690
     20691    psFree(rowSet);
     20692
     20693    return returnSet;
     20694}
     20695bool magicInputSkyfileDeleteObject(psDB *dbh, const magicInputSkyfileRow *object)
     20696{
     20697    psMetadata *where = magicInputSkyfileMetadataFromObject(object);
     20698    long long count = psDBDeleteRows(dbh, MAGICINPUTSKYFILE_TABLE_NAME, where, 0);
     20699    psFree(where);
     20700    if (count < 0) {
     20701        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicInputSkyfile");
     20702        return false;
     20703    }
     20704    if (count > 1) {
     20705        // XXX should this be a psAbort() instead?  It is possible that
     20706        // having an object match multiple rows was by design.
     20707        psError(PS_ERR_UNKNOWN, true, "magicInputSkyfileRow object matched more then one row.  Check your database schema");
     20708        return false;
     20709    }
     20710
     20711    return true;
     20712}
     20713long long magicInputSkyfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     20714{
     20715    long long       deleted = 0;
     20716
     20717    for (long long i = 0; i < objects->n; i++) {
     20718        magicInputSkyfileRow *object = objects->data[i];
     20719        psMetadata *where = magicInputSkyfileMetadataFromObject(object);
     20720        long long count = psDBDeleteRows(dbh, MAGICINPUTSKYFILE_TABLE_NAME, where, limit);
     20721        psFree(where);
     20722        if (count < 0) {
     20723            psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicInputSkyfile");
     20724            return count;
     20725        }
     20726
     20727        deleted += count;
     20728    }
     20729
     20730    return deleted;
     20731}
     20732bool magicInputSkyfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     20733{
     20734    PS_ASSERT_PTR_NON_NULL(objects, false);
     20735
     20736    psMetadata *output = psMetadataAlloc();
     20737    for (long i = 0; i < psArrayLength(objects); i++) {
     20738        psMetadata *md = magicInputSkyfileMetadataFromObject(objects->data[i]);
     20739        if (!psMetadataAddMetadata(
     20740            output,
     20741            PS_LIST_TAIL,
     20742            MAGICINPUTSKYFILE_TABLE_NAME,
     20743            PS_META_DUPLICATE_OK,
     20744            NULL,
     20745            md
     20746        )) {
     20747            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     20748            psFree(md);
     20749            psFree(output);
     20750            return false;
     20751        }
     20752        psFree(md);
     20753    }
     20754
     20755    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     20756        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     20757        psFree(output);
     20758    }
     20759    psFree(output);
     20760
     20761    return true;
     20762}
     20763bool magicInputSkyfilePrintObject(FILE *stream, magicInputSkyfileRow *object, bool mdcf)
     20764{
     20765    PS_ASSERT_PTR_NON_NULL(object, false);
     20766
     20767    psMetadata *md = magicInputSkyfileMetadataFromObject(object);
     20768
     20769    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     20770        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     20771        psFree(md);
     20772    }
     20773
     20774    psFree(md);
     20775
     20776    return true;
     20777}
     20778static void magicTreeRowFree(magicTreeRow *object);
     20779
     20780magicTreeRow *magicTreeRowAlloc(psS64 magic_id, const char *node, const char *dep)
     20781{
     20782    magicTreeRow    *_object;
     20783
     20784    _object = psAlloc(sizeof(magicTreeRow));
     20785    psMemSetDeallocator(_object, (psFreeFunc)magicTreeRowFree);
     20786
     20787    _object->magic_id = magic_id;
     20788    _object->node = psStringCopy(node);
     20789    _object->dep = psStringCopy(dep);
     20790
     20791    return _object;
     20792}
     20793
     20794static void magicTreeRowFree(magicTreeRow *object)
     20795{
     20796    psFree(object->node);
     20797    psFree(object->dep);
     20798}
     20799
     20800bool magicTreeCreateTable(psDB *dbh)
     20801{
     20802    psMetadata *md = psMetadataAlloc();
     20803    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, "Key fkey(magic_id) ref magicRun(magic_id)", 0)) {
     20804        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20805        psFree(md);
     20806        return false;
     20807    }
     20808    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, "Key INDEX(magic_id, node)", "64")) {
     20809        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     20810        psFree(md);
     20811        return false;
     20812    }
     20813    if (!psMetadataAdd(md, PS_LIST_TAIL, "dep", PS_DATA_STRING, "Key", "64")) {
     20814        psError(PS_ERR_UNKNOWN, false, "failed to add item dep");
     20815        psFree(md);
     20816        return false;
     20817    }
     20818
     20819    bool status = psDBCreateTable(dbh, MAGICTREE_TABLE_NAME, md);
     20820
     20821    psFree(md);
     20822
     20823    return status;
     20824}
     20825
     20826bool magicTreeDropTable(psDB *dbh)
     20827{
     20828    return psDBDropTable(dbh, MAGICTREE_TABLE_NAME);
     20829}
     20830
     20831bool magicTreeInsert(psDB * dbh, psS64 magic_id, const char *node, const char *dep)
     20832{
     20833    psMetadata *md = psMetadataAlloc();
     20834    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, magic_id)) {
     20835        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20836        psFree(md);
     20837        return false;
     20838    }
     20839    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, node)) {
     20840        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     20841        psFree(md);
     20842        return false;
     20843    }
     20844    if (!psMetadataAdd(md, PS_LIST_TAIL, "dep", PS_DATA_STRING, NULL, dep)) {
     20845        psError(PS_ERR_UNKNOWN, false, "failed to add item dep");
     20846        psFree(md);
     20847        return false;
     20848    }
     20849
     20850    bool status = psDBInsertOneRow(dbh, MAGICTREE_TABLE_NAME, md);
     20851    psFree(md);
     20852
     20853    return status;
     20854}
     20855
     20856long long magicTreeDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     20857{
     20858    long long       deleted = 0;
     20859
     20860    long long count = psDBDeleteRows(dbh, MAGICTREE_TABLE_NAME, where, limit);
     20861    if (count < 0) {
     20862        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicTree");
     20863        return count;
     20864
     20865        deleted += count;
     20866    }
     20867
     20868    return deleted;
     20869}
     20870bool magicTreeInsertObject(psDB *dbh, magicTreeRow *object)
     20871{
     20872    return magicTreeInsert(dbh, object->magic_id, object->node, object->dep);
     20873}
     20874
     20875bool magicTreeInsertObjects(psDB *dbh, psArray *objects)
     20876{
     20877    for (long i = 0; i < psArrayLength(objects); i++) {
     20878        if (!magicTreeInsertObject(dbh, objects->data[i])) {
     20879            return false;
     20880        }
     20881    }
     20882
     20883    return true;
     20884}
     20885
     20886bool magicTreeInsertFits(psDB *dbh, const psFits *fits)
     20887{
     20888    psArray         *rowSet;
     20889
     20890    // move to (the first?) extension named  MAGICTREE_TABLE_NAME
     20891    if (!psFitsMoveExtName(fits, MAGICTREE_TABLE_NAME)) {
     20892        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", MAGICTREE_TABLE_NAME);
     20893        return false;
     20894    }
     20895
     20896    // check HDU type
     20897    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     20898        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     20899        return false;
     20900    }
     20901
     20902    // read fits table
     20903    rowSet = psFitsReadTable(fits);
     20904    if (!rowSet) {
     20905        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     20906        psFree(rowSet);
     20907        return false;
     20908    }
     20909
     20910    if (!psDBInsertRows(dbh, MAGICTREE_TABLE_NAME, rowSet)) {
     20911        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     20912        psFree(rowSet);
     20913        return false;
     20914    }
     20915
     20916    psFree(rowSet);
     20917
     20918    return true;
     20919}
     20920
     20921bool magicTreeSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     20922{
     20923    psArray         *rowSet;
     20924
     20925    rowSet = psDBSelectRows(dbh, MAGICTREE_TABLE_NAME, where, limit);
     20926    if (!rowSet) {
     20927        return false;
     20928    }
     20929
     20930    // output to fits
     20931    if (!psFitsWriteTable(fits, NULL, rowSet, MAGICTREE_TABLE_NAME)) {
     20932        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     20933        psFree(rowSet);
     20934        return false;
     20935    }
     20936
     20937    psFree(rowSet);
     20938
     20939    return true;
     20940}
     20941
     20942psMetadata *magicTreeMetadataFromObject(const magicTreeRow *object)
     20943{
     20944    psMetadata *md = psMetadataAlloc();
     20945    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, object->magic_id)) {
     20946        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     20947        psFree(md);
     20948        return false;
     20949    }
     20950    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, object->node)) {
     20951        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     20952        psFree(md);
     20953        return false;
     20954    }
     20955    if (!psMetadataAdd(md, PS_LIST_TAIL, "dep", PS_DATA_STRING, NULL, object->dep)) {
     20956        psError(PS_ERR_UNKNOWN, false, "failed to add item dep");
     20957        psFree(md);
     20958        return false;
     20959    }
     20960
     20961
     20962    return md;
     20963}
     20964
     20965magicTreeRow *magicTreeObjectFromMetadata(psMetadata *md)
     20966{
     20967
     20968bool status = false;
     20969    psS64 magic_id = psMetadataLookupS64(&status, md, "magic_id");
     20970    if (!status) {
     20971        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item magic_id");
     20972        return false;
     20973    }
     20974    char* node = psMetadataLookupPtr(&status, md, "node");
     20975    if (!status) {
     20976        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item node");
     20977        return false;
     20978    }
     20979    char* dep = psMetadataLookupPtr(&status, md, "dep");
     20980    if (!status) {
     20981        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item dep");
     20982        return false;
     20983    }
     20984
     20985    return magicTreeRowAlloc(magic_id, node, dep);
     20986}
     20987psArray *magicTreeSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     20988{
     20989    psArray         *rowSet;
     20990    psArray         *returnSet;
     20991    psU64           i;
     20992
     20993    rowSet = psDBSelectRows(dbh, MAGICTREE_TABLE_NAME, where, limit);
     20994    if (!rowSet) {
     20995        return NULL;
     20996    }
     20997
     20998    // convert psMetadata rows to row objects
     20999
     21000    returnSet = psArrayAllocEmpty(rowSet->n);
     21001
     21002    for (i = 0; i < rowSet->n; i++) {
     21003        magicTreeRow *object = magicTreeObjectFromMetadata(rowSet->data[i]);
     21004        psArrayAdd(returnSet, 0, object);
     21005        psFree(object);
     21006    }
     21007
     21008    psFree(rowSet);
     21009
     21010    return returnSet;
     21011}
     21012bool magicTreeDeleteObject(psDB *dbh, const magicTreeRow *object)
     21013{
     21014    psMetadata *where = magicTreeMetadataFromObject(object);
     21015    long long count = psDBDeleteRows(dbh, MAGICTREE_TABLE_NAME, where, 0);
     21016    psFree(where);
     21017    if (count < 0) {
     21018        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicTree");
     21019        return false;
     21020    }
     21021    if (count > 1) {
     21022        // XXX should this be a psAbort() instead?  It is possible that
     21023        // having an object match multiple rows was by design.
     21024        psError(PS_ERR_UNKNOWN, true, "magicTreeRow object matched more then one row.  Check your database schema");
     21025        return false;
     21026    }
     21027
     21028    return true;
     21029}
     21030long long magicTreeDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     21031{
     21032    long long       deleted = 0;
     21033
     21034    for (long long i = 0; i < objects->n; i++) {
     21035        magicTreeRow *object = objects->data[i];
     21036        psMetadata *where = magicTreeMetadataFromObject(object);
     21037        long long count = psDBDeleteRows(dbh, MAGICTREE_TABLE_NAME, where, limit);
     21038        psFree(where);
     21039        if (count < 0) {
     21040            psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicTree");
     21041            return count;
     21042        }
     21043
     21044        deleted += count;
     21045    }
     21046
     21047    return deleted;
     21048}
     21049bool magicTreePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     21050{
     21051    PS_ASSERT_PTR_NON_NULL(objects, false);
     21052
     21053    psMetadata *output = psMetadataAlloc();
     21054    for (long i = 0; i < psArrayLength(objects); i++) {
     21055        psMetadata *md = magicTreeMetadataFromObject(objects->data[i]);
     21056        if (!psMetadataAddMetadata(
     21057            output,
     21058            PS_LIST_TAIL,
     21059            MAGICTREE_TABLE_NAME,
     21060            PS_META_DUPLICATE_OK,
     21061            NULL,
     21062            md
     21063        )) {
     21064            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     21065            psFree(md);
     21066            psFree(output);
     21067            return false;
     21068        }
     21069        psFree(md);
     21070    }
     21071
     21072    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     21073        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     21074        psFree(output);
     21075    }
     21076    psFree(output);
     21077
     21078    return true;
     21079}
     21080bool magicTreePrintObject(FILE *stream, magicTreeRow *object, bool mdcf)
     21081{
     21082    PS_ASSERT_PTR_NON_NULL(object, false);
     21083
     21084    psMetadata *md = magicTreeMetadataFromObject(object);
     21085
     21086    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     21087        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     21088        psFree(md);
     21089    }
     21090
     21091    psFree(md);
     21092
     21093    return true;
     21094}
     21095static void magicNodeResultRowFree(magicNodeResultRow *object);
     21096
     21097magicNodeResultRow *magicNodeResultRowAlloc(psS64 magic_id, const char *node, const char *uri)
     21098{
     21099    magicNodeResultRow *_object;
     21100
     21101    _object = psAlloc(sizeof(magicNodeResultRow));
     21102    psMemSetDeallocator(_object, (psFreeFunc)magicNodeResultRowFree);
     21103
     21104    _object->magic_id = magic_id;
     21105    _object->node = psStringCopy(node);
     21106    _object->uri = psStringCopy(uri);
     21107
     21108    return _object;
     21109}
     21110
     21111static void magicNodeResultRowFree(magicNodeResultRow *object)
     21112{
     21113    psFree(object->node);
     21114    psFree(object->uri);
     21115}
     21116
     21117bool magicNodeResultCreateTable(psDB *dbh)
     21118{
     21119    psMetadata *md = psMetadataAlloc();
     21120    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, "Primary Key fkey(magic_id) ref magicRun(magic_id)", 0)) {
     21121        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21122        psFree(md);
     21123        return false;
     21124    }
     21125    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, "Primary Key fkey(magic_id, node) ref magicTree(magic_id, node)", "64")) {
     21126        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     21127        psFree(md);
     21128        return false;
     21129    }
     21130    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     21131        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21132        psFree(md);
     21133        return false;
     21134    }
     21135
     21136    bool status = psDBCreateTable(dbh, MAGICNODERESULT_TABLE_NAME, md);
     21137
     21138    psFree(md);
     21139
     21140    return status;
     21141}
     21142
     21143bool magicNodeResultDropTable(psDB *dbh)
     21144{
     21145    return psDBDropTable(dbh, MAGICNODERESULT_TABLE_NAME);
     21146}
     21147
     21148bool magicNodeResultInsert(psDB * dbh, psS64 magic_id, const char *node, const char *uri)
     21149{
     21150    psMetadata *md = psMetadataAlloc();
     21151    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, magic_id)) {
     21152        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21153        psFree(md);
     21154        return false;
     21155    }
     21156    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, node)) {
     21157        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     21158        psFree(md);
     21159        return false;
     21160    }
     21161    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     21162        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21163        psFree(md);
     21164        return false;
     21165    }
     21166
     21167    bool status = psDBInsertOneRow(dbh, MAGICNODERESULT_TABLE_NAME, md);
     21168    psFree(md);
     21169
     21170    return status;
     21171}
     21172
     21173long long magicNodeResultDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     21174{
     21175    long long       deleted = 0;
     21176
     21177    long long count = psDBDeleteRows(dbh, MAGICNODERESULT_TABLE_NAME, where, limit);
     21178    if (count < 0) {
     21179        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicNodeResult");
     21180        return count;
     21181
     21182        deleted += count;
     21183    }
     21184
     21185    return deleted;
     21186}
     21187bool magicNodeResultInsertObject(psDB *dbh, magicNodeResultRow *object)
     21188{
     21189    return magicNodeResultInsert(dbh, object->magic_id, object->node, object->uri);
     21190}
     21191
     21192bool magicNodeResultInsertObjects(psDB *dbh, psArray *objects)
     21193{
     21194    for (long i = 0; i < psArrayLength(objects); i++) {
     21195        if (!magicNodeResultInsertObject(dbh, objects->data[i])) {
     21196            return false;
     21197        }
     21198    }
     21199
     21200    return true;
     21201}
     21202
     21203bool magicNodeResultInsertFits(psDB *dbh, const psFits *fits)
     21204{
     21205    psArray         *rowSet;
     21206
     21207    // move to (the first?) extension named  MAGICNODERESULT_TABLE_NAME
     21208    if (!psFitsMoveExtName(fits, MAGICNODERESULT_TABLE_NAME)) {
     21209        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", MAGICNODERESULT_TABLE_NAME);
     21210        return false;
     21211    }
     21212
     21213    // check HDU type
     21214    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     21215        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     21216        return false;
     21217    }
     21218
     21219    // read fits table
     21220    rowSet = psFitsReadTable(fits);
     21221    if (!rowSet) {
     21222        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     21223        psFree(rowSet);
     21224        return false;
     21225    }
     21226
     21227    if (!psDBInsertRows(dbh, MAGICNODERESULT_TABLE_NAME, rowSet)) {
     21228        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     21229        psFree(rowSet);
     21230        return false;
     21231    }
     21232
     21233    psFree(rowSet);
     21234
     21235    return true;
     21236}
     21237
     21238bool magicNodeResultSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     21239{
     21240    psArray         *rowSet;
     21241
     21242    rowSet = psDBSelectRows(dbh, MAGICNODERESULT_TABLE_NAME, where, limit);
     21243    if (!rowSet) {
     21244        return false;
     21245    }
     21246
     21247    // output to fits
     21248    if (!psFitsWriteTable(fits, NULL, rowSet, MAGICNODERESULT_TABLE_NAME)) {
     21249        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     21250        psFree(rowSet);
     21251        return false;
     21252    }
     21253
     21254    psFree(rowSet);
     21255
     21256    return true;
     21257}
     21258
     21259psMetadata *magicNodeResultMetadataFromObject(const magicNodeResultRow *object)
     21260{
     21261    psMetadata *md = psMetadataAlloc();
     21262    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, object->magic_id)) {
     21263        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21264        psFree(md);
     21265        return false;
     21266    }
     21267    if (!psMetadataAdd(md, PS_LIST_TAIL, "node", PS_DATA_STRING, NULL, object->node)) {
     21268        psError(PS_ERR_UNKNOWN, false, "failed to add item node");
     21269        psFree(md);
     21270        return false;
     21271    }
     21272    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     21273        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21274        psFree(md);
     21275        return false;
     21276    }
     21277
     21278
     21279    return md;
     21280}
     21281
     21282magicNodeResultRow *magicNodeResultObjectFromMetadata(psMetadata *md)
     21283{
     21284
     21285bool status = false;
     21286    psS64 magic_id = psMetadataLookupS64(&status, md, "magic_id");
     21287    if (!status) {
     21288        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item magic_id");
     21289        return false;
     21290    }
     21291    char* node = psMetadataLookupPtr(&status, md, "node");
     21292    if (!status) {
     21293        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item node");
     21294        return false;
     21295    }
     21296    char* uri = psMetadataLookupPtr(&status, md, "uri");
     21297    if (!status) {
     21298        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     21299        return false;
     21300    }
     21301
     21302    return magicNodeResultRowAlloc(magic_id, node, uri);
     21303}
     21304psArray *magicNodeResultSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     21305{
     21306    psArray         *rowSet;
     21307    psArray         *returnSet;
     21308    psU64           i;
     21309
     21310    rowSet = psDBSelectRows(dbh, MAGICNODERESULT_TABLE_NAME, where, limit);
     21311    if (!rowSet) {
     21312        return NULL;
     21313    }
     21314
     21315    // convert psMetadata rows to row objects
     21316
     21317    returnSet = psArrayAllocEmpty(rowSet->n);
     21318
     21319    for (i = 0; i < rowSet->n; i++) {
     21320        magicNodeResultRow *object = magicNodeResultObjectFromMetadata(rowSet->data[i]);
     21321        psArrayAdd(returnSet, 0, object);
     21322        psFree(object);
     21323    }
     21324
     21325    psFree(rowSet);
     21326
     21327    return returnSet;
     21328}
     21329bool magicNodeResultDeleteObject(psDB *dbh, const magicNodeResultRow *object)
     21330{
     21331    psMetadata *where = magicNodeResultMetadataFromObject(object);
     21332    long long count = psDBDeleteRows(dbh, MAGICNODERESULT_TABLE_NAME, where, 0);
     21333    psFree(where);
     21334    if (count < 0) {
     21335        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicNodeResult");
     21336        return false;
     21337    }
     21338    if (count > 1) {
     21339        // XXX should this be a psAbort() instead?  It is possible that
     21340        // having an object match multiple rows was by design.
     21341        psError(PS_ERR_UNKNOWN, true, "magicNodeResultRow object matched more then one row.  Check your database schema");
     21342        return false;
     21343    }
     21344
     21345    return true;
     21346}
     21347long long magicNodeResultDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     21348{
     21349    long long       deleted = 0;
     21350
     21351    for (long long i = 0; i < objects->n; i++) {
     21352        magicNodeResultRow *object = objects->data[i];
     21353        psMetadata *where = magicNodeResultMetadataFromObject(object);
     21354        long long count = psDBDeleteRows(dbh, MAGICNODERESULT_TABLE_NAME, where, limit);
     21355        psFree(where);
     21356        if (count < 0) {
     21357            psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicNodeResult");
     21358            return count;
     21359        }
     21360
     21361        deleted += count;
     21362    }
     21363
     21364    return deleted;
     21365}
     21366bool magicNodeResultPrintObjects(FILE *stream, psArray *objects, bool mdcf)
     21367{
     21368    PS_ASSERT_PTR_NON_NULL(objects, false);
     21369
     21370    psMetadata *output = psMetadataAlloc();
     21371    for (long i = 0; i < psArrayLength(objects); i++) {
     21372        psMetadata *md = magicNodeResultMetadataFromObject(objects->data[i]);
     21373        if (!psMetadataAddMetadata(
     21374            output,
     21375            PS_LIST_TAIL,
     21376            MAGICNODERESULT_TABLE_NAME,
     21377            PS_META_DUPLICATE_OK,
     21378            NULL,
     21379            md
     21380        )) {
     21381            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     21382            psFree(md);
     21383            psFree(output);
     21384            return false;
     21385        }
     21386        psFree(md);
     21387    }
     21388
     21389    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     21390        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     21391        psFree(output);
     21392    }
     21393    psFree(output);
     21394
     21395    return true;
     21396}
     21397bool magicNodeResultPrintObject(FILE *stream, magicNodeResultRow *object, bool mdcf)
     21398{
     21399    PS_ASSERT_PTR_NON_NULL(object, false);
     21400
     21401    psMetadata *md = magicNodeResultMetadataFromObject(object);
     21402
     21403    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     21404        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     21405        psFree(md);
     21406    }
     21407
     21408    psFree(md);
     21409
     21410    return true;
     21411}
     21412static void magicMaskRowFree(magicMaskRow *object);
     21413
     21414magicMaskRow *magicMaskRowAlloc(psS64 magic_id, const char *uri)
     21415{
     21416    magicMaskRow    *_object;
     21417
     21418    _object = psAlloc(sizeof(magicMaskRow));
     21419    psMemSetDeallocator(_object, (psFreeFunc)magicMaskRowFree);
     21420
     21421    _object->magic_id = magic_id;
     21422    _object->uri = psStringCopy(uri);
     21423
     21424    return _object;
     21425}
     21426
     21427static void magicMaskRowFree(magicMaskRow *object)
     21428{
     21429    psFree(object->uri);
     21430}
     21431
     21432bool magicMaskCreateTable(psDB *dbh)
     21433{
     21434    psMetadata *md = psMetadataAlloc();
     21435    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, "Primary Key fkey(magic_id) ref magicRun(magic_id)", 0)) {
     21436        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21437        psFree(md);
     21438        return false;
     21439    }
     21440    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     21441        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21442        psFree(md);
     21443        return false;
     21444    }
     21445
     21446    bool status = psDBCreateTable(dbh, MAGICMASK_TABLE_NAME, md);
     21447
     21448    psFree(md);
     21449
     21450    return status;
     21451}
     21452
     21453bool magicMaskDropTable(psDB *dbh)
     21454{
     21455    return psDBDropTable(dbh, MAGICMASK_TABLE_NAME);
     21456}
     21457
     21458bool magicMaskInsert(psDB * dbh, psS64 magic_id, const char *uri)
     21459{
     21460    psMetadata *md = psMetadataAlloc();
     21461    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, magic_id)) {
     21462        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21463        psFree(md);
     21464        return false;
     21465    }
     21466    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     21467        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21468        psFree(md);
     21469        return false;
     21470    }
     21471
     21472    bool status = psDBInsertOneRow(dbh, MAGICMASK_TABLE_NAME, md);
     21473    psFree(md);
     21474
     21475    return status;
     21476}
     21477
     21478long long magicMaskDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     21479{
     21480    long long       deleted = 0;
     21481
     21482    long long count = psDBDeleteRows(dbh, MAGICMASK_TABLE_NAME, where, limit);
     21483    if (count < 0) {
     21484        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicMask");
     21485        return count;
     21486
     21487        deleted += count;
     21488    }
     21489
     21490    return deleted;
     21491}
     21492bool magicMaskInsertObject(psDB *dbh, magicMaskRow *object)
     21493{
     21494    return magicMaskInsert(dbh, object->magic_id, object->uri);
     21495}
     21496
     21497bool magicMaskInsertObjects(psDB *dbh, psArray *objects)
     21498{
     21499    for (long i = 0; i < psArrayLength(objects); i++) {
     21500        if (!magicMaskInsertObject(dbh, objects->data[i])) {
     21501            return false;
     21502        }
     21503    }
     21504
     21505    return true;
     21506}
     21507
     21508bool magicMaskInsertFits(psDB *dbh, const psFits *fits)
     21509{
     21510    psArray         *rowSet;
     21511
     21512    // move to (the first?) extension named  MAGICMASK_TABLE_NAME
     21513    if (!psFitsMoveExtName(fits, MAGICMASK_TABLE_NAME)) {
     21514        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", MAGICMASK_TABLE_NAME);
     21515        return false;
     21516    }
     21517
     21518    // check HDU type
     21519    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     21520        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     21521        return false;
     21522    }
     21523
     21524    // read fits table
     21525    rowSet = psFitsReadTable(fits);
     21526    if (!rowSet) {
     21527        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     21528        psFree(rowSet);
     21529        return false;
     21530    }
     21531
     21532    if (!psDBInsertRows(dbh, MAGICMASK_TABLE_NAME, rowSet)) {
     21533        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     21534        psFree(rowSet);
     21535        return false;
     21536    }
     21537
     21538    psFree(rowSet);
     21539
     21540    return true;
     21541}
     21542
     21543bool magicMaskSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     21544{
     21545    psArray         *rowSet;
     21546
     21547    rowSet = psDBSelectRows(dbh, MAGICMASK_TABLE_NAME, where, limit);
     21548    if (!rowSet) {
     21549        return false;
     21550    }
     21551
     21552    // output to fits
     21553    if (!psFitsWriteTable(fits, NULL, rowSet, MAGICMASK_TABLE_NAME)) {
     21554        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     21555        psFree(rowSet);
     21556        return false;
     21557    }
     21558
     21559    psFree(rowSet);
     21560
     21561    return true;
     21562}
     21563
     21564psMetadata *magicMaskMetadataFromObject(const magicMaskRow *object)
     21565{
     21566    psMetadata *md = psMetadataAlloc();
     21567    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, object->magic_id)) {
     21568        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21569        psFree(md);
     21570        return false;
     21571    }
     21572    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     21573        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21574        psFree(md);
     21575        return false;
     21576    }
     21577
     21578
     21579    return md;
     21580}
     21581
     21582magicMaskRow *magicMaskObjectFromMetadata(psMetadata *md)
     21583{
     21584
     21585bool status = false;
     21586    psS64 magic_id = psMetadataLookupS64(&status, md, "magic_id");
     21587    if (!status) {
     21588        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item magic_id");
     21589        return false;
     21590    }
     21591    char* uri = psMetadataLookupPtr(&status, md, "uri");
     21592    if (!status) {
     21593        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     21594        return false;
     21595    }
     21596
     21597    return magicMaskRowAlloc(magic_id, uri);
     21598}
     21599psArray *magicMaskSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     21600{
     21601    psArray         *rowSet;
     21602    psArray         *returnSet;
     21603    psU64           i;
     21604
     21605    rowSet = psDBSelectRows(dbh, MAGICMASK_TABLE_NAME, where, limit);
     21606    if (!rowSet) {
     21607        return NULL;
     21608    }
     21609
     21610    // convert psMetadata rows to row objects
     21611
     21612    returnSet = psArrayAllocEmpty(rowSet->n);
     21613
     21614    for (i = 0; i < rowSet->n; i++) {
     21615        magicMaskRow *object = magicMaskObjectFromMetadata(rowSet->data[i]);
     21616        psArrayAdd(returnSet, 0, object);
     21617        psFree(object);
     21618    }
     21619
     21620    psFree(rowSet);
     21621
     21622    return returnSet;
     21623}
     21624bool magicMaskDeleteObject(psDB *dbh, const magicMaskRow *object)
     21625{
     21626    psMetadata *where = magicMaskMetadataFromObject(object);
     21627    long long count = psDBDeleteRows(dbh, MAGICMASK_TABLE_NAME, where, 0);
     21628    psFree(where);
     21629    if (count < 0) {
     21630        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicMask");
     21631        return false;
     21632    }
     21633    if (count > 1) {
     21634        // XXX should this be a psAbort() instead?  It is possible that
     21635        // having an object match multiple rows was by design.
     21636        psError(PS_ERR_UNKNOWN, true, "magicMaskRow object matched more then one row.  Check your database schema");
     21637        return false;
     21638    }
     21639
     21640    return true;
     21641}
     21642long long magicMaskDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     21643{
     21644    long long       deleted = 0;
     21645
     21646    for (long long i = 0; i < objects->n; i++) {
     21647        magicMaskRow *object = objects->data[i];
     21648        psMetadata *where = magicMaskMetadataFromObject(object);
     21649        long long count = psDBDeleteRows(dbh, MAGICMASK_TABLE_NAME, where, limit);
     21650        psFree(where);
     21651        if (count < 0) {
     21652            psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicMask");
     21653            return count;
     21654        }
     21655
     21656        deleted += count;
     21657    }
     21658
     21659    return deleted;
     21660}
     21661bool magicMaskPrintObjects(FILE *stream, psArray *objects, bool mdcf)
     21662{
     21663    PS_ASSERT_PTR_NON_NULL(objects, false);
     21664
     21665    psMetadata *output = psMetadataAlloc();
     21666    for (long i = 0; i < psArrayLength(objects); i++) {
     21667        psMetadata *md = magicMaskMetadataFromObject(objects->data[i]);
     21668        if (!psMetadataAddMetadata(
     21669            output,
     21670            PS_LIST_TAIL,
     21671            MAGICMASK_TABLE_NAME,
     21672            PS_META_DUPLICATE_OK,
     21673            NULL,
     21674            md
     21675        )) {
     21676            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     21677            psFree(md);
     21678            psFree(output);
     21679            return false;
     21680        }
     21681        psFree(md);
     21682    }
     21683
     21684    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     21685        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     21686        psFree(output);
     21687    }
     21688    psFree(output);
     21689
     21690    return true;
     21691}
     21692bool magicMaskPrintObject(FILE *stream, magicMaskRow *object, bool mdcf)
     21693{
     21694    PS_ASSERT_PTR_NON_NULL(object, false);
     21695
     21696    psMetadata *md = magicMaskMetadataFromObject(object);
     21697
     21698    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     21699        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     21700        psFree(md);
     21701    }
     21702
     21703    psFree(md);
     21704
     21705    return true;
     21706}
     21707static void magicSkyfileMaskRowFree(magicSkyfileMaskRow *object);
     21708
     21709magicSkyfileMaskRow *magicSkyfileMaskRowAlloc(psS64 magic_id, psS64 diff_id, const char *uri)
     21710{
     21711    magicSkyfileMaskRow *_object;
     21712
     21713    _object = psAlloc(sizeof(magicSkyfileMaskRow));
     21714    psMemSetDeallocator(_object, (psFreeFunc)magicSkyfileMaskRowFree);
     21715
     21716    _object->magic_id = magic_id;
     21717    _object->diff_id = diff_id;
     21718    _object->uri = psStringCopy(uri);
     21719
     21720    return _object;
     21721}
     21722
     21723static void magicSkyfileMaskRowFree(magicSkyfileMaskRow *object)
     21724{
     21725    psFree(object->uri);
     21726}
     21727
     21728bool magicSkyfileMaskCreateTable(psDB *dbh)
     21729{
     21730    psMetadata *md = psMetadataAlloc();
     21731    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, "Primary Key fkey(magic_id) ref magicRun(magic_id)", 0)) {
     21732        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21733        psFree(md);
     21734        return false;
     21735    }
     21736    if (!psMetadataAdd(md, PS_LIST_TAIL, "diff_id", PS_DATA_S64, "Primary Key fkey(magic_id, diff_id) ref magicInputSkyfile(magic_id, diff_id)", 0)) {
     21737        psError(PS_ERR_UNKNOWN, false, "failed to add item diff_id");
     21738        psFree(md);
     21739        return false;
     21740    }
     21741    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, "fkey(magic_id) ref magicMask(magic_id)", "255")) {
     21742        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21743        psFree(md);
     21744        return false;
     21745    }
     21746
     21747    bool status = psDBCreateTable(dbh, MAGICSKYFILEMASK_TABLE_NAME, md);
     21748
     21749    psFree(md);
     21750
     21751    return status;
     21752}
     21753
     21754bool magicSkyfileMaskDropTable(psDB *dbh)
     21755{
     21756    return psDBDropTable(dbh, MAGICSKYFILEMASK_TABLE_NAME);
     21757}
     21758
     21759bool magicSkyfileMaskInsert(psDB * dbh, psS64 magic_id, psS64 diff_id, const char *uri)
     21760{
     21761    psMetadata *md = psMetadataAlloc();
     21762    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, magic_id)) {
     21763        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21764        psFree(md);
     21765        return false;
     21766    }
     21767    if (!psMetadataAdd(md, PS_LIST_TAIL, "diff_id", PS_DATA_S64, NULL, diff_id)) {
     21768        psError(PS_ERR_UNKNOWN, false, "failed to add item diff_id");
     21769        psFree(md);
     21770        return false;
     21771    }
     21772    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     21773        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21774        psFree(md);
     21775        return false;
     21776    }
     21777
     21778    bool status = psDBInsertOneRow(dbh, MAGICSKYFILEMASK_TABLE_NAME, md);
     21779    psFree(md);
     21780
     21781    return status;
     21782}
     21783
     21784long long magicSkyfileMaskDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     21785{
     21786    long long       deleted = 0;
     21787
     21788    long long count = psDBDeleteRows(dbh, MAGICSKYFILEMASK_TABLE_NAME, where, limit);
     21789    if (count < 0) {
     21790        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicSkyfileMask");
     21791        return count;
     21792
     21793        deleted += count;
     21794    }
     21795
     21796    return deleted;
     21797}
     21798bool magicSkyfileMaskInsertObject(psDB *dbh, magicSkyfileMaskRow *object)
     21799{
     21800    return magicSkyfileMaskInsert(dbh, object->magic_id, object->diff_id, object->uri);
     21801}
     21802
     21803bool magicSkyfileMaskInsertObjects(psDB *dbh, psArray *objects)
     21804{
     21805    for (long i = 0; i < psArrayLength(objects); i++) {
     21806        if (!magicSkyfileMaskInsertObject(dbh, objects->data[i])) {
     21807            return false;
     21808        }
     21809    }
     21810
     21811    return true;
     21812}
     21813
     21814bool magicSkyfileMaskInsertFits(psDB *dbh, const psFits *fits)
     21815{
     21816    psArray         *rowSet;
     21817
     21818    // move to (the first?) extension named  MAGICSKYFILEMASK_TABLE_NAME
     21819    if (!psFitsMoveExtName(fits, MAGICSKYFILEMASK_TABLE_NAME)) {
     21820        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", MAGICSKYFILEMASK_TABLE_NAME);
     21821        return false;
     21822    }
     21823
     21824    // check HDU type
     21825    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     21826        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     21827        return false;
     21828    }
     21829
     21830    // read fits table
     21831    rowSet = psFitsReadTable(fits);
     21832    if (!rowSet) {
     21833        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     21834        psFree(rowSet);
     21835        return false;
     21836    }
     21837
     21838    if (!psDBInsertRows(dbh, MAGICSKYFILEMASK_TABLE_NAME, rowSet)) {
     21839        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     21840        psFree(rowSet);
     21841        return false;
     21842    }
     21843
     21844    psFree(rowSet);
     21845
     21846    return true;
     21847}
     21848
     21849bool magicSkyfileMaskSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     21850{
     21851    psArray         *rowSet;
     21852
     21853    rowSet = psDBSelectRows(dbh, MAGICSKYFILEMASK_TABLE_NAME, where, limit);
     21854    if (!rowSet) {
     21855        return false;
     21856    }
     21857
     21858    // output to fits
     21859    if (!psFitsWriteTable(fits, NULL, rowSet, MAGICSKYFILEMASK_TABLE_NAME)) {
     21860        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     21861        psFree(rowSet);
     21862        return false;
     21863    }
     21864
     21865    psFree(rowSet);
     21866
     21867    return true;
     21868}
     21869
     21870psMetadata *magicSkyfileMaskMetadataFromObject(const magicSkyfileMaskRow *object)
     21871{
     21872    psMetadata *md = psMetadataAlloc();
     21873    if (!psMetadataAdd(md, PS_LIST_TAIL, "magic_id", PS_DATA_S64, NULL, object->magic_id)) {
     21874        psError(PS_ERR_UNKNOWN, false, "failed to add item magic_id");
     21875        psFree(md);
     21876        return false;
     21877    }
     21878    if (!psMetadataAdd(md, PS_LIST_TAIL, "diff_id", PS_DATA_S64, NULL, object->diff_id)) {
     21879        psError(PS_ERR_UNKNOWN, false, "failed to add item diff_id");
     21880        psFree(md);
     21881        return false;
     21882    }
     21883    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     21884        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     21885        psFree(md);
     21886        return false;
     21887    }
     21888
     21889
     21890    return md;
     21891}
     21892
     21893magicSkyfileMaskRow *magicSkyfileMaskObjectFromMetadata(psMetadata *md)
     21894{
     21895
     21896bool status = false;
     21897    psS64 magic_id = psMetadataLookupS64(&status, md, "magic_id");
     21898    if (!status) {
     21899        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item magic_id");
     21900        return false;
     21901    }
     21902    psS64 diff_id = psMetadataLookupS64(&status, md, "diff_id");
     21903    if (!status) {
     21904        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item diff_id");
     21905        return false;
     21906    }
     21907    char* uri = psMetadataLookupPtr(&status, md, "uri");
     21908    if (!status) {
     21909        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     21910        return false;
     21911    }
     21912
     21913    return magicSkyfileMaskRowAlloc(magic_id, diff_id, uri);
     21914}
     21915psArray *magicSkyfileMaskSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     21916{
     21917    psArray         *rowSet;
     21918    psArray         *returnSet;
     21919    psU64           i;
     21920
     21921    rowSet = psDBSelectRows(dbh, MAGICSKYFILEMASK_TABLE_NAME, where, limit);
     21922    if (!rowSet) {
     21923        return NULL;
     21924    }
     21925
     21926    // convert psMetadata rows to row objects
     21927
     21928    returnSet = psArrayAllocEmpty(rowSet->n);
     21929
     21930    for (i = 0; i < rowSet->n; i++) {
     21931        magicSkyfileMaskRow *object = magicSkyfileMaskObjectFromMetadata(rowSet->data[i]);
     21932        psArrayAdd(returnSet, 0, object);
     21933        psFree(object);
     21934    }
     21935
     21936    psFree(rowSet);
     21937
     21938    return returnSet;
     21939}
     21940bool magicSkyfileMaskDeleteObject(psDB *dbh, const magicSkyfileMaskRow *object)
     21941{
     21942    psMetadata *where = magicSkyfileMaskMetadataFromObject(object);
     21943    long long count = psDBDeleteRows(dbh, MAGICSKYFILEMASK_TABLE_NAME, where, 0);
     21944    psFree(where);
     21945    if (count < 0) {
     21946        psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicSkyfileMask");
     21947        return false;
     21948    }
     21949    if (count > 1) {
     21950        // XXX should this be a psAbort() instead?  It is possible that
     21951        // having an object match multiple rows was by design.
     21952        psError(PS_ERR_UNKNOWN, true, "magicSkyfileMaskRow object matched more then one row.  Check your database schema");
     21953        return false;
     21954    }
     21955
     21956    return true;
     21957}
     21958long long magicSkyfileMaskDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     21959{
     21960    long long       deleted = 0;
     21961
     21962    for (long long i = 0; i < objects->n; i++) {
     21963        magicSkyfileMaskRow *object = objects->data[i];
     21964        psMetadata *where = magicSkyfileMaskMetadataFromObject(object);
     21965        long long count = psDBDeleteRows(dbh, MAGICSKYFILEMASK_TABLE_NAME, where, limit);
     21966        psFree(where);
     21967        if (count < 0) {
     21968            psError(PS_ERR_UNKNOWN, true, "failed to delete row from magicSkyfileMask");
     21969            return count;
     21970        }
     21971
     21972        deleted += count;
     21973    }
     21974
     21975    return deleted;
     21976}
     21977bool magicSkyfileMaskPrintObjects(FILE *stream, psArray *objects, bool mdcf)
     21978{
     21979    PS_ASSERT_PTR_NON_NULL(objects, false);
     21980
     21981    psMetadata *output = psMetadataAlloc();
     21982    for (long i = 0; i < psArrayLength(objects); i++) {
     21983        psMetadata *md = magicSkyfileMaskMetadataFromObject(objects->data[i]);
     21984        if (!psMetadataAddMetadata(
     21985            output,
     21986            PS_LIST_TAIL,
     21987            MAGICSKYFILEMASK_TABLE_NAME,
     21988            PS_META_DUPLICATE_OK,
     21989            NULL,
     21990            md
     21991        )) {
     21992            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     21993            psFree(md);
     21994            psFree(output);
     21995            return false;
     21996        }
     21997        psFree(md);
     21998    }
     21999
     22000    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     22001        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     22002        psFree(output);
     22003    }
     22004    psFree(output);
     22005
     22006    return true;
     22007}
     22008bool magicSkyfileMaskPrintObject(FILE *stream, magicSkyfileMaskRow *object, bool mdcf)
     22009{
     22010    PS_ASSERT_PTR_NON_NULL(object, false);
     22011
     22012    psMetadata *md = magicSkyfileMaskMetadataFromObject(object);
     22013
     22014    if (!ippdbPrintMetadataRaw(stream, md, mdcf)) {
     22015        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     22016        psFree(md);
     22017    }
     22018
     22019    psFree(md);
     22020
     22021    return true;
     22022}
Note: See TracChangeset for help on using the changeset viewer.