IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 15421 for trunk/ippdb/src


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

update

Location:
trunk/ippdb/src
Files:
2 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}
  • trunk/ippdb/src/ippdb.h

    r15420 r15421  
    125125);
    126126
     127/** pzDataStoreRow data structure
     128 *
     129 * Structure for representing a single row of pzDataStore table data.
     130 */
     131
     132typedef struct {
     133    char            *camera;
     134    char            *telescope;
     135    char            *uri;
     136} pzDataStoreRow;
     137
     138/** Creates a new pzDataStoreRow object
     139 *
     140 *  @return A new pzDataStoreRow object or NULL on failure.
     141 */
     142
     143pzDataStoreRow *pzDataStoreRowAlloc(
     144    const char      *camera,
     145    const char      *telescope,
     146    const char      *uri
     147);
     148
     149/** Creates a new pzDataStore table
     150 *
     151 * @return true on success
     152 */
     153
     154bool pzDataStoreCreateTable(
     155    psDB            *dbh                ///< Database handle
     156);
     157
     158/** Deletes a pzDataStore table
     159 *
     160 * @return true on success
     161 */
     162
     163bool pzDataStoreDropTable(
     164    psDB            *dbh                ///< Database handle
     165);
     166
     167/** Insert a single row into a table
     168 *
     169 * This function constructs and inserts a single row based on it's parameters.
     170 *
     171 * @return true on success
     172 */
     173
     174bool pzDataStoreInsert(
     175    psDB            *dbh,               ///< Database handle
     176    const char      *camera,
     177    const char      *telescope,
     178    const char      *uri
     179);
     180
     181/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     182 *
     183 * @return A The number of rows removed or a negative value on error
     184 */
     185
     186long long pzDataStoreDelete(
     187    psDB            *dbh,               ///< Database handle
     188    const psMetadata *where,            ///< Row match criteria
     189    unsigned long long limit            ///< Maximum number of elements to delete
     190);
     191
     192/** Insert a single pzDataStoreRow object into a table
     193 *
     194 * This function constructs and inserts a single row based on it's parameters.
     195 *
     196 * @return true on success
     197 */
     198
     199bool pzDataStoreInsertObject(
     200    psDB            *dbh,               ///< Database handle
     201    pzDataStoreRow  *object             ///< pzDataStoreRow object
     202);
     203
     204/** Insert an array of pzDataStoreRow object into a table
     205 *
     206 * This function constructs and inserts multiple rows based on it's parameters.
     207 *
     208 * @return true on success
     209 */
     210
     211bool pzDataStoreInsertObjects(
     212    psDB            *dbh,               ///< Database handle
     213    psArray         *objects            ///< array of pzDataStoreRow objects
     214);
     215
     216/** Insert data from a binary FITS table pzDataStoreRow into the database
     217 *
     218 * This function expects a psFits object with a FITS table as the first
     219 * extension.  The table must have at least one row of data in it, that is of
     220 * the appropriate format (number of columns and their type).  All other
     221 * extensions are ignored.
     222 *
     223 * @return true on success
     224 */
     225
     226bool pzDataStoreInsertFits(
     227    psDB            *dbh,               ///< Database handle
     228    const psFits    *fits               ///< psFits object
     229);
     230
     231/** Selects up to limit from the database and returns them in a binary FITS table
     232 *
     233 * This function assumes an empty psFits object and will create a FITS table
     234 * as the first extension.
     235 *
     236 *  See psDBSelectRows() for documentation on the format of where.
     237 *
     238 * @return true on success
     239 */
     240
     241bool pzDataStoreSelectRowsFits(
     242    psDB            *dbh,               ///< Database handle
     243    psFits          *fits,              ///< psFits object
     244    const psMetadata *where,            ///< Row match criteria
     245    unsigned long long limit            ///< Maximum number of elements to return
     246);
     247
     248/** Convert a pzDataStoreRow into an equivalent psMetadata
     249 *
     250 * @return A psMetadata pointer or NULL on error
     251 */
     252
     253psMetadata *pzDataStoreMetadataFromObject(
     254    const pzDataStoreRow *object             ///< fooRow to convert into a psMetadata
     255);
     256
     257/** Convert a psMetadata into an equivalent fooRow
     258 *
     259 * @return A pzDataStoreRow pointer or NULL on error
     260 */
     261
     262pzDataStoreRow *pzDataStoreObjectFromMetadata(
     263    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     264);
     265/** Selects up to limit rows from the database and returns as pzDataStoreRow objects in a psArray
     266 *
     267 *  See psDBSelectRows() for documentation on the format of where.
     268 *
     269 * @return A psArray pointer or NULL on error
     270 */
     271
     272psArray *pzDataStoreSelectRowObjects(
     273    psDB            *dbh,               ///< Database handle
     274    const psMetadata *where,            ///< Row match criteria
     275    unsigned long long limit            ///< Maximum number of elements to return
     276);
     277/** Deletes a row from the database coresponding to an pzDataStore
     278 *
     279 *  Note that a 'where' search psMetadata is constructed from each object and
     280 *  used to find rows to delete.
     281 *
     282 * @return A The number of rows removed or a negative value on error
     283 */
     284
     285bool pzDataStoreDeleteObject(
     286    psDB            *dbh,               ///< Database handle
     287    const pzDataStoreRow *object    ///< Object to delete
     288);
     289/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     290 *
     291 *  Note that a 'where' search psMetadata is constructed from each object and
     292 *  used to find rows to delete.
     293 *
     294 * @return A The number of rows removed or a negative value on error
     295 */
     296
     297long long pzDataStoreDeleteRowObjects(
     298    psDB            *dbh,               ///< Database handle
     299    const psArray   *objects,           ///< Array of objects to delete
     300    unsigned long long limit            ///< Maximum number of elements to delete
     301);
     302/** Formats and prints an array of pzDataStoreRow objects
     303 *
     304 * When mdcf is set the formated output is in psMetadataConfig
     305 * format, otherwise it is in a simple tabular format.
     306 *
     307 * @return true on success
     308 */
     309
     310bool pzDataStorePrintObjects(
     311    FILE            *stream,            ///< a stream
     312    psArray         *objects,           ///< An array of pzDataStoreRow objects
     313    bool            mdcf                ///< format as mdconfig or simple
     314);
     315/** Formats and prints an pzDataStoreRow object
     316 *
     317 * When mdcf is set the formated output is in psMetadataConfig
     318 * format, otherwise it is in a simple tabular format.
     319 *
     320 * @return true on success
     321 */
     322
     323bool pzDataStorePrintObject(
     324    FILE            *stream,            ///< a stream
     325    pzDataStoreRow *object,    ///< an pzDataStoreRow object
     326    bool            mdcf                ///< format as mdconfig or simple
     327);
    127328/** summitExpRow data structure
    128329 *
     
    769970    char            *class;
    770971    char            *class_id;
    771     psS64           exp_id;
    772972} pzPendingImfileRow;
    773973
     
    782982    const char      *telescope,
    783983    const char      *class,
    784     const char      *class_id,
    785     psS64           exp_id
     984    const char      *class_id
    786985);
    787986
     
    8171016    const char      *telescope,
    8181017    const char      *class,
    819     const char      *class_id,
    820     psS64           exp_id
     1018    const char      *class_id
    8211019);
    8221020
     
    11801378    char            *class;
    11811379    char            *class_id;
    1182     psS64           exp_id;
    11831380    char            *uri;
    11841381} pzDoneImfileRow;
     
    11951392    const char      *class,
    11961393    const char      *class_id,
    1197     psS64           exp_id,
    11981394    const char      *uri
    11991395);
     
    12311427    const char      *class,
    12321428    const char      *class_id,
    1233     psS64           exp_id,
    12341429    const char      *uri
    12351430);
     
    13931588    char            *tmp_telescope;
    13941589    char            *state;
    1395     psS32           imfiles;
    13961590    char            *workdir;
    13971591    char            *workdir_state;
     1592    char            *reduction;
    13981593} newExpRow;
    13991594
     
    14091604    const char      *tmp_telescope,
    14101605    const char      *state,
    1411     psS32           imfiles,
    14121606    const char      *workdir,
    1413     const char      *workdir_state
     1607    const char      *workdir_state,
     1608    const char      *reduction
    14141609);
    14151610
     
    14461641    const char      *tmp_telescope,
    14471642    const char      *state,
    1448     psS32           imfiles,
    14491643    const char      *workdir,
    1450     const char      *workdir_state
     1644    const char      *workdir_state,
     1645    const char      *reduction
    14511646);
    14521647
     
    18122007    char            *exp_tag;
    18132008    char            *exp_type;
    1814     psS32           imfiles;
    18152009    char            *filelevel;
    18162010    char            *workdir;
     2011    char            *reduction;
    18172012    char            *filter;
    18182013    psF32           airmass;
     
    18512046    const char      *exp_tag,
    18522047    const char      *exp_type,
    1853     psS32           imfiles,
    18542048    const char      *filelevel,
    18552049    const char      *workdir,
     2050    const char      *reduction,
    18562051    const char      *filter,
    18572052    psF32           airmass,
     
    19112106    const char      *exp_tag,
    19122107    const char      *exp_type,
    1913     psS32           imfiles,
    19142108    const char      *filelevel,
    19152109    const char      *workdir,
     2110    const char      *reduction,
    19162111    const char      *filter,
    19172112    psF32           airmass,
     
    25742769typedef struct {
    25752770    psS64           chip_id;
     2771    psS64           exp_id;
    25762772    char            *state;
    25772773    char            *workdir;
     
    25902786chipRunRow *chipRunRowAlloc(
    25912787    psS64           chip_id,
     2788    psS64           exp_id,
    25922789    const char      *state,
    25932790    const char      *workdir,
     
    26272824    psDB            *dbh,               ///< Database handle
    26282825    psS64           chip_id,
     2826    psS64           exp_id,
    26292827    const char      *state,
    26302828    const char      *workdir,
     
    27812979    FILE            *stream,            ///< a stream
    27822980    chipRunRow *object,    ///< an chipRunRow object
    2783     bool            mdcf                ///< format as mdconfig or simple
    2784 );
    2785 /** chipInputImfileRow data structure
    2786  *
    2787  * Structure for representing a single row of chipInputImfile table data.
    2788  */
    2789 
    2790 typedef struct {
    2791     psS64           chip_id;
    2792     psS64           exp_id;
    2793     char            *class_id;
    2794 } chipInputImfileRow;
    2795 
    2796 /** Creates a new chipInputImfileRow object
    2797  *
    2798  *  @return A new chipInputImfileRow object or NULL on failure.
    2799  */
    2800 
    2801 chipInputImfileRow *chipInputImfileRowAlloc(
    2802     psS64           chip_id,
    2803     psS64           exp_id,
    2804     const char      *class_id
    2805 );
    2806 
    2807 /** Creates a new chipInputImfile table
    2808  *
    2809  * @return true on success
    2810  */
    2811 
    2812 bool chipInputImfileCreateTable(
    2813     psDB            *dbh                ///< Database handle
    2814 );
    2815 
    2816 /** Deletes a chipInputImfile table
    2817  *
    2818  * @return true on success
    2819  */
    2820 
    2821 bool chipInputImfileDropTable(
    2822     psDB            *dbh                ///< Database handle
    2823 );
    2824 
    2825 /** Insert a single row into a table
    2826  *
    2827  * This function constructs and inserts a single row based on it's parameters.
    2828  *
    2829  * @return true on success
    2830  */
    2831 
    2832 bool chipInputImfileInsert(
    2833     psDB            *dbh,               ///< Database handle
    2834     psS64           chip_id,
    2835     psS64           exp_id,
    2836     const char      *class_id
    2837 );
    2838 
    2839 /** Deletes up to limit rows from the database and returns the number of rows actually deleted.
    2840  *
    2841  * @return A The number of rows removed or a negative value on error
    2842  */
    2843 
    2844 long long chipInputImfileDelete(
    2845     psDB            *dbh,               ///< Database handle
    2846     const psMetadata *where,            ///< Row match criteria
    2847     unsigned long long limit            ///< Maximum number of elements to delete
    2848 );
    2849 
    2850 /** Insert a single chipInputImfileRow object into a table
    2851  *
    2852  * This function constructs and inserts a single row based on it's parameters.
    2853  *
    2854  * @return true on success
    2855  */
    2856 
    2857 bool chipInputImfileInsertObject(
    2858     psDB            *dbh,               ///< Database handle
    2859     chipInputImfileRow *object             ///< chipInputImfileRow object
    2860 );
    2861 
    2862 /** Insert an array of chipInputImfileRow object into a table
    2863  *
    2864  * This function constructs and inserts multiple rows based on it's parameters.
    2865  *
    2866  * @return true on success
    2867  */
    2868 
    2869 bool chipInputImfileInsertObjects(
    2870     psDB            *dbh,               ///< Database handle
    2871     psArray         *objects            ///< array of chipInputImfileRow objects
    2872 );
    2873 
    2874 /** Insert data from a binary FITS table chipInputImfileRow into the database
    2875  *
    2876  * This function expects a psFits object with a FITS table as the first
    2877  * extension.  The table must have at least one row of data in it, that is of
    2878  * the appropriate format (number of columns and their type).  All other
    2879  * extensions are ignored.
    2880  *
    2881  * @return true on success
    2882  */
    2883 
    2884 bool chipInputImfileInsertFits(
    2885     psDB            *dbh,               ///< Database handle
    2886     const psFits    *fits               ///< psFits object
    2887 );
    2888 
    2889 /** Selects up to limit from the database and returns them in a binary FITS table
    2890  *
    2891  * This function assumes an empty psFits object and will create a FITS table
    2892  * as the first extension.
    2893  *
    2894  *  See psDBSelectRows() for documentation on the format of where.
    2895  *
    2896  * @return true on success
    2897  */
    2898 
    2899 bool chipInputImfileSelectRowsFits(
    2900     psDB            *dbh,               ///< Database handle
    2901     psFits          *fits,              ///< psFits object
    2902     const psMetadata *where,            ///< Row match criteria
    2903     unsigned long long limit            ///< Maximum number of elements to return
    2904 );
    2905 
    2906 /** Convert a chipInputImfileRow into an equivalent psMetadata
    2907  *
    2908  * @return A psMetadata pointer or NULL on error
    2909  */
    2910 
    2911 psMetadata *chipInputImfileMetadataFromObject(
    2912     const chipInputImfileRow *object             ///< fooRow to convert into a psMetadata
    2913 );
    2914 
    2915 /** Convert a psMetadata into an equivalent fooRow
    2916  *
    2917  * @return A chipInputImfileRow pointer or NULL on error
    2918  */
    2919 
    2920 chipInputImfileRow *chipInputImfileObjectFromMetadata(
    2921     psMetadata      *md                 ///< psMetadata to convert into a fooRow
    2922 );
    2923 /** Selects up to limit rows from the database and returns as chipInputImfileRow objects in a psArray
    2924  *
    2925  *  See psDBSelectRows() for documentation on the format of where.
    2926  *
    2927  * @return A psArray pointer or NULL on error
    2928  */
    2929 
    2930 psArray *chipInputImfileSelectRowObjects(
    2931     psDB            *dbh,               ///< Database handle
    2932     const psMetadata *where,            ///< Row match criteria
    2933     unsigned long long limit            ///< Maximum number of elements to return
    2934 );
    2935 /** Deletes a row from the database coresponding to an chipInputImfile
    2936  *
    2937  *  Note that a 'where' search psMetadata is constructed from each object and
    2938  *  used to find rows to delete.
    2939  *
    2940  * @return A The number of rows removed or a negative value on error
    2941  */
    2942 
    2943 bool chipInputImfileDeleteObject(
    2944     psDB            *dbh,               ///< Database handle
    2945     const chipInputImfileRow *object    ///< Object to delete
    2946 );
    2947 /** Deletes up to limit rows from the database and returns the number of rows actually deleted.
    2948  *
    2949  *  Note that a 'where' search psMetadata is constructed from each object and
    2950  *  used to find rows to delete.
    2951  *
    2952  * @return A The number of rows removed or a negative value on error
    2953  */
    2954 
    2955 long long chipInputImfileDeleteRowObjects(
    2956     psDB            *dbh,               ///< Database handle
    2957     const psArray   *objects,           ///< Array of objects to delete
    2958     unsigned long long limit            ///< Maximum number of elements to delete
    2959 );
    2960 /** Formats and prints an array of chipInputImfileRow objects
    2961  *
    2962  * When mdcf is set the formated output is in psMetadataConfig
    2963  * format, otherwise it is in a simple tabular format.
    2964  *
    2965  * @return true on success
    2966  */
    2967 
    2968 bool chipInputImfilePrintObjects(
    2969     FILE            *stream,            ///< a stream
    2970     psArray         *objects,           ///< An array of chipInputImfileRow objects
    2971     bool            mdcf                ///< format as mdconfig or simple
    2972 );
    2973 /** Formats and prints an chipInputImfileRow object
    2974  *
    2975  * When mdcf is set the formated output is in psMetadataConfig
    2976  * format, otherwise it is in a simple tabular format.
    2977  *
    2978  * @return true on success
    2979  */
    2980 
    2981 bool chipInputImfilePrintObject(
    2982     FILE            *stream,            ///< a stream
    2983     chipInputImfileRow *object,    ///< an chipInputImfileRow object
    29842981    bool            mdcf                ///< format as mdconfig or simple
    29852982);
     
    47374734    psF64           bg;
    47384735    psF64           bg_stdev;
     4736    psF64           good_frac;
     4737    psS16           fault;
    47394738} warpSkyfileRow;
    47404739
     
    47514750    const char      *path_base,
    47524751    psF64           bg,
    4753     psF64           bg_stdev
     4752    psF64           bg_stdev,
     4753    psF64           good_frac,
     4754    psS16           fault
    47544755);
    47554756
     
    47874788    const char      *path_base,
    47884789    psF64           bg,
    4789     psF64           bg_stdev
     4790    psF64           bg_stdev,
     4791    psF64           good_frac,
     4792    psS16           fault
    47904793);
    47914794
     
    51575160typedef struct {
    51585161    psS64           diff_id;
     5162    bool            template;
     5163    psS64           stack_id;
    51595164    psS64           warp_id;
    51605165    char            *skycell_id;
    51615166    char            *tess_id;
    51625167    char            *kind;
    5163     bool            template;
    51645168} diffInputSkyfileRow;
    51655169
     
    51715175diffInputSkyfileRow *diffInputSkyfileRowAlloc(
    51725176    psS64           diff_id,
     5177    bool            template,
     5178    psS64           stack_id,
    51735179    psS64           warp_id,
    51745180    const char      *skycell_id,
    51755181    const char      *tess_id,
    5176     const char      *kind,
    5177     bool            template
     5182    const char      *kind
    51785183);
    51795184
     
    52065211    psDB            *dbh,               ///< Database handle
    52075212    psS64           diff_id,
     5213    bool            template,
     5214    psS64           stack_id,
    52085215    psS64           warp_id,
    52095216    const char      *skycell_id,
    52105217    const char      *tess_id,
    5211     const char      *kind,
    5212     bool            template
     5218    const char      *kind
    52135219);
    52145220
     
    53715377    psF64           bg;
    53725378    psF64           bg_stdev;
     5379    psF64           good_frac;
     5380    psS16           fault;
    53735381} diffSkyfileRow;
    53745382
     
    53835391    const char      *path_base,
    53845392    psF64           bg,
    5385     psF64           bg_stdev
     5393    psF64           bg_stdev,
     5394    psF64           good_frac,
     5395    psS16           fault
    53865396);
    53875397
     
    54175427    const char      *path_base,
    54185428    psF64           bg,
    5419     psF64           bg_stdev
     5429    psF64           bg_stdev,
     5430    psF64           good_frac,
     5431    psS16           fault
    54205432);
    54215433
     
    59896001    psF64           bg;
    59906002    psF64           bg_stdev;
     6003    psF64           good_frac;
     6004    psS16           fault;
    59916005} stackSumSkyfileRow;
    59926006
     
    60016015    const char      *path_base,
    60026016    psF64           bg,
    6003     psF64           bg_stdev
     6017    psF64           bg_stdev,
     6018    psF64           good_frac,
     6019    psS16           fault
    60046020);
    60056021
     
    60356051    const char      *path_base,
    60366052    psF64           bg,
    6037     psF64           bg_stdev
     6053    psF64           bg_stdev,
     6054    psF64           good_frac,
     6055    psS16           fault
    60386056);
    60396057
     
    80758093    psF64           bg_stdev;
    80768094    psF64           bg_mean_stdev;
     8095    psF64           bg_skewness;
     8096    psF64           bg_kurtosis;
    80778097    psF64           bin_stdev;
    80788098    psF64           fringe_0;
    80798099    psF64           fringe_1;
    80808100    psF64           fringe_2;
     8101    psF64           fringe_resid_0;
     8102    psF64           fringe_resid_1;
     8103    psF64           fringe_resid_2;
    80818104    psF64           user_1;
    80828105    psF64           user_2;
     
    81038126    psF64           bg_stdev,
    81048127    psF64           bg_mean_stdev,
     8128    psF64           bg_skewness,
     8129    psF64           bg_kurtosis,
    81058130    psF64           bin_stdev,
    81068131    psF64           fringe_0,
    81078132    psF64           fringe_1,
    81088133    psF64           fringe_2,
     8134    psF64           fringe_resid_0,
     8135    psF64           fringe_resid_1,
     8136    psF64           fringe_resid_2,
    81098137    psF64           user_1,
    81108138    psF64           user_2,
     
    81528180    psF64           bg_stdev,
    81538181    psF64           bg_mean_stdev,
     8182    psF64           bg_skewness,
     8183    psF64           bg_kurtosis,
    81548184    psF64           bin_stdev,
    81558185    psF64           fringe_0,
    81568186    psF64           fringe_1,
    81578187    psF64           fringe_2,
     8188    psF64           fringe_resid_0,
     8189    psF64           fringe_resid_1,
     8190    psF64           fringe_resid_2,
    81588191    psF64           user_1,
    81598192    psF64           user_2,
     
    83258358    psF64           bg_stdev;
    83268359    psF64           bg_mean_stdev;
     8360    psF64           bg_skewness;
     8361    psF64           bg_kurtosis;
    83278362    psF64           bin_stdev;
    83288363    psF64           fringe_0;
    83298364    psF64           fringe_1;
    83308365    psF64           fringe_2;
     8366    psF64           fringe_resid_0;
     8367    psF64           fringe_resid_1;
     8368    psF64           fringe_resid_2;
    83318369    psF64           user_1;
    83328370    psF64           user_2;
     
    83528390    psF64           bg_stdev,
    83538391    psF64           bg_mean_stdev,
     8392    psF64           bg_skewness,
     8393    psF64           bg_kurtosis,
    83548394    psF64           bin_stdev,
    83558395    psF64           fringe_0,
    83568396    psF64           fringe_1,
    83578397    psF64           fringe_2,
     8398    psF64           fringe_resid_0,
     8399    psF64           fringe_resid_1,
     8400    psF64           fringe_resid_2,
    83588401    psF64           user_1,
    83598402    psF64           user_2,
     
    84008443    psF64           bg_stdev,
    84018444    psF64           bg_mean_stdev,
     8445    psF64           bg_skewness,
     8446    psF64           bg_kurtosis,
    84028447    psF64           bin_stdev,
    84038448    psF64           fringe_0,
    84048449    psF64           fringe_1,
    84058450    psF64           fringe_2,
     8451    psF64           fringe_resid_0,
     8452    psF64           fringe_resid_1,
     8453    psF64           fringe_resid_2,
    84068454    psF64           user_1,
    84078455    psF64           user_2,
     
    87748822    bool            mdcf                ///< format as mdconfig or simple
    87758823);
     8824/** detRegisteredImfileRow data structure
     8825 *
     8826 * Structure for representing a single row of detRegisteredImfile table data.
     8827 */
     8828
     8829typedef struct {
     8830    psS64           det_id;
     8831    psS32           iteration;
     8832    char            *class_id;
     8833    char            *uri;
     8834    psF64           bg;
     8835    psF64           bg_stdev;
     8836    psF64           bg_mean_stdev;
     8837    psF64           user_1;
     8838    psF64           user_2;
     8839    psF64           user_3;
     8840    psF64           user_4;
     8841    psF64           user_5;
     8842    char            *path_base;
     8843    psS16           fault;
     8844} detRegisteredImfileRow;
     8845
     8846/** Creates a new detRegisteredImfileRow object
     8847 *
     8848 *  @return A new detRegisteredImfileRow object or NULL on failure.
     8849 */
     8850
     8851detRegisteredImfileRow *detRegisteredImfileRowAlloc(
     8852    psS64           det_id,
     8853    psS32           iteration,
     8854    const char      *class_id,
     8855    const char      *uri,
     8856    psF64           bg,
     8857    psF64           bg_stdev,
     8858    psF64           bg_mean_stdev,
     8859    psF64           user_1,
     8860    psF64           user_2,
     8861    psF64           user_3,
     8862    psF64           user_4,
     8863    psF64           user_5,
     8864    const char      *path_base,
     8865    psS16           fault
     8866);
     8867
     8868/** Creates a new detRegisteredImfile table
     8869 *
     8870 * @return true on success
     8871 */
     8872
     8873bool detRegisteredImfileCreateTable(
     8874    psDB            *dbh                ///< Database handle
     8875);
     8876
     8877/** Deletes a detRegisteredImfile table
     8878 *
     8879 * @return true on success
     8880 */
     8881
     8882bool detRegisteredImfileDropTable(
     8883    psDB            *dbh                ///< Database handle
     8884);
     8885
     8886/** Insert a single row into a table
     8887 *
     8888 * This function constructs and inserts a single row based on it's parameters.
     8889 *
     8890 * @return true on success
     8891 */
     8892
     8893bool detRegisteredImfileInsert(
     8894    psDB            *dbh,               ///< Database handle
     8895    psS64           det_id,
     8896    psS32           iteration,
     8897    const char      *class_id,
     8898    const char      *uri,
     8899    psF64           bg,
     8900    psF64           bg_stdev,
     8901    psF64           bg_mean_stdev,
     8902    psF64           user_1,
     8903    psF64           user_2,
     8904    psF64           user_3,
     8905    psF64           user_4,
     8906    psF64           user_5,
     8907    const char      *path_base,
     8908    psS16           fault
     8909);
     8910
     8911/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     8912 *
     8913 * @return A The number of rows removed or a negative value on error
     8914 */
     8915
     8916long long detRegisteredImfileDelete(
     8917    psDB            *dbh,               ///< Database handle
     8918    const psMetadata *where,            ///< Row match criteria
     8919    unsigned long long limit            ///< Maximum number of elements to delete
     8920);
     8921
     8922/** Insert a single detRegisteredImfileRow object into a table
     8923 *
     8924 * This function constructs and inserts a single row based on it's parameters.
     8925 *
     8926 * @return true on success
     8927 */
     8928
     8929bool detRegisteredImfileInsertObject(
     8930    psDB            *dbh,               ///< Database handle
     8931    detRegisteredImfileRow *object             ///< detRegisteredImfileRow object
     8932);
     8933
     8934/** Insert an array of detRegisteredImfileRow object into a table
     8935 *
     8936 * This function constructs and inserts multiple rows based on it's parameters.
     8937 *
     8938 * @return true on success
     8939 */
     8940
     8941bool detRegisteredImfileInsertObjects(
     8942    psDB            *dbh,               ///< Database handle
     8943    psArray         *objects            ///< array of detRegisteredImfileRow objects
     8944);
     8945
     8946/** Insert data from a binary FITS table detRegisteredImfileRow into the database
     8947 *
     8948 * This function expects a psFits object with a FITS table as the first
     8949 * extension.  The table must have at least one row of data in it, that is of
     8950 * the appropriate format (number of columns and their type).  All other
     8951 * extensions are ignored.
     8952 *
     8953 * @return true on success
     8954 */
     8955
     8956bool detRegisteredImfileInsertFits(
     8957    psDB            *dbh,               ///< Database handle
     8958    const psFits    *fits               ///< psFits object
     8959);
     8960
     8961/** Selects up to limit from the database and returns them in a binary FITS table
     8962 *
     8963 * This function assumes an empty psFits object and will create a FITS table
     8964 * as the first extension.
     8965 *
     8966 *  See psDBSelectRows() for documentation on the format of where.
     8967 *
     8968 * @return true on success
     8969 */
     8970
     8971bool detRegisteredImfileSelectRowsFits(
     8972    psDB            *dbh,               ///< Database handle
     8973    psFits          *fits,              ///< psFits object
     8974    const psMetadata *where,            ///< Row match criteria
     8975    unsigned long long limit            ///< Maximum number of elements to return
     8976);
     8977
     8978/** Convert a detRegisteredImfileRow into an equivalent psMetadata
     8979 *
     8980 * @return A psMetadata pointer or NULL on error
     8981 */
     8982
     8983psMetadata *detRegisteredImfileMetadataFromObject(
     8984    const detRegisteredImfileRow *object             ///< fooRow to convert into a psMetadata
     8985);
     8986
     8987/** Convert a psMetadata into an equivalent fooRow
     8988 *
     8989 * @return A detRegisteredImfileRow pointer or NULL on error
     8990 */
     8991
     8992detRegisteredImfileRow *detRegisteredImfileObjectFromMetadata(
     8993    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     8994);
     8995/** Selects up to limit rows from the database and returns as detRegisteredImfileRow objects in a psArray
     8996 *
     8997 *  See psDBSelectRows() for documentation on the format of where.
     8998 *
     8999 * @return A psArray pointer or NULL on error
     9000 */
     9001
     9002psArray *detRegisteredImfileSelectRowObjects(
     9003    psDB            *dbh,               ///< Database handle
     9004    const psMetadata *where,            ///< Row match criteria
     9005    unsigned long long limit            ///< Maximum number of elements to return
     9006);
     9007/** Deletes a row from the database coresponding to an detRegisteredImfile
     9008 *
     9009 *  Note that a 'where' search psMetadata is constructed from each object and
     9010 *  used to find rows to delete.
     9011 *
     9012 * @return A The number of rows removed or a negative value on error
     9013 */
     9014
     9015bool detRegisteredImfileDeleteObject(
     9016    psDB            *dbh,               ///< Database handle
     9017    const detRegisteredImfileRow *object    ///< Object to delete
     9018);
     9019/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9020 *
     9021 *  Note that a 'where' search psMetadata is constructed from each object and
     9022 *  used to find rows to delete.
     9023 *
     9024 * @return A The number of rows removed or a negative value on error
     9025 */
     9026
     9027long long detRegisteredImfileDeleteRowObjects(
     9028    psDB            *dbh,               ///< Database handle
     9029    const psArray   *objects,           ///< Array of objects to delete
     9030    unsigned long long limit            ///< Maximum number of elements to delete
     9031);
     9032/** Formats and prints an array of detRegisteredImfileRow objects
     9033 *
     9034 * When mdcf is set the formated output is in psMetadataConfig
     9035 * format, otherwise it is in a simple tabular format.
     9036 *
     9037 * @return true on success
     9038 */
     9039
     9040bool detRegisteredImfilePrintObjects(
     9041    FILE            *stream,            ///< a stream
     9042    psArray         *objects,           ///< An array of detRegisteredImfileRow objects
     9043    bool            mdcf                ///< format as mdconfig or simple
     9044);
     9045/** Formats and prints an detRegisteredImfileRow object
     9046 *
     9047 * When mdcf is set the formated output is in psMetadataConfig
     9048 * format, otherwise it is in a simple tabular format.
     9049 *
     9050 * @return true on success
     9051 */
     9052
     9053bool detRegisteredImfilePrintObject(
     9054    FILE            *stream,            ///< a stream
     9055    detRegisteredImfileRow *object,    ///< an detRegisteredImfileRow object
     9056    bool            mdcf                ///< format as mdconfig or simple
     9057);
     9058/** detCorrectedExpRow data structure
     9059 *
     9060 * Structure for representing a single row of detCorrectedExp table data.
     9061 */
     9062
     9063typedef struct {
     9064    psS64           det_id;
     9065    psS64           exp_id;
     9066    char            *uri;
     9067    psS64           corr_id;
     9068    char            *corr_type;
     9069    char            *recipe;
     9070    char            *path_base;
     9071    psS16           fault;
     9072} detCorrectedExpRow;
     9073
     9074/** Creates a new detCorrectedExpRow object
     9075 *
     9076 *  @return A new detCorrectedExpRow object or NULL on failure.
     9077 */
     9078
     9079detCorrectedExpRow *detCorrectedExpRowAlloc(
     9080    psS64           det_id,
     9081    psS64           exp_id,
     9082    const char      *uri,
     9083    psS64           corr_id,
     9084    const char      *corr_type,
     9085    const char      *recipe,
     9086    const char      *path_base,
     9087    psS16           fault
     9088);
     9089
     9090/** Creates a new detCorrectedExp table
     9091 *
     9092 * @return true on success
     9093 */
     9094
     9095bool detCorrectedExpCreateTable(
     9096    psDB            *dbh                ///< Database handle
     9097);
     9098
     9099/** Deletes a detCorrectedExp table
     9100 *
     9101 * @return true on success
     9102 */
     9103
     9104bool detCorrectedExpDropTable(
     9105    psDB            *dbh                ///< Database handle
     9106);
     9107
     9108/** Insert a single row into a table
     9109 *
     9110 * This function constructs and inserts a single row based on it's parameters.
     9111 *
     9112 * @return true on success
     9113 */
     9114
     9115bool detCorrectedExpInsert(
     9116    psDB            *dbh,               ///< Database handle
     9117    psS64           det_id,
     9118    psS64           exp_id,
     9119    const char      *uri,
     9120    psS64           corr_id,
     9121    const char      *corr_type,
     9122    const char      *recipe,
     9123    const char      *path_base,
     9124    psS16           fault
     9125);
     9126
     9127/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9128 *
     9129 * @return A The number of rows removed or a negative value on error
     9130 */
     9131
     9132long long detCorrectedExpDelete(
     9133    psDB            *dbh,               ///< Database handle
     9134    const psMetadata *where,            ///< Row match criteria
     9135    unsigned long long limit            ///< Maximum number of elements to delete
     9136);
     9137
     9138/** Insert a single detCorrectedExpRow object into a table
     9139 *
     9140 * This function constructs and inserts a single row based on it's parameters.
     9141 *
     9142 * @return true on success
     9143 */
     9144
     9145bool detCorrectedExpInsertObject(
     9146    psDB            *dbh,               ///< Database handle
     9147    detCorrectedExpRow *object             ///< detCorrectedExpRow object
     9148);
     9149
     9150/** Insert an array of detCorrectedExpRow object into a table
     9151 *
     9152 * This function constructs and inserts multiple rows based on it's parameters.
     9153 *
     9154 * @return true on success
     9155 */
     9156
     9157bool detCorrectedExpInsertObjects(
     9158    psDB            *dbh,               ///< Database handle
     9159    psArray         *objects            ///< array of detCorrectedExpRow objects
     9160);
     9161
     9162/** Insert data from a binary FITS table detCorrectedExpRow into the database
     9163 *
     9164 * This function expects a psFits object with a FITS table as the first
     9165 * extension.  The table must have at least one row of data in it, that is of
     9166 * the appropriate format (number of columns and their type).  All other
     9167 * extensions are ignored.
     9168 *
     9169 * @return true on success
     9170 */
     9171
     9172bool detCorrectedExpInsertFits(
     9173    psDB            *dbh,               ///< Database handle
     9174    const psFits    *fits               ///< psFits object
     9175);
     9176
     9177/** Selects up to limit from the database and returns them in a binary FITS table
     9178 *
     9179 * This function assumes an empty psFits object and will create a FITS table
     9180 * as the first extension.
     9181 *
     9182 *  See psDBSelectRows() for documentation on the format of where.
     9183 *
     9184 * @return true on success
     9185 */
     9186
     9187bool detCorrectedExpSelectRowsFits(
     9188    psDB            *dbh,               ///< Database handle
     9189    psFits          *fits,              ///< psFits object
     9190    const psMetadata *where,            ///< Row match criteria
     9191    unsigned long long limit            ///< Maximum number of elements to return
     9192);
     9193
     9194/** Convert a detCorrectedExpRow into an equivalent psMetadata
     9195 *
     9196 * @return A psMetadata pointer or NULL on error
     9197 */
     9198
     9199psMetadata *detCorrectedExpMetadataFromObject(
     9200    const detCorrectedExpRow *object             ///< fooRow to convert into a psMetadata
     9201);
     9202
     9203/** Convert a psMetadata into an equivalent fooRow
     9204 *
     9205 * @return A detCorrectedExpRow pointer or NULL on error
     9206 */
     9207
     9208detCorrectedExpRow *detCorrectedExpObjectFromMetadata(
     9209    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     9210);
     9211/** Selects up to limit rows from the database and returns as detCorrectedExpRow objects in a psArray
     9212 *
     9213 *  See psDBSelectRows() for documentation on the format of where.
     9214 *
     9215 * @return A psArray pointer or NULL on error
     9216 */
     9217
     9218psArray *detCorrectedExpSelectRowObjects(
     9219    psDB            *dbh,               ///< Database handle
     9220    const psMetadata *where,            ///< Row match criteria
     9221    unsigned long long limit            ///< Maximum number of elements to return
     9222);
     9223/** Deletes a row from the database coresponding to an detCorrectedExp
     9224 *
     9225 *  Note that a 'where' search psMetadata is constructed from each object and
     9226 *  used to find rows to delete.
     9227 *
     9228 * @return A The number of rows removed or a negative value on error
     9229 */
     9230
     9231bool detCorrectedExpDeleteObject(
     9232    psDB            *dbh,               ///< Database handle
     9233    const detCorrectedExpRow *object    ///< Object to delete
     9234);
     9235/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9236 *
     9237 *  Note that a 'where' search psMetadata is constructed from each object and
     9238 *  used to find rows to delete.
     9239 *
     9240 * @return A The number of rows removed or a negative value on error
     9241 */
     9242
     9243long long detCorrectedExpDeleteRowObjects(
     9244    psDB            *dbh,               ///< Database handle
     9245    const psArray   *objects,           ///< Array of objects to delete
     9246    unsigned long long limit            ///< Maximum number of elements to delete
     9247);
     9248/** Formats and prints an array of detCorrectedExpRow objects
     9249 *
     9250 * When mdcf is set the formated output is in psMetadataConfig
     9251 * format, otherwise it is in a simple tabular format.
     9252 *
     9253 * @return true on success
     9254 */
     9255
     9256bool detCorrectedExpPrintObjects(
     9257    FILE            *stream,            ///< a stream
     9258    psArray         *objects,           ///< An array of detCorrectedExpRow objects
     9259    bool            mdcf                ///< format as mdconfig or simple
     9260);
     9261/** Formats and prints an detCorrectedExpRow object
     9262 *
     9263 * When mdcf is set the formated output is in psMetadataConfig
     9264 * format, otherwise it is in a simple tabular format.
     9265 *
     9266 * @return true on success
     9267 */
     9268
     9269bool detCorrectedExpPrintObject(
     9270    FILE            *stream,            ///< a stream
     9271    detCorrectedExpRow *object,    ///< an detCorrectedExpRow object
     9272    bool            mdcf                ///< format as mdconfig or simple
     9273);
     9274/** detCorrectedImfileRow data structure
     9275 *
     9276 * Structure for representing a single row of detCorrectedImfile table data.
     9277 */
     9278
     9279typedef struct {
     9280    psS64           det_id;
     9281    psS64           exp_id;
     9282    char            *class_id;
     9283    char            *uri;
     9284    char            *path_base;
     9285    psS16           fault;
     9286} detCorrectedImfileRow;
     9287
     9288/** Creates a new detCorrectedImfileRow object
     9289 *
     9290 *  @return A new detCorrectedImfileRow object or NULL on failure.
     9291 */
     9292
     9293detCorrectedImfileRow *detCorrectedImfileRowAlloc(
     9294    psS64           det_id,
     9295    psS64           exp_id,
     9296    const char      *class_id,
     9297    const char      *uri,
     9298    const char      *path_base,
     9299    psS16           fault
     9300);
     9301
     9302/** Creates a new detCorrectedImfile table
     9303 *
     9304 * @return true on success
     9305 */
     9306
     9307bool detCorrectedImfileCreateTable(
     9308    psDB            *dbh                ///< Database handle
     9309);
     9310
     9311/** Deletes a detCorrectedImfile table
     9312 *
     9313 * @return true on success
     9314 */
     9315
     9316bool detCorrectedImfileDropTable(
     9317    psDB            *dbh                ///< Database handle
     9318);
     9319
     9320/** Insert a single row into a table
     9321 *
     9322 * This function constructs and inserts a single row based on it's parameters.
     9323 *
     9324 * @return true on success
     9325 */
     9326
     9327bool detCorrectedImfileInsert(
     9328    psDB            *dbh,               ///< Database handle
     9329    psS64           det_id,
     9330    psS64           exp_id,
     9331    const char      *class_id,
     9332    const char      *uri,
     9333    const char      *path_base,
     9334    psS16           fault
     9335);
     9336
     9337/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9338 *
     9339 * @return A The number of rows removed or a negative value on error
     9340 */
     9341
     9342long long detCorrectedImfileDelete(
     9343    psDB            *dbh,               ///< Database handle
     9344    const psMetadata *where,            ///< Row match criteria
     9345    unsigned long long limit            ///< Maximum number of elements to delete
     9346);
     9347
     9348/** Insert a single detCorrectedImfileRow object into a table
     9349 *
     9350 * This function constructs and inserts a single row based on it's parameters.
     9351 *
     9352 * @return true on success
     9353 */
     9354
     9355bool detCorrectedImfileInsertObject(
     9356    psDB            *dbh,               ///< Database handle
     9357    detCorrectedImfileRow *object             ///< detCorrectedImfileRow object
     9358);
     9359
     9360/** Insert an array of detCorrectedImfileRow object into a table
     9361 *
     9362 * This function constructs and inserts multiple rows based on it's parameters.
     9363 *
     9364 * @return true on success
     9365 */
     9366
     9367bool detCorrectedImfileInsertObjects(
     9368    psDB            *dbh,               ///< Database handle
     9369    psArray         *objects            ///< array of detCorrectedImfileRow objects
     9370);
     9371
     9372/** Insert data from a binary FITS table detCorrectedImfileRow into the database
     9373 *
     9374 * This function expects a psFits object with a FITS table as the first
     9375 * extension.  The table must have at least one row of data in it, that is of
     9376 * the appropriate format (number of columns and their type).  All other
     9377 * extensions are ignored.
     9378 *
     9379 * @return true on success
     9380 */
     9381
     9382bool detCorrectedImfileInsertFits(
     9383    psDB            *dbh,               ///< Database handle
     9384    const psFits    *fits               ///< psFits object
     9385);
     9386
     9387/** Selects up to limit from the database and returns them in a binary FITS table
     9388 *
     9389 * This function assumes an empty psFits object and will create a FITS table
     9390 * as the first extension.
     9391 *
     9392 *  See psDBSelectRows() for documentation on the format of where.
     9393 *
     9394 * @return true on success
     9395 */
     9396
     9397bool detCorrectedImfileSelectRowsFits(
     9398    psDB            *dbh,               ///< Database handle
     9399    psFits          *fits,              ///< psFits object
     9400    const psMetadata *where,            ///< Row match criteria
     9401    unsigned long long limit            ///< Maximum number of elements to return
     9402);
     9403
     9404/** Convert a detCorrectedImfileRow into an equivalent psMetadata
     9405 *
     9406 * @return A psMetadata pointer or NULL on error
     9407 */
     9408
     9409psMetadata *detCorrectedImfileMetadataFromObject(
     9410    const detCorrectedImfileRow *object             ///< fooRow to convert into a psMetadata
     9411);
     9412
     9413/** Convert a psMetadata into an equivalent fooRow
     9414 *
     9415 * @return A detCorrectedImfileRow pointer or NULL on error
     9416 */
     9417
     9418detCorrectedImfileRow *detCorrectedImfileObjectFromMetadata(
     9419    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     9420);
     9421/** Selects up to limit rows from the database and returns as detCorrectedImfileRow objects in a psArray
     9422 *
     9423 *  See psDBSelectRows() for documentation on the format of where.
     9424 *
     9425 * @return A psArray pointer or NULL on error
     9426 */
     9427
     9428psArray *detCorrectedImfileSelectRowObjects(
     9429    psDB            *dbh,               ///< Database handle
     9430    const psMetadata *where,            ///< Row match criteria
     9431    unsigned long long limit            ///< Maximum number of elements to return
     9432);
     9433/** Deletes a row from the database coresponding to an detCorrectedImfile
     9434 *
     9435 *  Note that a 'where' search psMetadata is constructed from each object and
     9436 *  used to find rows to delete.
     9437 *
     9438 * @return A The number of rows removed or a negative value on error
     9439 */
     9440
     9441bool detCorrectedImfileDeleteObject(
     9442    psDB            *dbh,               ///< Database handle
     9443    const detCorrectedImfileRow *object    ///< Object to delete
     9444);
     9445/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9446 *
     9447 *  Note that a 'where' search psMetadata is constructed from each object and
     9448 *  used to find rows to delete.
     9449 *
     9450 * @return A The number of rows removed or a negative value on error
     9451 */
     9452
     9453long long detCorrectedImfileDeleteRowObjects(
     9454    psDB            *dbh,               ///< Database handle
     9455    const psArray   *objects,           ///< Array of objects to delete
     9456    unsigned long long limit            ///< Maximum number of elements to delete
     9457);
     9458/** Formats and prints an array of detCorrectedImfileRow objects
     9459 *
     9460 * When mdcf is set the formated output is in psMetadataConfig
     9461 * format, otherwise it is in a simple tabular format.
     9462 *
     9463 * @return true on success
     9464 */
     9465
     9466bool detCorrectedImfilePrintObjects(
     9467    FILE            *stream,            ///< a stream
     9468    psArray         *objects,           ///< An array of detCorrectedImfileRow objects
     9469    bool            mdcf                ///< format as mdconfig or simple
     9470);
     9471/** Formats and prints an detCorrectedImfileRow object
     9472 *
     9473 * When mdcf is set the formated output is in psMetadataConfig
     9474 * format, otherwise it is in a simple tabular format.
     9475 *
     9476 * @return true on success
     9477 */
     9478
     9479bool detCorrectedImfilePrintObject(
     9480    FILE            *stream,            ///< a stream
     9481    detCorrectedImfileRow *object,    ///< an detCorrectedImfileRow object
     9482    bool            mdcf                ///< format as mdconfig or simple
     9483);
     9484/** magicRunRow data structure
     9485 *
     9486 * Structure for representing a single row of magicRun table data.
     9487 */
     9488
     9489typedef struct {
     9490    psS64           magic_id;
     9491    char            *state;
     9492    char            *workdir;
     9493    char            *workdir_state;
     9494    char            *label;
     9495    char            *dvodb;
     9496    psTime*         registered;
     9497} magicRunRow;
     9498
     9499/** Creates a new magicRunRow object
     9500 *
     9501 *  @return A new magicRunRow object or NULL on failure.
     9502 */
     9503
     9504magicRunRow *magicRunRowAlloc(
     9505    psS64           magic_id,
     9506    const char      *state,
     9507    const char      *workdir,
     9508    const char      *workdir_state,
     9509    const char      *label,
     9510    const char      *dvodb,
     9511    psTime*         registered
     9512);
     9513
     9514/** Creates a new magicRun table
     9515 *
     9516 * @return true on success
     9517 */
     9518
     9519bool magicRunCreateTable(
     9520    psDB            *dbh                ///< Database handle
     9521);
     9522
     9523/** Deletes a magicRun table
     9524 *
     9525 * @return true on success
     9526 */
     9527
     9528bool magicRunDropTable(
     9529    psDB            *dbh                ///< Database handle
     9530);
     9531
     9532/** Insert a single row into a table
     9533 *
     9534 * This function constructs and inserts a single row based on it's parameters.
     9535 *
     9536 * @return true on success
     9537 */
     9538
     9539bool magicRunInsert(
     9540    psDB            *dbh,               ///< Database handle
     9541    psS64           magic_id,
     9542    const char      *state,
     9543    const char      *workdir,
     9544    const char      *workdir_state,
     9545    const char      *label,
     9546    const char      *dvodb,
     9547    psTime*         registered
     9548);
     9549
     9550/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9551 *
     9552 * @return A The number of rows removed or a negative value on error
     9553 */
     9554
     9555long long magicRunDelete(
     9556    psDB            *dbh,               ///< Database handle
     9557    const psMetadata *where,            ///< Row match criteria
     9558    unsigned long long limit            ///< Maximum number of elements to delete
     9559);
     9560
     9561/** Insert a single magicRunRow object into a table
     9562 *
     9563 * This function constructs and inserts a single row based on it's parameters.
     9564 *
     9565 * @return true on success
     9566 */
     9567
     9568bool magicRunInsertObject(
     9569    psDB            *dbh,               ///< Database handle
     9570    magicRunRow     *object             ///< magicRunRow object
     9571);
     9572
     9573/** Insert an array of magicRunRow object into a table
     9574 *
     9575 * This function constructs and inserts multiple rows based on it's parameters.
     9576 *
     9577 * @return true on success
     9578 */
     9579
     9580bool magicRunInsertObjects(
     9581    psDB            *dbh,               ///< Database handle
     9582    psArray         *objects            ///< array of magicRunRow objects
     9583);
     9584
     9585/** Insert data from a binary FITS table magicRunRow into the database
     9586 *
     9587 * This function expects a psFits object with a FITS table as the first
     9588 * extension.  The table must have at least one row of data in it, that is of
     9589 * the appropriate format (number of columns and their type).  All other
     9590 * extensions are ignored.
     9591 *
     9592 * @return true on success
     9593 */
     9594
     9595bool magicRunInsertFits(
     9596    psDB            *dbh,               ///< Database handle
     9597    const psFits    *fits               ///< psFits object
     9598);
     9599
     9600/** Selects up to limit from the database and returns them in a binary FITS table
     9601 *
     9602 * This function assumes an empty psFits object and will create a FITS table
     9603 * as the first extension.
     9604 *
     9605 *  See psDBSelectRows() for documentation on the format of where.
     9606 *
     9607 * @return true on success
     9608 */
     9609
     9610bool magicRunSelectRowsFits(
     9611    psDB            *dbh,               ///< Database handle
     9612    psFits          *fits,              ///< psFits object
     9613    const psMetadata *where,            ///< Row match criteria
     9614    unsigned long long limit            ///< Maximum number of elements to return
     9615);
     9616
     9617/** Convert a magicRunRow into an equivalent psMetadata
     9618 *
     9619 * @return A psMetadata pointer or NULL on error
     9620 */
     9621
     9622psMetadata *magicRunMetadataFromObject(
     9623    const magicRunRow *object             ///< fooRow to convert into a psMetadata
     9624);
     9625
     9626/** Convert a psMetadata into an equivalent fooRow
     9627 *
     9628 * @return A magicRunRow pointer or NULL on error
     9629 */
     9630
     9631magicRunRow *magicRunObjectFromMetadata(
     9632    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     9633);
     9634/** Selects up to limit rows from the database and returns as magicRunRow objects in a psArray
     9635 *
     9636 *  See psDBSelectRows() for documentation on the format of where.
     9637 *
     9638 * @return A psArray pointer or NULL on error
     9639 */
     9640
     9641psArray *magicRunSelectRowObjects(
     9642    psDB            *dbh,               ///< Database handle
     9643    const psMetadata *where,            ///< Row match criteria
     9644    unsigned long long limit            ///< Maximum number of elements to return
     9645);
     9646/** Deletes a row from the database coresponding to an magicRun
     9647 *
     9648 *  Note that a 'where' search psMetadata is constructed from each object and
     9649 *  used to find rows to delete.
     9650 *
     9651 * @return A The number of rows removed or a negative value on error
     9652 */
     9653
     9654bool magicRunDeleteObject(
     9655    psDB            *dbh,               ///< Database handle
     9656    const magicRunRow *object    ///< Object to delete
     9657);
     9658/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9659 *
     9660 *  Note that a 'where' search psMetadata is constructed from each object and
     9661 *  used to find rows to delete.
     9662 *
     9663 * @return A The number of rows removed or a negative value on error
     9664 */
     9665
     9666long long magicRunDeleteRowObjects(
     9667    psDB            *dbh,               ///< Database handle
     9668    const psArray   *objects,           ///< Array of objects to delete
     9669    unsigned long long limit            ///< Maximum number of elements to delete
     9670);
     9671/** Formats and prints an array of magicRunRow objects
     9672 *
     9673 * When mdcf is set the formated output is in psMetadataConfig
     9674 * format, otherwise it is in a simple tabular format.
     9675 *
     9676 * @return true on success
     9677 */
     9678
     9679bool magicRunPrintObjects(
     9680    FILE            *stream,            ///< a stream
     9681    psArray         *objects,           ///< An array of magicRunRow objects
     9682    bool            mdcf                ///< format as mdconfig or simple
     9683);
     9684/** Formats and prints an magicRunRow object
     9685 *
     9686 * When mdcf is set the formated output is in psMetadataConfig
     9687 * format, otherwise it is in a simple tabular format.
     9688 *
     9689 * @return true on success
     9690 */
     9691
     9692bool magicRunPrintObject(
     9693    FILE            *stream,            ///< a stream
     9694    magicRunRow *object,    ///< an magicRunRow object
     9695    bool            mdcf                ///< format as mdconfig or simple
     9696);
     9697/** magicInputSkyfileRow data structure
     9698 *
     9699 * Structure for representing a single row of magicInputSkyfile table data.
     9700 */
     9701
     9702typedef struct {
     9703    psS64           magic_id;
     9704    psS64           diff_id;
     9705    char            *node;
     9706} magicInputSkyfileRow;
     9707
     9708/** Creates a new magicInputSkyfileRow object
     9709 *
     9710 *  @return A new magicInputSkyfileRow object or NULL on failure.
     9711 */
     9712
     9713magicInputSkyfileRow *magicInputSkyfileRowAlloc(
     9714    psS64           magic_id,
     9715    psS64           diff_id,
     9716    const char      *node
     9717);
     9718
     9719/** Creates a new magicInputSkyfile table
     9720 *
     9721 * @return true on success
     9722 */
     9723
     9724bool magicInputSkyfileCreateTable(
     9725    psDB            *dbh                ///< Database handle
     9726);
     9727
     9728/** Deletes a magicInputSkyfile table
     9729 *
     9730 * @return true on success
     9731 */
     9732
     9733bool magicInputSkyfileDropTable(
     9734    psDB            *dbh                ///< Database handle
     9735);
     9736
     9737/** Insert a single row into a table
     9738 *
     9739 * This function constructs and inserts a single row based on it's parameters.
     9740 *
     9741 * @return true on success
     9742 */
     9743
     9744bool magicInputSkyfileInsert(
     9745    psDB            *dbh,               ///< Database handle
     9746    psS64           magic_id,
     9747    psS64           diff_id,
     9748    const char      *node
     9749);
     9750
     9751/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9752 *
     9753 * @return A The number of rows removed or a negative value on error
     9754 */
     9755
     9756long long magicInputSkyfileDelete(
     9757    psDB            *dbh,               ///< Database handle
     9758    const psMetadata *where,            ///< Row match criteria
     9759    unsigned long long limit            ///< Maximum number of elements to delete
     9760);
     9761
     9762/** Insert a single magicInputSkyfileRow object into a table
     9763 *
     9764 * This function constructs and inserts a single row based on it's parameters.
     9765 *
     9766 * @return true on success
     9767 */
     9768
     9769bool magicInputSkyfileInsertObject(
     9770    psDB            *dbh,               ///< Database handle
     9771    magicInputSkyfileRow *object             ///< magicInputSkyfileRow object
     9772);
     9773
     9774/** Insert an array of magicInputSkyfileRow object into a table
     9775 *
     9776 * This function constructs and inserts multiple rows based on it's parameters.
     9777 *
     9778 * @return true on success
     9779 */
     9780
     9781bool magicInputSkyfileInsertObjects(
     9782    psDB            *dbh,               ///< Database handle
     9783    psArray         *objects            ///< array of magicInputSkyfileRow objects
     9784);
     9785
     9786/** Insert data from a binary FITS table magicInputSkyfileRow into the database
     9787 *
     9788 * This function expects a psFits object with a FITS table as the first
     9789 * extension.  The table must have at least one row of data in it, that is of
     9790 * the appropriate format (number of columns and their type).  All other
     9791 * extensions are ignored.
     9792 *
     9793 * @return true on success
     9794 */
     9795
     9796bool magicInputSkyfileInsertFits(
     9797    psDB            *dbh,               ///< Database handle
     9798    const psFits    *fits               ///< psFits object
     9799);
     9800
     9801/** Selects up to limit from the database and returns them in a binary FITS table
     9802 *
     9803 * This function assumes an empty psFits object and will create a FITS table
     9804 * as the first extension.
     9805 *
     9806 *  See psDBSelectRows() for documentation on the format of where.
     9807 *
     9808 * @return true on success
     9809 */
     9810
     9811bool magicInputSkyfileSelectRowsFits(
     9812    psDB            *dbh,               ///< Database handle
     9813    psFits          *fits,              ///< psFits object
     9814    const psMetadata *where,            ///< Row match criteria
     9815    unsigned long long limit            ///< Maximum number of elements to return
     9816);
     9817
     9818/** Convert a magicInputSkyfileRow into an equivalent psMetadata
     9819 *
     9820 * @return A psMetadata pointer or NULL on error
     9821 */
     9822
     9823psMetadata *magicInputSkyfileMetadataFromObject(
     9824    const magicInputSkyfileRow *object             ///< fooRow to convert into a psMetadata
     9825);
     9826
     9827/** Convert a psMetadata into an equivalent fooRow
     9828 *
     9829 * @return A magicInputSkyfileRow pointer or NULL on error
     9830 */
     9831
     9832magicInputSkyfileRow *magicInputSkyfileObjectFromMetadata(
     9833    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     9834);
     9835/** Selects up to limit rows from the database and returns as magicInputSkyfileRow objects in a psArray
     9836 *
     9837 *  See psDBSelectRows() for documentation on the format of where.
     9838 *
     9839 * @return A psArray pointer or NULL on error
     9840 */
     9841
     9842psArray *magicInputSkyfileSelectRowObjects(
     9843    psDB            *dbh,               ///< Database handle
     9844    const psMetadata *where,            ///< Row match criteria
     9845    unsigned long long limit            ///< Maximum number of elements to return
     9846);
     9847/** Deletes a row from the database coresponding to an magicInputSkyfile
     9848 *
     9849 *  Note that a 'where' search psMetadata is constructed from each object and
     9850 *  used to find rows to delete.
     9851 *
     9852 * @return A The number of rows removed or a negative value on error
     9853 */
     9854
     9855bool magicInputSkyfileDeleteObject(
     9856    psDB            *dbh,               ///< Database handle
     9857    const magicInputSkyfileRow *object    ///< Object to delete
     9858);
     9859/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9860 *
     9861 *  Note that a 'where' search psMetadata is constructed from each object and
     9862 *  used to find rows to delete.
     9863 *
     9864 * @return A The number of rows removed or a negative value on error
     9865 */
     9866
     9867long long magicInputSkyfileDeleteRowObjects(
     9868    psDB            *dbh,               ///< Database handle
     9869    const psArray   *objects,           ///< Array of objects to delete
     9870    unsigned long long limit            ///< Maximum number of elements to delete
     9871);
     9872/** Formats and prints an array of magicInputSkyfileRow objects
     9873 *
     9874 * When mdcf is set the formated output is in psMetadataConfig
     9875 * format, otherwise it is in a simple tabular format.
     9876 *
     9877 * @return true on success
     9878 */
     9879
     9880bool magicInputSkyfilePrintObjects(
     9881    FILE            *stream,            ///< a stream
     9882    psArray         *objects,           ///< An array of magicInputSkyfileRow objects
     9883    bool            mdcf                ///< format as mdconfig or simple
     9884);
     9885/** Formats and prints an magicInputSkyfileRow object
     9886 *
     9887 * When mdcf is set the formated output is in psMetadataConfig
     9888 * format, otherwise it is in a simple tabular format.
     9889 *
     9890 * @return true on success
     9891 */
     9892
     9893bool magicInputSkyfilePrintObject(
     9894    FILE            *stream,            ///< a stream
     9895    magicInputSkyfileRow *object,    ///< an magicInputSkyfileRow object
     9896    bool            mdcf                ///< format as mdconfig or simple
     9897);
     9898/** magicTreeRow data structure
     9899 *
     9900 * Structure for representing a single row of magicTree table data.
     9901 */
     9902
     9903typedef struct {
     9904    psS64           magic_id;
     9905    char            *node;
     9906    char            *dep;
     9907} magicTreeRow;
     9908
     9909/** Creates a new magicTreeRow object
     9910 *
     9911 *  @return A new magicTreeRow object or NULL on failure.
     9912 */
     9913
     9914magicTreeRow *magicTreeRowAlloc(
     9915    psS64           magic_id,
     9916    const char      *node,
     9917    const char      *dep
     9918);
     9919
     9920/** Creates a new magicTree table
     9921 *
     9922 * @return true on success
     9923 */
     9924
     9925bool magicTreeCreateTable(
     9926    psDB            *dbh                ///< Database handle
     9927);
     9928
     9929/** Deletes a magicTree table
     9930 *
     9931 * @return true on success
     9932 */
     9933
     9934bool magicTreeDropTable(
     9935    psDB            *dbh                ///< Database handle
     9936);
     9937
     9938/** Insert a single row into a table
     9939 *
     9940 * This function constructs and inserts a single row based on it's parameters.
     9941 *
     9942 * @return true on success
     9943 */
     9944
     9945bool magicTreeInsert(
     9946    psDB            *dbh,               ///< Database handle
     9947    psS64           magic_id,
     9948    const char      *node,
     9949    const char      *dep
     9950);
     9951
     9952/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     9953 *
     9954 * @return A The number of rows removed or a negative value on error
     9955 */
     9956
     9957long long magicTreeDelete(
     9958    psDB            *dbh,               ///< Database handle
     9959    const psMetadata *where,            ///< Row match criteria
     9960    unsigned long long limit            ///< Maximum number of elements to delete
     9961);
     9962
     9963/** Insert a single magicTreeRow object into a table
     9964 *
     9965 * This function constructs and inserts a single row based on it's parameters.
     9966 *
     9967 * @return true on success
     9968 */
     9969
     9970bool magicTreeInsertObject(
     9971    psDB            *dbh,               ///< Database handle
     9972    magicTreeRow    *object             ///< magicTreeRow object
     9973);
     9974
     9975/** Insert an array of magicTreeRow object into a table
     9976 *
     9977 * This function constructs and inserts multiple rows based on it's parameters.
     9978 *
     9979 * @return true on success
     9980 */
     9981
     9982bool magicTreeInsertObjects(
     9983    psDB            *dbh,               ///< Database handle
     9984    psArray         *objects            ///< array of magicTreeRow objects
     9985);
     9986
     9987/** Insert data from a binary FITS table magicTreeRow into the database
     9988 *
     9989 * This function expects a psFits object with a FITS table as the first
     9990 * extension.  The table must have at least one row of data in it, that is of
     9991 * the appropriate format (number of columns and their type).  All other
     9992 * extensions are ignored.
     9993 *
     9994 * @return true on success
     9995 */
     9996
     9997bool magicTreeInsertFits(
     9998    psDB            *dbh,               ///< Database handle
     9999    const psFits    *fits               ///< psFits object
     10000);
     10001
     10002/** Selects up to limit from the database and returns them in a binary FITS table
     10003 *
     10004 * This function assumes an empty psFits object and will create a FITS table
     10005 * as the first extension.
     10006 *
     10007 *  See psDBSelectRows() for documentation on the format of where.
     10008 *
     10009 * @return true on success
     10010 */
     10011
     10012bool magicTreeSelectRowsFits(
     10013    psDB            *dbh,               ///< Database handle
     10014    psFits          *fits,              ///< psFits object
     10015    const psMetadata *where,            ///< Row match criteria
     10016    unsigned long long limit            ///< Maximum number of elements to return
     10017);
     10018
     10019/** Convert a magicTreeRow into an equivalent psMetadata
     10020 *
     10021 * @return A psMetadata pointer or NULL on error
     10022 */
     10023
     10024psMetadata *magicTreeMetadataFromObject(
     10025    const magicTreeRow *object             ///< fooRow to convert into a psMetadata
     10026);
     10027
     10028/** Convert a psMetadata into an equivalent fooRow
     10029 *
     10030 * @return A magicTreeRow pointer or NULL on error
     10031 */
     10032
     10033magicTreeRow *magicTreeObjectFromMetadata(
     10034    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     10035);
     10036/** Selects up to limit rows from the database and returns as magicTreeRow objects in a psArray
     10037 *
     10038 *  See psDBSelectRows() for documentation on the format of where.
     10039 *
     10040 * @return A psArray pointer or NULL on error
     10041 */
     10042
     10043psArray *magicTreeSelectRowObjects(
     10044    psDB            *dbh,               ///< Database handle
     10045    const psMetadata *where,            ///< Row match criteria
     10046    unsigned long long limit            ///< Maximum number of elements to return
     10047);
     10048/** Deletes a row from the database coresponding to an magicTree
     10049 *
     10050 *  Note that a 'where' search psMetadata is constructed from each object and
     10051 *  used to find rows to delete.
     10052 *
     10053 * @return A The number of rows removed or a negative value on error
     10054 */
     10055
     10056bool magicTreeDeleteObject(
     10057    psDB            *dbh,               ///< Database handle
     10058    const magicTreeRow *object    ///< Object to delete
     10059);
     10060/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10061 *
     10062 *  Note that a 'where' search psMetadata is constructed from each object and
     10063 *  used to find rows to delete.
     10064 *
     10065 * @return A The number of rows removed or a negative value on error
     10066 */
     10067
     10068long long magicTreeDeleteRowObjects(
     10069    psDB            *dbh,               ///< Database handle
     10070    const psArray   *objects,           ///< Array of objects to delete
     10071    unsigned long long limit            ///< Maximum number of elements to delete
     10072);
     10073/** Formats and prints an array of magicTreeRow objects
     10074 *
     10075 * When mdcf is set the formated output is in psMetadataConfig
     10076 * format, otherwise it is in a simple tabular format.
     10077 *
     10078 * @return true on success
     10079 */
     10080
     10081bool magicTreePrintObjects(
     10082    FILE            *stream,            ///< a stream
     10083    psArray         *objects,           ///< An array of magicTreeRow objects
     10084    bool            mdcf                ///< format as mdconfig or simple
     10085);
     10086/** Formats and prints an magicTreeRow object
     10087 *
     10088 * When mdcf is set the formated output is in psMetadataConfig
     10089 * format, otherwise it is in a simple tabular format.
     10090 *
     10091 * @return true on success
     10092 */
     10093
     10094bool magicTreePrintObject(
     10095    FILE            *stream,            ///< a stream
     10096    magicTreeRow *object,    ///< an magicTreeRow object
     10097    bool            mdcf                ///< format as mdconfig or simple
     10098);
     10099/** magicNodeResultRow data structure
     10100 *
     10101 * Structure for representing a single row of magicNodeResult table data.
     10102 */
     10103
     10104typedef struct {
     10105    psS64           magic_id;
     10106    char            *node;
     10107    char            *uri;
     10108} magicNodeResultRow;
     10109
     10110/** Creates a new magicNodeResultRow object
     10111 *
     10112 *  @return A new magicNodeResultRow object or NULL on failure.
     10113 */
     10114
     10115magicNodeResultRow *magicNodeResultRowAlloc(
     10116    psS64           magic_id,
     10117    const char      *node,
     10118    const char      *uri
     10119);
     10120
     10121/** Creates a new magicNodeResult table
     10122 *
     10123 * @return true on success
     10124 */
     10125
     10126bool magicNodeResultCreateTable(
     10127    psDB            *dbh                ///< Database handle
     10128);
     10129
     10130/** Deletes a magicNodeResult table
     10131 *
     10132 * @return true on success
     10133 */
     10134
     10135bool magicNodeResultDropTable(
     10136    psDB            *dbh                ///< Database handle
     10137);
     10138
     10139/** Insert a single row into a table
     10140 *
     10141 * This function constructs and inserts a single row based on it's parameters.
     10142 *
     10143 * @return true on success
     10144 */
     10145
     10146bool magicNodeResultInsert(
     10147    psDB            *dbh,               ///< Database handle
     10148    psS64           magic_id,
     10149    const char      *node,
     10150    const char      *uri
     10151);
     10152
     10153/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10154 *
     10155 * @return A The number of rows removed or a negative value on error
     10156 */
     10157
     10158long long magicNodeResultDelete(
     10159    psDB            *dbh,               ///< Database handle
     10160    const psMetadata *where,            ///< Row match criteria
     10161    unsigned long long limit            ///< Maximum number of elements to delete
     10162);
     10163
     10164/** Insert a single magicNodeResultRow object into a table
     10165 *
     10166 * This function constructs and inserts a single row based on it's parameters.
     10167 *
     10168 * @return true on success
     10169 */
     10170
     10171bool magicNodeResultInsertObject(
     10172    psDB            *dbh,               ///< Database handle
     10173    magicNodeResultRow *object             ///< magicNodeResultRow object
     10174);
     10175
     10176/** Insert an array of magicNodeResultRow object into a table
     10177 *
     10178 * This function constructs and inserts multiple rows based on it's parameters.
     10179 *
     10180 * @return true on success
     10181 */
     10182
     10183bool magicNodeResultInsertObjects(
     10184    psDB            *dbh,               ///< Database handle
     10185    psArray         *objects            ///< array of magicNodeResultRow objects
     10186);
     10187
     10188/** Insert data from a binary FITS table magicNodeResultRow into the database
     10189 *
     10190 * This function expects a psFits object with a FITS table as the first
     10191 * extension.  The table must have at least one row of data in it, that is of
     10192 * the appropriate format (number of columns and their type).  All other
     10193 * extensions are ignored.
     10194 *
     10195 * @return true on success
     10196 */
     10197
     10198bool magicNodeResultInsertFits(
     10199    psDB            *dbh,               ///< Database handle
     10200    const psFits    *fits               ///< psFits object
     10201);
     10202
     10203/** Selects up to limit from the database and returns them in a binary FITS table
     10204 *
     10205 * This function assumes an empty psFits object and will create a FITS table
     10206 * as the first extension.
     10207 *
     10208 *  See psDBSelectRows() for documentation on the format of where.
     10209 *
     10210 * @return true on success
     10211 */
     10212
     10213bool magicNodeResultSelectRowsFits(
     10214    psDB            *dbh,               ///< Database handle
     10215    psFits          *fits,              ///< psFits object
     10216    const psMetadata *where,            ///< Row match criteria
     10217    unsigned long long limit            ///< Maximum number of elements to return
     10218);
     10219
     10220/** Convert a magicNodeResultRow into an equivalent psMetadata
     10221 *
     10222 * @return A psMetadata pointer or NULL on error
     10223 */
     10224
     10225psMetadata *magicNodeResultMetadataFromObject(
     10226    const magicNodeResultRow *object             ///< fooRow to convert into a psMetadata
     10227);
     10228
     10229/** Convert a psMetadata into an equivalent fooRow
     10230 *
     10231 * @return A magicNodeResultRow pointer or NULL on error
     10232 */
     10233
     10234magicNodeResultRow *magicNodeResultObjectFromMetadata(
     10235    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     10236);
     10237/** Selects up to limit rows from the database and returns as magicNodeResultRow objects in a psArray
     10238 *
     10239 *  See psDBSelectRows() for documentation on the format of where.
     10240 *
     10241 * @return A psArray pointer or NULL on error
     10242 */
     10243
     10244psArray *magicNodeResultSelectRowObjects(
     10245    psDB            *dbh,               ///< Database handle
     10246    const psMetadata *where,            ///< Row match criteria
     10247    unsigned long long limit            ///< Maximum number of elements to return
     10248);
     10249/** Deletes a row from the database coresponding to an magicNodeResult
     10250 *
     10251 *  Note that a 'where' search psMetadata is constructed from each object and
     10252 *  used to find rows to delete.
     10253 *
     10254 * @return A The number of rows removed or a negative value on error
     10255 */
     10256
     10257bool magicNodeResultDeleteObject(
     10258    psDB            *dbh,               ///< Database handle
     10259    const magicNodeResultRow *object    ///< Object to delete
     10260);
     10261/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10262 *
     10263 *  Note that a 'where' search psMetadata is constructed from each object and
     10264 *  used to find rows to delete.
     10265 *
     10266 * @return A The number of rows removed or a negative value on error
     10267 */
     10268
     10269long long magicNodeResultDeleteRowObjects(
     10270    psDB            *dbh,               ///< Database handle
     10271    const psArray   *objects,           ///< Array of objects to delete
     10272    unsigned long long limit            ///< Maximum number of elements to delete
     10273);
     10274/** Formats and prints an array of magicNodeResultRow objects
     10275 *
     10276 * When mdcf is set the formated output is in psMetadataConfig
     10277 * format, otherwise it is in a simple tabular format.
     10278 *
     10279 * @return true on success
     10280 */
     10281
     10282bool magicNodeResultPrintObjects(
     10283    FILE            *stream,            ///< a stream
     10284    psArray         *objects,           ///< An array of magicNodeResultRow objects
     10285    bool            mdcf                ///< format as mdconfig or simple
     10286);
     10287/** Formats and prints an magicNodeResultRow object
     10288 *
     10289 * When mdcf is set the formated output is in psMetadataConfig
     10290 * format, otherwise it is in a simple tabular format.
     10291 *
     10292 * @return true on success
     10293 */
     10294
     10295bool magicNodeResultPrintObject(
     10296    FILE            *stream,            ///< a stream
     10297    magicNodeResultRow *object,    ///< an magicNodeResultRow object
     10298    bool            mdcf                ///< format as mdconfig or simple
     10299);
     10300/** magicMaskRow data structure
     10301 *
     10302 * Structure for representing a single row of magicMask table data.
     10303 */
     10304
     10305typedef struct {
     10306    psS64           magic_id;
     10307    char            *uri;
     10308} magicMaskRow;
     10309
     10310/** Creates a new magicMaskRow object
     10311 *
     10312 *  @return A new magicMaskRow object or NULL on failure.
     10313 */
     10314
     10315magicMaskRow *magicMaskRowAlloc(
     10316    psS64           magic_id,
     10317    const char      *uri
     10318);
     10319
     10320/** Creates a new magicMask table
     10321 *
     10322 * @return true on success
     10323 */
     10324
     10325bool magicMaskCreateTable(
     10326    psDB            *dbh                ///< Database handle
     10327);
     10328
     10329/** Deletes a magicMask table
     10330 *
     10331 * @return true on success
     10332 */
     10333
     10334bool magicMaskDropTable(
     10335    psDB            *dbh                ///< Database handle
     10336);
     10337
     10338/** Insert a single row into a table
     10339 *
     10340 * This function constructs and inserts a single row based on it's parameters.
     10341 *
     10342 * @return true on success
     10343 */
     10344
     10345bool magicMaskInsert(
     10346    psDB            *dbh,               ///< Database handle
     10347    psS64           magic_id,
     10348    const char      *uri
     10349);
     10350
     10351/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10352 *
     10353 * @return A The number of rows removed or a negative value on error
     10354 */
     10355
     10356long long magicMaskDelete(
     10357    psDB            *dbh,               ///< Database handle
     10358    const psMetadata *where,            ///< Row match criteria
     10359    unsigned long long limit            ///< Maximum number of elements to delete
     10360);
     10361
     10362/** Insert a single magicMaskRow object into a table
     10363 *
     10364 * This function constructs and inserts a single row based on it's parameters.
     10365 *
     10366 * @return true on success
     10367 */
     10368
     10369bool magicMaskInsertObject(
     10370    psDB            *dbh,               ///< Database handle
     10371    magicMaskRow    *object             ///< magicMaskRow object
     10372);
     10373
     10374/** Insert an array of magicMaskRow object into a table
     10375 *
     10376 * This function constructs and inserts multiple rows based on it's parameters.
     10377 *
     10378 * @return true on success
     10379 */
     10380
     10381bool magicMaskInsertObjects(
     10382    psDB            *dbh,               ///< Database handle
     10383    psArray         *objects            ///< array of magicMaskRow objects
     10384);
     10385
     10386/** Insert data from a binary FITS table magicMaskRow into the database
     10387 *
     10388 * This function expects a psFits object with a FITS table as the first
     10389 * extension.  The table must have at least one row of data in it, that is of
     10390 * the appropriate format (number of columns and their type).  All other
     10391 * extensions are ignored.
     10392 *
     10393 * @return true on success
     10394 */
     10395
     10396bool magicMaskInsertFits(
     10397    psDB            *dbh,               ///< Database handle
     10398    const psFits    *fits               ///< psFits object
     10399);
     10400
     10401/** Selects up to limit from the database and returns them in a binary FITS table
     10402 *
     10403 * This function assumes an empty psFits object and will create a FITS table
     10404 * as the first extension.
     10405 *
     10406 *  See psDBSelectRows() for documentation on the format of where.
     10407 *
     10408 * @return true on success
     10409 */
     10410
     10411bool magicMaskSelectRowsFits(
     10412    psDB            *dbh,               ///< Database handle
     10413    psFits          *fits,              ///< psFits object
     10414    const psMetadata *where,            ///< Row match criteria
     10415    unsigned long long limit            ///< Maximum number of elements to return
     10416);
     10417
     10418/** Convert a magicMaskRow into an equivalent psMetadata
     10419 *
     10420 * @return A psMetadata pointer or NULL on error
     10421 */
     10422
     10423psMetadata *magicMaskMetadataFromObject(
     10424    const magicMaskRow *object             ///< fooRow to convert into a psMetadata
     10425);
     10426
     10427/** Convert a psMetadata into an equivalent fooRow
     10428 *
     10429 * @return A magicMaskRow pointer or NULL on error
     10430 */
     10431
     10432magicMaskRow *magicMaskObjectFromMetadata(
     10433    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     10434);
     10435/** Selects up to limit rows from the database and returns as magicMaskRow objects in a psArray
     10436 *
     10437 *  See psDBSelectRows() for documentation on the format of where.
     10438 *
     10439 * @return A psArray pointer or NULL on error
     10440 */
     10441
     10442psArray *magicMaskSelectRowObjects(
     10443    psDB            *dbh,               ///< Database handle
     10444    const psMetadata *where,            ///< Row match criteria
     10445    unsigned long long limit            ///< Maximum number of elements to return
     10446);
     10447/** Deletes a row from the database coresponding to an magicMask
     10448 *
     10449 *  Note that a 'where' search psMetadata is constructed from each object and
     10450 *  used to find rows to delete.
     10451 *
     10452 * @return A The number of rows removed or a negative value on error
     10453 */
     10454
     10455bool magicMaskDeleteObject(
     10456    psDB            *dbh,               ///< Database handle
     10457    const magicMaskRow *object    ///< Object to delete
     10458);
     10459/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10460 *
     10461 *  Note that a 'where' search psMetadata is constructed from each object and
     10462 *  used to find rows to delete.
     10463 *
     10464 * @return A The number of rows removed or a negative value on error
     10465 */
     10466
     10467long long magicMaskDeleteRowObjects(
     10468    psDB            *dbh,               ///< Database handle
     10469    const psArray   *objects,           ///< Array of objects to delete
     10470    unsigned long long limit            ///< Maximum number of elements to delete
     10471);
     10472/** Formats and prints an array of magicMaskRow objects
     10473 *
     10474 * When mdcf is set the formated output is in psMetadataConfig
     10475 * format, otherwise it is in a simple tabular format.
     10476 *
     10477 * @return true on success
     10478 */
     10479
     10480bool magicMaskPrintObjects(
     10481    FILE            *stream,            ///< a stream
     10482    psArray         *objects,           ///< An array of magicMaskRow objects
     10483    bool            mdcf                ///< format as mdconfig or simple
     10484);
     10485/** Formats and prints an magicMaskRow object
     10486 *
     10487 * When mdcf is set the formated output is in psMetadataConfig
     10488 * format, otherwise it is in a simple tabular format.
     10489 *
     10490 * @return true on success
     10491 */
     10492
     10493bool magicMaskPrintObject(
     10494    FILE            *stream,            ///< a stream
     10495    magicMaskRow *object,    ///< an magicMaskRow object
     10496    bool            mdcf                ///< format as mdconfig or simple
     10497);
     10498/** magicSkyfileMaskRow data structure
     10499 *
     10500 * Structure for representing a single row of magicSkyfileMask table data.
     10501 */
     10502
     10503typedef struct {
     10504    psS64           magic_id;
     10505    psS64           diff_id;
     10506    char            *uri;
     10507} magicSkyfileMaskRow;
     10508
     10509/** Creates a new magicSkyfileMaskRow object
     10510 *
     10511 *  @return A new magicSkyfileMaskRow object or NULL on failure.
     10512 */
     10513
     10514magicSkyfileMaskRow *magicSkyfileMaskRowAlloc(
     10515    psS64           magic_id,
     10516    psS64           diff_id,
     10517    const char      *uri
     10518);
     10519
     10520/** Creates a new magicSkyfileMask table
     10521 *
     10522 * @return true on success
     10523 */
     10524
     10525bool magicSkyfileMaskCreateTable(
     10526    psDB            *dbh                ///< Database handle
     10527);
     10528
     10529/** Deletes a magicSkyfileMask table
     10530 *
     10531 * @return true on success
     10532 */
     10533
     10534bool magicSkyfileMaskDropTable(
     10535    psDB            *dbh                ///< Database handle
     10536);
     10537
     10538/** Insert a single row into a table
     10539 *
     10540 * This function constructs and inserts a single row based on it's parameters.
     10541 *
     10542 * @return true on success
     10543 */
     10544
     10545bool magicSkyfileMaskInsert(
     10546    psDB            *dbh,               ///< Database handle
     10547    psS64           magic_id,
     10548    psS64           diff_id,
     10549    const char      *uri
     10550);
     10551
     10552/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10553 *
     10554 * @return A The number of rows removed or a negative value on error
     10555 */
     10556
     10557long long magicSkyfileMaskDelete(
     10558    psDB            *dbh,               ///< Database handle
     10559    const psMetadata *where,            ///< Row match criteria
     10560    unsigned long long limit            ///< Maximum number of elements to delete
     10561);
     10562
     10563/** Insert a single magicSkyfileMaskRow object into a table
     10564 *
     10565 * This function constructs and inserts a single row based on it's parameters.
     10566 *
     10567 * @return true on success
     10568 */
     10569
     10570bool magicSkyfileMaskInsertObject(
     10571    psDB            *dbh,               ///< Database handle
     10572    magicSkyfileMaskRow *object             ///< magicSkyfileMaskRow object
     10573);
     10574
     10575/** Insert an array of magicSkyfileMaskRow object into a table
     10576 *
     10577 * This function constructs and inserts multiple rows based on it's parameters.
     10578 *
     10579 * @return true on success
     10580 */
     10581
     10582bool magicSkyfileMaskInsertObjects(
     10583    psDB            *dbh,               ///< Database handle
     10584    psArray         *objects            ///< array of magicSkyfileMaskRow objects
     10585);
     10586
     10587/** Insert data from a binary FITS table magicSkyfileMaskRow into the database
     10588 *
     10589 * This function expects a psFits object with a FITS table as the first
     10590 * extension.  The table must have at least one row of data in it, that is of
     10591 * the appropriate format (number of columns and their type).  All other
     10592 * extensions are ignored.
     10593 *
     10594 * @return true on success
     10595 */
     10596
     10597bool magicSkyfileMaskInsertFits(
     10598    psDB            *dbh,               ///< Database handle
     10599    const psFits    *fits               ///< psFits object
     10600);
     10601
     10602/** Selects up to limit from the database and returns them in a binary FITS table
     10603 *
     10604 * This function assumes an empty psFits object and will create a FITS table
     10605 * as the first extension.
     10606 *
     10607 *  See psDBSelectRows() for documentation on the format of where.
     10608 *
     10609 * @return true on success
     10610 */
     10611
     10612bool magicSkyfileMaskSelectRowsFits(
     10613    psDB            *dbh,               ///< Database handle
     10614    psFits          *fits,              ///< psFits object
     10615    const psMetadata *where,            ///< Row match criteria
     10616    unsigned long long limit            ///< Maximum number of elements to return
     10617);
     10618
     10619/** Convert a magicSkyfileMaskRow into an equivalent psMetadata
     10620 *
     10621 * @return A psMetadata pointer or NULL on error
     10622 */
     10623
     10624psMetadata *magicSkyfileMaskMetadataFromObject(
     10625    const magicSkyfileMaskRow *object             ///< fooRow to convert into a psMetadata
     10626);
     10627
     10628/** Convert a psMetadata into an equivalent fooRow
     10629 *
     10630 * @return A magicSkyfileMaskRow pointer or NULL on error
     10631 */
     10632
     10633magicSkyfileMaskRow *magicSkyfileMaskObjectFromMetadata(
     10634    psMetadata      *md                 ///< psMetadata to convert into a fooRow
     10635);
     10636/** Selects up to limit rows from the database and returns as magicSkyfileMaskRow objects in a psArray
     10637 *
     10638 *  See psDBSelectRows() for documentation on the format of where.
     10639 *
     10640 * @return A psArray pointer or NULL on error
     10641 */
     10642
     10643psArray *magicSkyfileMaskSelectRowObjects(
     10644    psDB            *dbh,               ///< Database handle
     10645    const psMetadata *where,            ///< Row match criteria
     10646    unsigned long long limit            ///< Maximum number of elements to return
     10647);
     10648/** Deletes a row from the database coresponding to an magicSkyfileMask
     10649 *
     10650 *  Note that a 'where' search psMetadata is constructed from each object and
     10651 *  used to find rows to delete.
     10652 *
     10653 * @return A The number of rows removed or a negative value on error
     10654 */
     10655
     10656bool magicSkyfileMaskDeleteObject(
     10657    psDB            *dbh,               ///< Database handle
     10658    const magicSkyfileMaskRow *object    ///< Object to delete
     10659);
     10660/** Deletes up to limit rows from the database and returns the number of rows actually deleted.
     10661 *
     10662 *  Note that a 'where' search psMetadata is constructed from each object and
     10663 *  used to find rows to delete.
     10664 *
     10665 * @return A The number of rows removed or a negative value on error
     10666 */
     10667
     10668long long magicSkyfileMaskDeleteRowObjects(
     10669    psDB            *dbh,               ///< Database handle
     10670    const psArray   *objects,           ///< Array of objects to delete
     10671    unsigned long long limit            ///< Maximum number of elements to delete
     10672);
     10673/** Formats and prints an array of magicSkyfileMaskRow objects
     10674 *
     10675 * When mdcf is set the formated output is in psMetadataConfig
     10676 * format, otherwise it is in a simple tabular format.
     10677 *
     10678 * @return true on success
     10679 */
     10680
     10681bool magicSkyfileMaskPrintObjects(
     10682    FILE            *stream,            ///< a stream
     10683    psArray         *objects,           ///< An array of magicSkyfileMaskRow objects
     10684    bool            mdcf                ///< format as mdconfig or simple
     10685);
     10686/** Formats and prints an magicSkyfileMaskRow object
     10687 *
     10688 * When mdcf is set the formated output is in psMetadataConfig
     10689 * format, otherwise it is in a simple tabular format.
     10690 *
     10691 * @return true on success
     10692 */
     10693
     10694bool magicSkyfileMaskPrintObject(
     10695    FILE            *stream,            ///< a stream
     10696    magicSkyfileMaskRow *object,    ///< an magicSkyfileMaskRow object
     10697    bool            mdcf                ///< format as mdconfig or simple
     10698);
    877610699
    877710700/// @}
     
    878110704#endif
    878210705
    8783 #endif // DETRUNSUMMARY_DB_H
     10706#endif // MAGICSKYFILEMASK_DB_H
Note: See TracChangeset for help on using the changeset viewer.