IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Dec 12, 2006, 5:52:50 PM (20 years ago)
Author:
jhoblitt
Message:

VERSION 0.0.65

File:
1 edited

Legend:

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

    r10449 r10681  
    6363#define DETRESIDEXP_TABLE_NAME "detResidExp"
    6464#define DETRUNSUMMARY_TABLE_NAME "detRunSummary"
     65#define P4RUN_TABLE_NAME "p4Run"
     66#define P4INPUTIMFILE_TABLE_NAME "p4InputImfile"
     67#define P4PWARPEDIMFILE_TABLE_NAME "p4PWarpedImfile"
     68#define P4PSTACKEDIMFILE_TABLE_NAME "p4PStackedImfile"
     69#define P4PDIFFIMFILE_TABLE_NAME "p4PDiffImfile"
     70#define P4PMAGICMASKIMFILE_TABLE_NAME "p4PMagicMaskImfile"
    6571#define MAX_STRING_LENGTH 1024
    6672
     
    1316413170    return true;
    1316513171}
     13172static void p4RunRowFree(p4RunRow *object);
     13173
     13174p4RunRow *p4RunRowAlloc(psS32 p4_id, const char *survey_mode, const char *state, const char *filter, const char *skycell_id, const char *tess_id, psF64 ra, psF64 decl, const char *input_ss, const char *output_ss)
     13175{
     13176    p4RunRow        *_object;
     13177
     13178    _object = psAlloc(sizeof(p4RunRow));
     13179    psMemSetDeallocator(_object, (psFreeFunc)p4RunRowFree);
     13180
     13181    _object->p4_id = p4_id;
     13182    _object->survey_mode = psStringCopy(survey_mode);
     13183    _object->state = psStringCopy(state);
     13184    _object->filter = psStringCopy(filter);
     13185    _object->skycell_id = psStringCopy(skycell_id);
     13186    _object->tess_id = psStringCopy(tess_id);
     13187    _object->ra = ra;
     13188    _object->decl = decl;
     13189    _object->input_ss = psStringCopy(input_ss);
     13190    _object->output_ss = psStringCopy(output_ss);
     13191
     13192    return _object;
     13193}
     13194
     13195static void p4RunRowFree(p4RunRow *object)
     13196{
     13197    psFree(object->survey_mode);
     13198    psFree(object->state);
     13199    psFree(object->filter);
     13200    psFree(object->skycell_id);
     13201    psFree(object->tess_id);
     13202    psFree(object->input_ss);
     13203    psFree(object->output_ss);
     13204}
     13205
     13206bool p4RunCreateTable(psDB *dbh)
     13207{
     13208    psMetadata *md = psMetadataAlloc();
     13209    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, "Primary Key AUTO_INCREMENT", 0)) {
     13210        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13211        psFree(md);
     13212        return false;
     13213    }
     13214    if (!psMetadataAdd(md, PS_LIST_TAIL, "survey_mode", PS_DATA_STRING, "Key", "64")) {
     13215        psError(PS_ERR_UNKNOWN, false, "failed to add item survey_mode");
     13216        psFree(md);
     13217        return false;
     13218    }
     13219    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, "Key", "64")) {
     13220        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     13221        psFree(md);
     13222        return false;
     13223    }
     13224    if (!psMetadataAdd(md, PS_LIST_TAIL, "filter", PS_DATA_STRING, NULL, "64")) {
     13225        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
     13226        psFree(md);
     13227        return false;
     13228    }
     13229    if (!psMetadataAdd(md, PS_LIST_TAIL, "skycell_id", PS_DATA_STRING, NULL, "64")) {
     13230        psError(PS_ERR_UNKNOWN, false, "failed to add item skycell_id");
     13231        psFree(md);
     13232        return false;
     13233    }
     13234    if (!psMetadataAdd(md, PS_LIST_TAIL, "tess_id", PS_DATA_STRING, NULL, "64")) {
     13235        psError(PS_ERR_UNKNOWN, false, "failed to add item tess_id");
     13236        psFree(md);
     13237        return false;
     13238    }
     13239    if (!psMetadataAdd(md, PS_LIST_TAIL, "ra", PS_DATA_F64, NULL, 0.0)) {
     13240        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
     13241        psFree(md);
     13242        return false;
     13243    }
     13244    if (!psMetadataAdd(md, PS_LIST_TAIL, "decl", PS_DATA_F64, NULL, 0.0)) {
     13245        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
     13246        psFree(md);
     13247        return false;
     13248    }
     13249    if (!psMetadataAdd(md, PS_LIST_TAIL, "input_ss", PS_DATA_STRING, NULL, "64")) {
     13250        psError(PS_ERR_UNKNOWN, false, "failed to add item input_ss");
     13251        psFree(md);
     13252        return false;
     13253    }
     13254    if (!psMetadataAdd(md, PS_LIST_TAIL, "output_ss", PS_DATA_STRING, NULL, "64")) {
     13255        psError(PS_ERR_UNKNOWN, false, "failed to add item output_ss");
     13256        psFree(md);
     13257        return false;
     13258    }
     13259
     13260    bool status = psDBCreateTable(dbh, P4RUN_TABLE_NAME, md);
     13261
     13262    psFree(md);
     13263
     13264    return status;
     13265}
     13266
     13267bool p4RunDropTable(psDB *dbh)
     13268{
     13269    return psDBDropTable(dbh, P4RUN_TABLE_NAME);
     13270}
     13271
     13272bool p4RunInsert(psDB * dbh, psS32 p4_id, const char *survey_mode, const char *state, const char *filter, const char *skycell_id, const char *tess_id, psF64 ra, psF64 decl, const char *input_ss, const char *output_ss)
     13273{
     13274    psMetadata *md = psMetadataAlloc();
     13275    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, p4_id)) {
     13276        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13277        psFree(md);
     13278        return false;
     13279    }
     13280    if (!psMetadataAdd(md, PS_LIST_TAIL, "survey_mode", PS_DATA_STRING, NULL, survey_mode)) {
     13281        psError(PS_ERR_UNKNOWN, false, "failed to add item survey_mode");
     13282        psFree(md);
     13283        return false;
     13284    }
     13285    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, NULL, state)) {
     13286        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     13287        psFree(md);
     13288        return false;
     13289    }
     13290    if (!psMetadataAdd(md, PS_LIST_TAIL, "filter", PS_DATA_STRING, NULL, filter)) {
     13291        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
     13292        psFree(md);
     13293        return false;
     13294    }
     13295    if (!psMetadataAdd(md, PS_LIST_TAIL, "skycell_id", PS_DATA_STRING, NULL, skycell_id)) {
     13296        psError(PS_ERR_UNKNOWN, false, "failed to add item skycell_id");
     13297        psFree(md);
     13298        return false;
     13299    }
     13300    if (!psMetadataAdd(md, PS_LIST_TAIL, "tess_id", PS_DATA_STRING, NULL, tess_id)) {
     13301        psError(PS_ERR_UNKNOWN, false, "failed to add item tess_id");
     13302        psFree(md);
     13303        return false;
     13304    }
     13305    if (!psMetadataAdd(md, PS_LIST_TAIL, "ra", PS_DATA_F64, NULL, ra)) {
     13306        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
     13307        psFree(md);
     13308        return false;
     13309    }
     13310    if (!psMetadataAdd(md, PS_LIST_TAIL, "decl", PS_DATA_F64, NULL, decl)) {
     13311        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
     13312        psFree(md);
     13313        return false;
     13314    }
     13315    if (!psMetadataAdd(md, PS_LIST_TAIL, "input_ss", PS_DATA_STRING, NULL, input_ss)) {
     13316        psError(PS_ERR_UNKNOWN, false, "failed to add item input_ss");
     13317        psFree(md);
     13318        return false;
     13319    }
     13320    if (!psMetadataAdd(md, PS_LIST_TAIL, "output_ss", PS_DATA_STRING, NULL, output_ss)) {
     13321        psError(PS_ERR_UNKNOWN, false, "failed to add item output_ss");
     13322        psFree(md);
     13323        return false;
     13324    }
     13325
     13326    bool status = psDBInsertOneRow(dbh, P4RUN_TABLE_NAME, md);
     13327    psFree(md);
     13328
     13329    return status;
     13330}
     13331
     13332long long p4RunDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     13333{
     13334    long long       deleted = 0;
     13335
     13336    long long count = psDBDeleteRows(dbh, P4RUN_TABLE_NAME, where, limit);
     13337    if (count < 0) {
     13338        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4Run");
     13339        return count;
     13340
     13341        deleted += count;
     13342    }
     13343
     13344    return deleted;
     13345}
     13346bool p4RunInsertObject(psDB *dbh, p4RunRow *object)
     13347{
     13348    return p4RunInsert(dbh, object->p4_id, object->survey_mode, object->state, object->filter, object->skycell_id, object->tess_id, object->ra, object->decl, object->input_ss, object->output_ss);
     13349}
     13350
     13351bool p4RunInsertObjects(psDB *dbh, psArray *objects)
     13352{
     13353    for (long i = 0; i < psArrayLength(objects); i++) {
     13354        if (!p4RunInsertObject(dbh, objects->data[i])) {
     13355            return false;
     13356        }
     13357    }
     13358
     13359    return true;
     13360}
     13361
     13362bool p4RunInsertFits(psDB *dbh, const psFits *fits)
     13363{
     13364    psArray         *rowSet;
     13365
     13366    // move to (the first?) extension named  P4RUN_TABLE_NAME
     13367    if (!psFitsMoveExtName(fits, P4RUN_TABLE_NAME)) {
     13368        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P4RUN_TABLE_NAME);
     13369        return false;
     13370    }
     13371
     13372    // check HDU type
     13373    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     13374        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     13375        return false;
     13376    }
     13377
     13378    // read fits table
     13379    rowSet = psFitsReadTable(fits);
     13380    if (!rowSet) {
     13381        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     13382        psFree(rowSet);
     13383        return false;
     13384    }
     13385
     13386    if (!psDBInsertRows(dbh, P4RUN_TABLE_NAME, rowSet)) {
     13387        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     13388        psFree(rowSet);
     13389        return false;
     13390    }
     13391
     13392    psFree(rowSet);
     13393
     13394    return true;
     13395}
     13396
     13397bool p4RunSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     13398{
     13399    psArray         *rowSet;
     13400
     13401    rowSet = psDBSelectRows(dbh, P4RUN_TABLE_NAME, where, limit);
     13402    if (!rowSet) {
     13403        return false;
     13404    }
     13405
     13406    // output to fits
     13407    if (!psFitsWriteTable(fits, NULL, rowSet, P4RUN_TABLE_NAME)) {
     13408        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     13409        psFree(rowSet);
     13410        return false;
     13411    }
     13412
     13413    psFree(rowSet);
     13414
     13415    return true;
     13416}
     13417
     13418psMetadata *p4RunMetadataFromObject(const p4RunRow *object)
     13419{
     13420    psMetadata *md = psMetadataAlloc();
     13421    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, object->p4_id)) {
     13422        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13423        psFree(md);
     13424        return false;
     13425    }
     13426    if (!psMetadataAdd(md, PS_LIST_TAIL, "survey_mode", PS_DATA_STRING, NULL, object->survey_mode)) {
     13427        psError(PS_ERR_UNKNOWN, false, "failed to add item survey_mode");
     13428        psFree(md);
     13429        return false;
     13430    }
     13431    if (!psMetadataAdd(md, PS_LIST_TAIL, "state", PS_DATA_STRING, NULL, object->state)) {
     13432        psError(PS_ERR_UNKNOWN, false, "failed to add item state");
     13433        psFree(md);
     13434        return false;
     13435    }
     13436    if (!psMetadataAdd(md, PS_LIST_TAIL, "filter", PS_DATA_STRING, NULL, object->filter)) {
     13437        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
     13438        psFree(md);
     13439        return false;
     13440    }
     13441    if (!psMetadataAdd(md, PS_LIST_TAIL, "skycell_id", PS_DATA_STRING, NULL, object->skycell_id)) {
     13442        psError(PS_ERR_UNKNOWN, false, "failed to add item skycell_id");
     13443        psFree(md);
     13444        return false;
     13445    }
     13446    if (!psMetadataAdd(md, PS_LIST_TAIL, "tess_id", PS_DATA_STRING, NULL, object->tess_id)) {
     13447        psError(PS_ERR_UNKNOWN, false, "failed to add item tess_id");
     13448        psFree(md);
     13449        return false;
     13450    }
     13451    if (!psMetadataAdd(md, PS_LIST_TAIL, "ra", PS_DATA_F64, NULL, object->ra)) {
     13452        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
     13453        psFree(md);
     13454        return false;
     13455    }
     13456    if (!psMetadataAdd(md, PS_LIST_TAIL, "decl", PS_DATA_F64, NULL, object->decl)) {
     13457        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
     13458        psFree(md);
     13459        return false;
     13460    }
     13461    if (!psMetadataAdd(md, PS_LIST_TAIL, "input_ss", PS_DATA_STRING, NULL, object->input_ss)) {
     13462        psError(PS_ERR_UNKNOWN, false, "failed to add item input_ss");
     13463        psFree(md);
     13464        return false;
     13465    }
     13466    if (!psMetadataAdd(md, PS_LIST_TAIL, "output_ss", PS_DATA_STRING, NULL, object->output_ss)) {
     13467        psError(PS_ERR_UNKNOWN, false, "failed to add item output_ss");
     13468        psFree(md);
     13469        return false;
     13470    }
     13471
     13472
     13473    return md;
     13474}
     13475
     13476p4RunRow *p4RunObjectFromMetadata(psMetadata *md)
     13477{
     13478
     13479bool status = false;
     13480    psS32 p4_id = psMetadataLookupS32(&status, md, "p4_id");
     13481    if (!status) {
     13482        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p4_id");
     13483        return false;
     13484    }
     13485    char* survey_mode = psMetadataLookupPtr(&status, md, "survey_mode");
     13486    if (!status) {
     13487        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item survey_mode");
     13488        return false;
     13489    }
     13490    char* state = psMetadataLookupPtr(&status, md, "state");
     13491    if (!status) {
     13492        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item state");
     13493        return false;
     13494    }
     13495    char* filter = psMetadataLookupPtr(&status, md, "filter");
     13496    if (!status) {
     13497        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
     13498        return false;
     13499    }
     13500    char* skycell_id = psMetadataLookupPtr(&status, md, "skycell_id");
     13501    if (!status) {
     13502        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item skycell_id");
     13503        return false;
     13504    }
     13505    char* tess_id = psMetadataLookupPtr(&status, md, "tess_id");
     13506    if (!status) {
     13507        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item tess_id");
     13508        return false;
     13509    }
     13510    psF64 ra = psMetadataLookupF64(&status, md, "ra");
     13511    if (!status) {
     13512        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
     13513        return false;
     13514    }
     13515    psF64 decl = psMetadataLookupF64(&status, md, "decl");
     13516    if (!status) {
     13517        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
     13518        return false;
     13519    }
     13520    char* input_ss = psMetadataLookupPtr(&status, md, "input_ss");
     13521    if (!status) {
     13522        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item input_ss");
     13523        return false;
     13524    }
     13525    char* output_ss = psMetadataLookupPtr(&status, md, "output_ss");
     13526    if (!status) {
     13527        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item output_ss");
     13528        return false;
     13529    }
     13530
     13531    return p4RunRowAlloc(p4_id, survey_mode, state, filter, skycell_id, tess_id, ra, decl, input_ss, output_ss);
     13532}
     13533psArray *p4RunSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     13534{
     13535    psArray         *rowSet;
     13536    psArray         *returnSet;
     13537    psU64           i;
     13538
     13539    rowSet = psDBSelectRows(dbh, P4RUN_TABLE_NAME, where, limit);
     13540    if (!rowSet) {
     13541        return NULL;
     13542    }
     13543
     13544    // convert psMetadata rows to row objects
     13545
     13546    returnSet = psArrayAllocEmpty(rowSet->n);
     13547
     13548    for (i = 0; i < rowSet->n; i++) {
     13549        p4RunRow *object = p4RunObjectFromMetadata(rowSet->data[i]);
     13550        psArrayAdd(returnSet, 0, object);
     13551        psFree(object);
     13552    }
     13553
     13554    psFree(rowSet);
     13555
     13556    return returnSet;
     13557}
     13558bool p4RunDeleteObject(psDB *dbh, const p4RunRow *object)
     13559{
     13560    psMetadata *where = p4RunMetadataFromObject(object);
     13561    long long count = psDBDeleteRows(dbh, P4RUN_TABLE_NAME, where, 0);
     13562    psFree(where)
     13563    if (count < 0) {
     13564        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4Run");
     13565        return false;
     13566    }
     13567    if (count > 1) {
     13568        // XXX should this be a psAbort() instead?  It is possible that
     13569        // having an object match multiple rows was by design.
     13570        psError(PS_ERR_UNKNOWN, true, "p4RunRow object matched more then one row.  Check your database schema");
     13571        return false;
     13572    }
     13573
     13574    return true;
     13575}
     13576long long p4RunDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     13577{
     13578    long long       deleted = 0;
     13579
     13580    for (long long i = 0; i < objects->n; i++) {
     13581        p4RunRow *object = objects->data[i];
     13582        psMetadata *where = p4RunMetadataFromObject(object);
     13583        long long count = psDBDeleteRows(dbh, P4RUN_TABLE_NAME, where, limit);
     13584        psFree(where)
     13585        if (count < 0) {
     13586            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4Run");
     13587            return count;
     13588        }
     13589
     13590        deleted += count;
     13591    }
     13592
     13593    return deleted;
     13594}
     13595bool p4RunPrintObjects(FILE *stream, psArray *objects, bool mdcf)
     13596{
     13597    PS_ASSERT_PTR_NON_NULL(objects, false);
     13598
     13599    psMetadata *output = psMetadataAlloc();
     13600    for (long i = 0; i < psArrayLength(objects); i++) {
     13601        psMetadata *md = p4RunMetadataFromObject(objects->data[i]);
     13602        if (!psMetadataAddMetadata(
     13603            output,
     13604            PS_LIST_TAIL,
     13605            P4RUN_TABLE_NAME,
     13606            PS_META_DUPLICATE_OK,
     13607            NULL,
     13608            md
     13609        )) {
     13610            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     13611            psFree(md);
     13612            psFree(output);
     13613            return false;
     13614        }
     13615        psFree(md);
     13616    }
     13617
     13618    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     13619        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     13620        psFree(output);
     13621    }
     13622    psFree(output);
     13623
     13624    return true;
     13625}
     13626static void p4InputImfileRowFree(p4InputImfileRow *object);
     13627
     13628p4InputImfileRow *p4InputImfileRowAlloc(psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id)
     13629{
     13630    p4InputImfileRow *_object;
     13631
     13632    _object = psAlloc(sizeof(p4InputImfileRow));
     13633    psMemSetDeallocator(_object, (psFreeFunc)p4InputImfileRowFree);
     13634
     13635    _object->p4_id = p4_id;
     13636    _object->exp_tag = psStringCopy(exp_tag);
     13637    _object->p3_version = p3_version;
     13638    _object->class_id = psStringCopy(class_id);
     13639
     13640    return _object;
     13641}
     13642
     13643static void p4InputImfileRowFree(p4InputImfileRow *object)
     13644{
     13645    psFree(object->exp_tag);
     13646    psFree(object->class_id);
     13647}
     13648
     13649bool p4InputImfileCreateTable(psDB *dbh)
     13650{
     13651    psMetadata *md = psMetadataAlloc();
     13652    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, "Primary Key", 0)) {
     13653        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13654        psFree(md);
     13655        return false;
     13656    }
     13657    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Primary Key", "64")) {
     13658        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     13659        psFree(md);
     13660        return false;
     13661    }
     13662    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, "Primary Key", 0)) {
     13663        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     13664        psFree(md);
     13665        return false;
     13666    }
     13667    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     13668        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     13669        psFree(md);
     13670        return false;
     13671    }
     13672
     13673    bool status = psDBCreateTable(dbh, P4INPUTIMFILE_TABLE_NAME, md);
     13674
     13675    psFree(md);
     13676
     13677    return status;
     13678}
     13679
     13680bool p4InputImfileDropTable(psDB *dbh)
     13681{
     13682    return psDBDropTable(dbh, P4INPUTIMFILE_TABLE_NAME);
     13683}
     13684
     13685bool p4InputImfileInsert(psDB * dbh, psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id)
     13686{
     13687    psMetadata *md = psMetadataAlloc();
     13688    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, p4_id)) {
     13689        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13690        psFree(md);
     13691        return false;
     13692    }
     13693    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
     13694        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     13695        psFree(md);
     13696        return false;
     13697    }
     13698    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, p3_version)) {
     13699        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     13700        psFree(md);
     13701        return false;
     13702    }
     13703    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     13704        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     13705        psFree(md);
     13706        return false;
     13707    }
     13708
     13709    bool status = psDBInsertOneRow(dbh, P4INPUTIMFILE_TABLE_NAME, md);
     13710    psFree(md);
     13711
     13712    return status;
     13713}
     13714
     13715long long p4InputImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     13716{
     13717    long long       deleted = 0;
     13718
     13719    long long count = psDBDeleteRows(dbh, P4INPUTIMFILE_TABLE_NAME, where, limit);
     13720    if (count < 0) {
     13721        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4InputImfile");
     13722        return count;
     13723
     13724        deleted += count;
     13725    }
     13726
     13727    return deleted;
     13728}
     13729bool p4InputImfileInsertObject(psDB *dbh, p4InputImfileRow *object)
     13730{
     13731    return p4InputImfileInsert(dbh, object->p4_id, object->exp_tag, object->p3_version, object->class_id);
     13732}
     13733
     13734bool p4InputImfileInsertObjects(psDB *dbh, psArray *objects)
     13735{
     13736    for (long i = 0; i < psArrayLength(objects); i++) {
     13737        if (!p4InputImfileInsertObject(dbh, objects->data[i])) {
     13738            return false;
     13739        }
     13740    }
     13741
     13742    return true;
     13743}
     13744
     13745bool p4InputImfileInsertFits(psDB *dbh, const psFits *fits)
     13746{
     13747    psArray         *rowSet;
     13748
     13749    // move to (the first?) extension named  P4INPUTIMFILE_TABLE_NAME
     13750    if (!psFitsMoveExtName(fits, P4INPUTIMFILE_TABLE_NAME)) {
     13751        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P4INPUTIMFILE_TABLE_NAME);
     13752        return false;
     13753    }
     13754
     13755    // check HDU type
     13756    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     13757        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     13758        return false;
     13759    }
     13760
     13761    // read fits table
     13762    rowSet = psFitsReadTable(fits);
     13763    if (!rowSet) {
     13764        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     13765        psFree(rowSet);
     13766        return false;
     13767    }
     13768
     13769    if (!psDBInsertRows(dbh, P4INPUTIMFILE_TABLE_NAME, rowSet)) {
     13770        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     13771        psFree(rowSet);
     13772        return false;
     13773    }
     13774
     13775    psFree(rowSet);
     13776
     13777    return true;
     13778}
     13779
     13780bool p4InputImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     13781{
     13782    psArray         *rowSet;
     13783
     13784    rowSet = psDBSelectRows(dbh, P4INPUTIMFILE_TABLE_NAME, where, limit);
     13785    if (!rowSet) {
     13786        return false;
     13787    }
     13788
     13789    // output to fits
     13790    if (!psFitsWriteTable(fits, NULL, rowSet, P4INPUTIMFILE_TABLE_NAME)) {
     13791        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     13792        psFree(rowSet);
     13793        return false;
     13794    }
     13795
     13796    psFree(rowSet);
     13797
     13798    return true;
     13799}
     13800
     13801psMetadata *p4InputImfileMetadataFromObject(const p4InputImfileRow *object)
     13802{
     13803    psMetadata *md = psMetadataAlloc();
     13804    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, object->p4_id)) {
     13805        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13806        psFree(md);
     13807        return false;
     13808    }
     13809    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
     13810        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     13811        psFree(md);
     13812        return false;
     13813    }
     13814    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, object->p3_version)) {
     13815        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     13816        psFree(md);
     13817        return false;
     13818    }
     13819    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     13820        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     13821        psFree(md);
     13822        return false;
     13823    }
     13824
     13825
     13826    return md;
     13827}
     13828
     13829p4InputImfileRow *p4InputImfileObjectFromMetadata(psMetadata *md)
     13830{
     13831
     13832bool status = false;
     13833    psS32 p4_id = psMetadataLookupS32(&status, md, "p4_id");
     13834    if (!status) {
     13835        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p4_id");
     13836        return false;
     13837    }
     13838    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
     13839    if (!status) {
     13840        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
     13841        return false;
     13842    }
     13843    psS32 p3_version = psMetadataLookupS32(&status, md, "p3_version");
     13844    if (!status) {
     13845        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p3_version");
     13846        return false;
     13847    }
     13848    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     13849    if (!status) {
     13850        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     13851        return false;
     13852    }
     13853
     13854    return p4InputImfileRowAlloc(p4_id, exp_tag, p3_version, class_id);
     13855}
     13856psArray *p4InputImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     13857{
     13858    psArray         *rowSet;
     13859    psArray         *returnSet;
     13860    psU64           i;
     13861
     13862    rowSet = psDBSelectRows(dbh, P4INPUTIMFILE_TABLE_NAME, where, limit);
     13863    if (!rowSet) {
     13864        return NULL;
     13865    }
     13866
     13867    // convert psMetadata rows to row objects
     13868
     13869    returnSet = psArrayAllocEmpty(rowSet->n);
     13870
     13871    for (i = 0; i < rowSet->n; i++) {
     13872        p4InputImfileRow *object = p4InputImfileObjectFromMetadata(rowSet->data[i]);
     13873        psArrayAdd(returnSet, 0, object);
     13874        psFree(object);
     13875    }
     13876
     13877    psFree(rowSet);
     13878
     13879    return returnSet;
     13880}
     13881bool p4InputImfileDeleteObject(psDB *dbh, const p4InputImfileRow *object)
     13882{
     13883    psMetadata *where = p4InputImfileMetadataFromObject(object);
     13884    long long count = psDBDeleteRows(dbh, P4INPUTIMFILE_TABLE_NAME, where, 0);
     13885    psFree(where)
     13886    if (count < 0) {
     13887        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4InputImfile");
     13888        return false;
     13889    }
     13890    if (count > 1) {
     13891        // XXX should this be a psAbort() instead?  It is possible that
     13892        // having an object match multiple rows was by design.
     13893        psError(PS_ERR_UNKNOWN, true, "p4InputImfileRow object matched more then one row.  Check your database schema");
     13894        return false;
     13895    }
     13896
     13897    return true;
     13898}
     13899long long p4InputImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     13900{
     13901    long long       deleted = 0;
     13902
     13903    for (long long i = 0; i < objects->n; i++) {
     13904        p4InputImfileRow *object = objects->data[i];
     13905        psMetadata *where = p4InputImfileMetadataFromObject(object);
     13906        long long count = psDBDeleteRows(dbh, P4INPUTIMFILE_TABLE_NAME, where, limit);
     13907        psFree(where)
     13908        if (count < 0) {
     13909            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4InputImfile");
     13910            return count;
     13911        }
     13912
     13913        deleted += count;
     13914    }
     13915
     13916    return deleted;
     13917}
     13918bool p4InputImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     13919{
     13920    PS_ASSERT_PTR_NON_NULL(objects, false);
     13921
     13922    psMetadata *output = psMetadataAlloc();
     13923    for (long i = 0; i < psArrayLength(objects); i++) {
     13924        psMetadata *md = p4InputImfileMetadataFromObject(objects->data[i]);
     13925        if (!psMetadataAddMetadata(
     13926            output,
     13927            PS_LIST_TAIL,
     13928            P4INPUTIMFILE_TABLE_NAME,
     13929            PS_META_DUPLICATE_OK,
     13930            NULL,
     13931            md
     13932        )) {
     13933            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     13934            psFree(md);
     13935            psFree(output);
     13936            return false;
     13937        }
     13938        psFree(md);
     13939    }
     13940
     13941    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     13942        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     13943        psFree(output);
     13944    }
     13945    psFree(output);
     13946
     13947    return true;
     13948}
     13949static void p4PWarpedImfileRowFree(p4PWarpedImfileRow *object);
     13950
     13951p4PWarpedImfileRow *p4PWarpedImfileRowAlloc(psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id, const char *uri, const char *b1_uri, const char *b2_uri)
     13952{
     13953    p4PWarpedImfileRow *_object;
     13954
     13955    _object = psAlloc(sizeof(p4PWarpedImfileRow));
     13956    psMemSetDeallocator(_object, (psFreeFunc)p4PWarpedImfileRowFree);
     13957
     13958    _object->p4_id = p4_id;
     13959    _object->exp_tag = psStringCopy(exp_tag);
     13960    _object->p3_version = p3_version;
     13961    _object->class_id = psStringCopy(class_id);
     13962    _object->uri = psStringCopy(uri);
     13963    _object->b1_uri = psStringCopy(b1_uri);
     13964    _object->b2_uri = psStringCopy(b2_uri);
     13965
     13966    return _object;
     13967}
     13968
     13969static void p4PWarpedImfileRowFree(p4PWarpedImfileRow *object)
     13970{
     13971    psFree(object->exp_tag);
     13972    psFree(object->class_id);
     13973    psFree(object->uri);
     13974    psFree(object->b1_uri);
     13975    psFree(object->b2_uri);
     13976}
     13977
     13978bool p4PWarpedImfileCreateTable(psDB *dbh)
     13979{
     13980    psMetadata *md = psMetadataAlloc();
     13981    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, "Primary Key", 0)) {
     13982        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     13983        psFree(md);
     13984        return false;
     13985    }
     13986    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Primary Key", "64")) {
     13987        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     13988        psFree(md);
     13989        return false;
     13990    }
     13991    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, "Primary Key", 0)) {
     13992        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     13993        psFree(md);
     13994        return false;
     13995    }
     13996    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     13997        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     13998        psFree(md);
     13999        return false;
     14000    }
     14001    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     14002        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14003        psFree(md);
     14004        return false;
     14005    }
     14006    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, "255")) {
     14007        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14008        psFree(md);
     14009        return false;
     14010    }
     14011    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, "255")) {
     14012        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14013        psFree(md);
     14014        return false;
     14015    }
     14016
     14017    bool status = psDBCreateTable(dbh, P4PWARPEDIMFILE_TABLE_NAME, md);
     14018
     14019    psFree(md);
     14020
     14021    return status;
     14022}
     14023
     14024bool p4PWarpedImfileDropTable(psDB *dbh)
     14025{
     14026    return psDBDropTable(dbh, P4PWARPEDIMFILE_TABLE_NAME);
     14027}
     14028
     14029bool p4PWarpedImfileInsert(psDB * dbh, psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id, const char *uri, const char *b1_uri, const char *b2_uri)
     14030{
     14031    psMetadata *md = psMetadataAlloc();
     14032    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, p4_id)) {
     14033        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14034        psFree(md);
     14035        return false;
     14036    }
     14037    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
     14038        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     14039        psFree(md);
     14040        return false;
     14041    }
     14042    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, p3_version)) {
     14043        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     14044        psFree(md);
     14045        return false;
     14046    }
     14047    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     14048        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14049        psFree(md);
     14050        return false;
     14051    }
     14052    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     14053        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14054        psFree(md);
     14055        return false;
     14056    }
     14057    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, b1_uri)) {
     14058        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14059        psFree(md);
     14060        return false;
     14061    }
     14062    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, b2_uri)) {
     14063        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14064        psFree(md);
     14065        return false;
     14066    }
     14067
     14068    bool status = psDBInsertOneRow(dbh, P4PWARPEDIMFILE_TABLE_NAME, md);
     14069    psFree(md);
     14070
     14071    return status;
     14072}
     14073
     14074long long p4PWarpedImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     14075{
     14076    long long       deleted = 0;
     14077
     14078    long long count = psDBDeleteRows(dbh, P4PWARPEDIMFILE_TABLE_NAME, where, limit);
     14079    if (count < 0) {
     14080        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PWarpedImfile");
     14081        return count;
     14082
     14083        deleted += count;
     14084    }
     14085
     14086    return deleted;
     14087}
     14088bool p4PWarpedImfileInsertObject(psDB *dbh, p4PWarpedImfileRow *object)
     14089{
     14090    return p4PWarpedImfileInsert(dbh, object->p4_id, object->exp_tag, object->p3_version, object->class_id, object->uri, object->b1_uri, object->b2_uri);
     14091}
     14092
     14093bool p4PWarpedImfileInsertObjects(psDB *dbh, psArray *objects)
     14094{
     14095    for (long i = 0; i < psArrayLength(objects); i++) {
     14096        if (!p4PWarpedImfileInsertObject(dbh, objects->data[i])) {
     14097            return false;
     14098        }
     14099    }
     14100
     14101    return true;
     14102}
     14103
     14104bool p4PWarpedImfileInsertFits(psDB *dbh, const psFits *fits)
     14105{
     14106    psArray         *rowSet;
     14107
     14108    // move to (the first?) extension named  P4PWARPEDIMFILE_TABLE_NAME
     14109    if (!psFitsMoveExtName(fits, P4PWARPEDIMFILE_TABLE_NAME)) {
     14110        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P4PWARPEDIMFILE_TABLE_NAME);
     14111        return false;
     14112    }
     14113
     14114    // check HDU type
     14115    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     14116        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     14117        return false;
     14118    }
     14119
     14120    // read fits table
     14121    rowSet = psFitsReadTable(fits);
     14122    if (!rowSet) {
     14123        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     14124        psFree(rowSet);
     14125        return false;
     14126    }
     14127
     14128    if (!psDBInsertRows(dbh, P4PWARPEDIMFILE_TABLE_NAME, rowSet)) {
     14129        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     14130        psFree(rowSet);
     14131        return false;
     14132    }
     14133
     14134    psFree(rowSet);
     14135
     14136    return true;
     14137}
     14138
     14139bool p4PWarpedImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     14140{
     14141    psArray         *rowSet;
     14142
     14143    rowSet = psDBSelectRows(dbh, P4PWARPEDIMFILE_TABLE_NAME, where, limit);
     14144    if (!rowSet) {
     14145        return false;
     14146    }
     14147
     14148    // output to fits
     14149    if (!psFitsWriteTable(fits, NULL, rowSet, P4PWARPEDIMFILE_TABLE_NAME)) {
     14150        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     14151        psFree(rowSet);
     14152        return false;
     14153    }
     14154
     14155    psFree(rowSet);
     14156
     14157    return true;
     14158}
     14159
     14160psMetadata *p4PWarpedImfileMetadataFromObject(const p4PWarpedImfileRow *object)
     14161{
     14162    psMetadata *md = psMetadataAlloc();
     14163    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, object->p4_id)) {
     14164        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14165        psFree(md);
     14166        return false;
     14167    }
     14168    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
     14169        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     14170        psFree(md);
     14171        return false;
     14172    }
     14173    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, object->p3_version)) {
     14174        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     14175        psFree(md);
     14176        return false;
     14177    }
     14178    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     14179        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14180        psFree(md);
     14181        return false;
     14182    }
     14183    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     14184        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14185        psFree(md);
     14186        return false;
     14187    }
     14188    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, object->b1_uri)) {
     14189        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14190        psFree(md);
     14191        return false;
     14192    }
     14193    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, object->b2_uri)) {
     14194        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14195        psFree(md);
     14196        return false;
     14197    }
     14198
     14199
     14200    return md;
     14201}
     14202
     14203p4PWarpedImfileRow *p4PWarpedImfileObjectFromMetadata(psMetadata *md)
     14204{
     14205
     14206bool status = false;
     14207    psS32 p4_id = psMetadataLookupS32(&status, md, "p4_id");
     14208    if (!status) {
     14209        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p4_id");
     14210        return false;
     14211    }
     14212    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
     14213    if (!status) {
     14214        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
     14215        return false;
     14216    }
     14217    psS32 p3_version = psMetadataLookupS32(&status, md, "p3_version");
     14218    if (!status) {
     14219        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p3_version");
     14220        return false;
     14221    }
     14222    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     14223    if (!status) {
     14224        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     14225        return false;
     14226    }
     14227    char* uri = psMetadataLookupPtr(&status, md, "uri");
     14228    if (!status) {
     14229        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     14230        return false;
     14231    }
     14232    char* b1_uri = psMetadataLookupPtr(&status, md, "b1_uri");
     14233    if (!status) {
     14234        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b1_uri");
     14235        return false;
     14236    }
     14237    char* b2_uri = psMetadataLookupPtr(&status, md, "b2_uri");
     14238    if (!status) {
     14239        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b2_uri");
     14240        return false;
     14241    }
     14242
     14243    return p4PWarpedImfileRowAlloc(p4_id, exp_tag, p3_version, class_id, uri, b1_uri, b2_uri);
     14244}
     14245psArray *p4PWarpedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     14246{
     14247    psArray         *rowSet;
     14248    psArray         *returnSet;
     14249    psU64           i;
     14250
     14251    rowSet = psDBSelectRows(dbh, P4PWARPEDIMFILE_TABLE_NAME, where, limit);
     14252    if (!rowSet) {
     14253        return NULL;
     14254    }
     14255
     14256    // convert psMetadata rows to row objects
     14257
     14258    returnSet = psArrayAllocEmpty(rowSet->n);
     14259
     14260    for (i = 0; i < rowSet->n; i++) {
     14261        p4PWarpedImfileRow *object = p4PWarpedImfileObjectFromMetadata(rowSet->data[i]);
     14262        psArrayAdd(returnSet, 0, object);
     14263        psFree(object);
     14264    }
     14265
     14266    psFree(rowSet);
     14267
     14268    return returnSet;
     14269}
     14270bool p4PWarpedImfileDeleteObject(psDB *dbh, const p4PWarpedImfileRow *object)
     14271{
     14272    psMetadata *where = p4PWarpedImfileMetadataFromObject(object);
     14273    long long count = psDBDeleteRows(dbh, P4PWARPEDIMFILE_TABLE_NAME, where, 0);
     14274    psFree(where)
     14275    if (count < 0) {
     14276        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PWarpedImfile");
     14277        return false;
     14278    }
     14279    if (count > 1) {
     14280        // XXX should this be a psAbort() instead?  It is possible that
     14281        // having an object match multiple rows was by design.
     14282        psError(PS_ERR_UNKNOWN, true, "p4PWarpedImfileRow object matched more then one row.  Check your database schema");
     14283        return false;
     14284    }
     14285
     14286    return true;
     14287}
     14288long long p4PWarpedImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     14289{
     14290    long long       deleted = 0;
     14291
     14292    for (long long i = 0; i < objects->n; i++) {
     14293        p4PWarpedImfileRow *object = objects->data[i];
     14294        psMetadata *where = p4PWarpedImfileMetadataFromObject(object);
     14295        long long count = psDBDeleteRows(dbh, P4PWARPEDIMFILE_TABLE_NAME, where, limit);
     14296        psFree(where)
     14297        if (count < 0) {
     14298            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PWarpedImfile");
     14299            return count;
     14300        }
     14301
     14302        deleted += count;
     14303    }
     14304
     14305    return deleted;
     14306}
     14307bool p4PWarpedImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     14308{
     14309    PS_ASSERT_PTR_NON_NULL(objects, false);
     14310
     14311    psMetadata *output = psMetadataAlloc();
     14312    for (long i = 0; i < psArrayLength(objects); i++) {
     14313        psMetadata *md = p4PWarpedImfileMetadataFromObject(objects->data[i]);
     14314        if (!psMetadataAddMetadata(
     14315            output,
     14316            PS_LIST_TAIL,
     14317            P4PWARPEDIMFILE_TABLE_NAME,
     14318            PS_META_DUPLICATE_OK,
     14319            NULL,
     14320            md
     14321        )) {
     14322            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     14323            psFree(md);
     14324            psFree(output);
     14325            return false;
     14326        }
     14327        psFree(md);
     14328    }
     14329
     14330    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     14331        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     14332        psFree(output);
     14333    }
     14334    psFree(output);
     14335
     14336    return true;
     14337}
     14338static void p4PStackedImfileRowFree(p4PStackedImfileRow *object);
     14339
     14340p4PStackedImfileRow *p4PStackedImfileRowAlloc(psS32 p4_id, const char *class_id, const char *uri, const char *b1_uri, const char *b2_uri)
     14341{
     14342    p4PStackedImfileRow *_object;
     14343
     14344    _object = psAlloc(sizeof(p4PStackedImfileRow));
     14345    psMemSetDeallocator(_object, (psFreeFunc)p4PStackedImfileRowFree);
     14346
     14347    _object->p4_id = p4_id;
     14348    _object->class_id = psStringCopy(class_id);
     14349    _object->uri = psStringCopy(uri);
     14350    _object->b1_uri = psStringCopy(b1_uri);
     14351    _object->b2_uri = psStringCopy(b2_uri);
     14352
     14353    return _object;
     14354}
     14355
     14356static void p4PStackedImfileRowFree(p4PStackedImfileRow *object)
     14357{
     14358    psFree(object->class_id);
     14359    psFree(object->uri);
     14360    psFree(object->b1_uri);
     14361    psFree(object->b2_uri);
     14362}
     14363
     14364bool p4PStackedImfileCreateTable(psDB *dbh)
     14365{
     14366    psMetadata *md = psMetadataAlloc();
     14367    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, "Primary Key", 0)) {
     14368        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14369        psFree(md);
     14370        return false;
     14371    }
     14372    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     14373        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14374        psFree(md);
     14375        return false;
     14376    }
     14377    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     14378        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14379        psFree(md);
     14380        return false;
     14381    }
     14382    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, "255")) {
     14383        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14384        psFree(md);
     14385        return false;
     14386    }
     14387    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, "255")) {
     14388        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14389        psFree(md);
     14390        return false;
     14391    }
     14392
     14393    bool status = psDBCreateTable(dbh, P4PSTACKEDIMFILE_TABLE_NAME, md);
     14394
     14395    psFree(md);
     14396
     14397    return status;
     14398}
     14399
     14400bool p4PStackedImfileDropTable(psDB *dbh)
     14401{
     14402    return psDBDropTable(dbh, P4PSTACKEDIMFILE_TABLE_NAME);
     14403}
     14404
     14405bool p4PStackedImfileInsert(psDB * dbh, psS32 p4_id, const char *class_id, const char *uri, const char *b1_uri, const char *b2_uri)
     14406{
     14407    psMetadata *md = psMetadataAlloc();
     14408    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, p4_id)) {
     14409        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14410        psFree(md);
     14411        return false;
     14412    }
     14413    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     14414        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14415        psFree(md);
     14416        return false;
     14417    }
     14418    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     14419        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14420        psFree(md);
     14421        return false;
     14422    }
     14423    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, b1_uri)) {
     14424        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14425        psFree(md);
     14426        return false;
     14427    }
     14428    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, b2_uri)) {
     14429        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14430        psFree(md);
     14431        return false;
     14432    }
     14433
     14434    bool status = psDBInsertOneRow(dbh, P4PSTACKEDIMFILE_TABLE_NAME, md);
     14435    psFree(md);
     14436
     14437    return status;
     14438}
     14439
     14440long long p4PStackedImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     14441{
     14442    long long       deleted = 0;
     14443
     14444    long long count = psDBDeleteRows(dbh, P4PSTACKEDIMFILE_TABLE_NAME, where, limit);
     14445    if (count < 0) {
     14446        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PStackedImfile");
     14447        return count;
     14448
     14449        deleted += count;
     14450    }
     14451
     14452    return deleted;
     14453}
     14454bool p4PStackedImfileInsertObject(psDB *dbh, p4PStackedImfileRow *object)
     14455{
     14456    return p4PStackedImfileInsert(dbh, object->p4_id, object->class_id, object->uri, object->b1_uri, object->b2_uri);
     14457}
     14458
     14459bool p4PStackedImfileInsertObjects(psDB *dbh, psArray *objects)
     14460{
     14461    for (long i = 0; i < psArrayLength(objects); i++) {
     14462        if (!p4PStackedImfileInsertObject(dbh, objects->data[i])) {
     14463            return false;
     14464        }
     14465    }
     14466
     14467    return true;
     14468}
     14469
     14470bool p4PStackedImfileInsertFits(psDB *dbh, const psFits *fits)
     14471{
     14472    psArray         *rowSet;
     14473
     14474    // move to (the first?) extension named  P4PSTACKEDIMFILE_TABLE_NAME
     14475    if (!psFitsMoveExtName(fits, P4PSTACKEDIMFILE_TABLE_NAME)) {
     14476        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P4PSTACKEDIMFILE_TABLE_NAME);
     14477        return false;
     14478    }
     14479
     14480    // check HDU type
     14481    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     14482        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     14483        return false;
     14484    }
     14485
     14486    // read fits table
     14487    rowSet = psFitsReadTable(fits);
     14488    if (!rowSet) {
     14489        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     14490        psFree(rowSet);
     14491        return false;
     14492    }
     14493
     14494    if (!psDBInsertRows(dbh, P4PSTACKEDIMFILE_TABLE_NAME, rowSet)) {
     14495        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     14496        psFree(rowSet);
     14497        return false;
     14498    }
     14499
     14500    psFree(rowSet);
     14501
     14502    return true;
     14503}
     14504
     14505bool p4PStackedImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     14506{
     14507    psArray         *rowSet;
     14508
     14509    rowSet = psDBSelectRows(dbh, P4PSTACKEDIMFILE_TABLE_NAME, where, limit);
     14510    if (!rowSet) {
     14511        return false;
     14512    }
     14513
     14514    // output to fits
     14515    if (!psFitsWriteTable(fits, NULL, rowSet, P4PSTACKEDIMFILE_TABLE_NAME)) {
     14516        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     14517        psFree(rowSet);
     14518        return false;
     14519    }
     14520
     14521    psFree(rowSet);
     14522
     14523    return true;
     14524}
     14525
     14526psMetadata *p4PStackedImfileMetadataFromObject(const p4PStackedImfileRow *object)
     14527{
     14528    psMetadata *md = psMetadataAlloc();
     14529    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, object->p4_id)) {
     14530        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14531        psFree(md);
     14532        return false;
     14533    }
     14534    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     14535        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14536        psFree(md);
     14537        return false;
     14538    }
     14539    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     14540        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14541        psFree(md);
     14542        return false;
     14543    }
     14544    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, object->b1_uri)) {
     14545        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14546        psFree(md);
     14547        return false;
     14548    }
     14549    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, object->b2_uri)) {
     14550        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14551        psFree(md);
     14552        return false;
     14553    }
     14554
     14555
     14556    return md;
     14557}
     14558
     14559p4PStackedImfileRow *p4PStackedImfileObjectFromMetadata(psMetadata *md)
     14560{
     14561
     14562bool status = false;
     14563    psS32 p4_id = psMetadataLookupS32(&status, md, "p4_id");
     14564    if (!status) {
     14565        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p4_id");
     14566        return false;
     14567    }
     14568    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     14569    if (!status) {
     14570        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     14571        return false;
     14572    }
     14573    char* uri = psMetadataLookupPtr(&status, md, "uri");
     14574    if (!status) {
     14575        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     14576        return false;
     14577    }
     14578    char* b1_uri = psMetadataLookupPtr(&status, md, "b1_uri");
     14579    if (!status) {
     14580        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b1_uri");
     14581        return false;
     14582    }
     14583    char* b2_uri = psMetadataLookupPtr(&status, md, "b2_uri");
     14584    if (!status) {
     14585        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b2_uri");
     14586        return false;
     14587    }
     14588
     14589    return p4PStackedImfileRowAlloc(p4_id, class_id, uri, b1_uri, b2_uri);
     14590}
     14591psArray *p4PStackedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     14592{
     14593    psArray         *rowSet;
     14594    psArray         *returnSet;
     14595    psU64           i;
     14596
     14597    rowSet = psDBSelectRows(dbh, P4PSTACKEDIMFILE_TABLE_NAME, where, limit);
     14598    if (!rowSet) {
     14599        return NULL;
     14600    }
     14601
     14602    // convert psMetadata rows to row objects
     14603
     14604    returnSet = psArrayAllocEmpty(rowSet->n);
     14605
     14606    for (i = 0; i < rowSet->n; i++) {
     14607        p4PStackedImfileRow *object = p4PStackedImfileObjectFromMetadata(rowSet->data[i]);
     14608        psArrayAdd(returnSet, 0, object);
     14609        psFree(object);
     14610    }
     14611
     14612    psFree(rowSet);
     14613
     14614    return returnSet;
     14615}
     14616bool p4PStackedImfileDeleteObject(psDB *dbh, const p4PStackedImfileRow *object)
     14617{
     14618    psMetadata *where = p4PStackedImfileMetadataFromObject(object);
     14619    long long count = psDBDeleteRows(dbh, P4PSTACKEDIMFILE_TABLE_NAME, where, 0);
     14620    psFree(where)
     14621    if (count < 0) {
     14622        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PStackedImfile");
     14623        return false;
     14624    }
     14625    if (count > 1) {
     14626        // XXX should this be a psAbort() instead?  It is possible that
     14627        // having an object match multiple rows was by design.
     14628        psError(PS_ERR_UNKNOWN, true, "p4PStackedImfileRow object matched more then one row.  Check your database schema");
     14629        return false;
     14630    }
     14631
     14632    return true;
     14633}
     14634long long p4PStackedImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     14635{
     14636    long long       deleted = 0;
     14637
     14638    for (long long i = 0; i < objects->n; i++) {
     14639        p4PStackedImfileRow *object = objects->data[i];
     14640        psMetadata *where = p4PStackedImfileMetadataFromObject(object);
     14641        long long count = psDBDeleteRows(dbh, P4PSTACKEDIMFILE_TABLE_NAME, where, limit);
     14642        psFree(where)
     14643        if (count < 0) {
     14644            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PStackedImfile");
     14645            return count;
     14646        }
     14647
     14648        deleted += count;
     14649    }
     14650
     14651    return deleted;
     14652}
     14653bool p4PStackedImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     14654{
     14655    PS_ASSERT_PTR_NON_NULL(objects, false);
     14656
     14657    psMetadata *output = psMetadataAlloc();
     14658    for (long i = 0; i < psArrayLength(objects); i++) {
     14659        psMetadata *md = p4PStackedImfileMetadataFromObject(objects->data[i]);
     14660        if (!psMetadataAddMetadata(
     14661            output,
     14662            PS_LIST_TAIL,
     14663            P4PSTACKEDIMFILE_TABLE_NAME,
     14664            PS_META_DUPLICATE_OK,
     14665            NULL,
     14666            md
     14667        )) {
     14668            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     14669            psFree(md);
     14670            psFree(output);
     14671            return false;
     14672        }
     14673        psFree(md);
     14674    }
     14675
     14676    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     14677        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     14678        psFree(output);
     14679    }
     14680    psFree(output);
     14681
     14682    return true;
     14683}
     14684static void p4PDiffImfileRowFree(p4PDiffImfileRow *object);
     14685
     14686p4PDiffImfileRow *p4PDiffImfileRowAlloc(psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id, const char *uri, const char *b1_uri, const char *b2_uri)
     14687{
     14688    p4PDiffImfileRow *_object;
     14689
     14690    _object = psAlloc(sizeof(p4PDiffImfileRow));
     14691    psMemSetDeallocator(_object, (psFreeFunc)p4PDiffImfileRowFree);
     14692
     14693    _object->p4_id = p4_id;
     14694    _object->exp_tag = psStringCopy(exp_tag);
     14695    _object->p3_version = p3_version;
     14696    _object->class_id = psStringCopy(class_id);
     14697    _object->uri = psStringCopy(uri);
     14698    _object->b1_uri = psStringCopy(b1_uri);
     14699    _object->b2_uri = psStringCopy(b2_uri);
     14700
     14701    return _object;
     14702}
     14703
     14704static void p4PDiffImfileRowFree(p4PDiffImfileRow *object)
     14705{
     14706    psFree(object->exp_tag);
     14707    psFree(object->class_id);
     14708    psFree(object->uri);
     14709    psFree(object->b1_uri);
     14710    psFree(object->b2_uri);
     14711}
     14712
     14713bool p4PDiffImfileCreateTable(psDB *dbh)
     14714{
     14715    psMetadata *md = psMetadataAlloc();
     14716    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, "Primary Key", 0)) {
     14717        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14718        psFree(md);
     14719        return false;
     14720    }
     14721    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Primary Key", "64")) {
     14722        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     14723        psFree(md);
     14724        return false;
     14725    }
     14726    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, "Primary Key", 0)) {
     14727        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     14728        psFree(md);
     14729        return false;
     14730    }
     14731    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     14732        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14733        psFree(md);
     14734        return false;
     14735    }
     14736    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     14737        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14738        psFree(md);
     14739        return false;
     14740    }
     14741    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, "255")) {
     14742        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14743        psFree(md);
     14744        return false;
     14745    }
     14746    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, "255")) {
     14747        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14748        psFree(md);
     14749        return false;
     14750    }
     14751
     14752    bool status = psDBCreateTable(dbh, P4PDIFFIMFILE_TABLE_NAME, md);
     14753
     14754    psFree(md);
     14755
     14756    return status;
     14757}
     14758
     14759bool p4PDiffImfileDropTable(psDB *dbh)
     14760{
     14761    return psDBDropTable(dbh, P4PDIFFIMFILE_TABLE_NAME);
     14762}
     14763
     14764bool p4PDiffImfileInsert(psDB * dbh, psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id, const char *uri, const char *b1_uri, const char *b2_uri)
     14765{
     14766    psMetadata *md = psMetadataAlloc();
     14767    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, p4_id)) {
     14768        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14769        psFree(md);
     14770        return false;
     14771    }
     14772    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
     14773        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     14774        psFree(md);
     14775        return false;
     14776    }
     14777    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, p3_version)) {
     14778        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     14779        psFree(md);
     14780        return false;
     14781    }
     14782    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     14783        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14784        psFree(md);
     14785        return false;
     14786    }
     14787    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     14788        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14789        psFree(md);
     14790        return false;
     14791    }
     14792    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, b1_uri)) {
     14793        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14794        psFree(md);
     14795        return false;
     14796    }
     14797    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, b2_uri)) {
     14798        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14799        psFree(md);
     14800        return false;
     14801    }
     14802
     14803    bool status = psDBInsertOneRow(dbh, P4PDIFFIMFILE_TABLE_NAME, md);
     14804    psFree(md);
     14805
     14806    return status;
     14807}
     14808
     14809long long p4PDiffImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     14810{
     14811    long long       deleted = 0;
     14812
     14813    long long count = psDBDeleteRows(dbh, P4PDIFFIMFILE_TABLE_NAME, where, limit);
     14814    if (count < 0) {
     14815        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PDiffImfile");
     14816        return count;
     14817
     14818        deleted += count;
     14819    }
     14820
     14821    return deleted;
     14822}
     14823bool p4PDiffImfileInsertObject(psDB *dbh, p4PDiffImfileRow *object)
     14824{
     14825    return p4PDiffImfileInsert(dbh, object->p4_id, object->exp_tag, object->p3_version, object->class_id, object->uri, object->b1_uri, object->b2_uri);
     14826}
     14827
     14828bool p4PDiffImfileInsertObjects(psDB *dbh, psArray *objects)
     14829{
     14830    for (long i = 0; i < psArrayLength(objects); i++) {
     14831        if (!p4PDiffImfileInsertObject(dbh, objects->data[i])) {
     14832            return false;
     14833        }
     14834    }
     14835
     14836    return true;
     14837}
     14838
     14839bool p4PDiffImfileInsertFits(psDB *dbh, const psFits *fits)
     14840{
     14841    psArray         *rowSet;
     14842
     14843    // move to (the first?) extension named  P4PDIFFIMFILE_TABLE_NAME
     14844    if (!psFitsMoveExtName(fits, P4PDIFFIMFILE_TABLE_NAME)) {
     14845        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P4PDIFFIMFILE_TABLE_NAME);
     14846        return false;
     14847    }
     14848
     14849    // check HDU type
     14850    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     14851        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     14852        return false;
     14853    }
     14854
     14855    // read fits table
     14856    rowSet = psFitsReadTable(fits);
     14857    if (!rowSet) {
     14858        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     14859        psFree(rowSet);
     14860        return false;
     14861    }
     14862
     14863    if (!psDBInsertRows(dbh, P4PDIFFIMFILE_TABLE_NAME, rowSet)) {
     14864        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     14865        psFree(rowSet);
     14866        return false;
     14867    }
     14868
     14869    psFree(rowSet);
     14870
     14871    return true;
     14872}
     14873
     14874bool p4PDiffImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     14875{
     14876    psArray         *rowSet;
     14877
     14878    rowSet = psDBSelectRows(dbh, P4PDIFFIMFILE_TABLE_NAME, where, limit);
     14879    if (!rowSet) {
     14880        return false;
     14881    }
     14882
     14883    // output to fits
     14884    if (!psFitsWriteTable(fits, NULL, rowSet, P4PDIFFIMFILE_TABLE_NAME)) {
     14885        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     14886        psFree(rowSet);
     14887        return false;
     14888    }
     14889
     14890    psFree(rowSet);
     14891
     14892    return true;
     14893}
     14894
     14895psMetadata *p4PDiffImfileMetadataFromObject(const p4PDiffImfileRow *object)
     14896{
     14897    psMetadata *md = psMetadataAlloc();
     14898    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, object->p4_id)) {
     14899        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     14900        psFree(md);
     14901        return false;
     14902    }
     14903    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
     14904        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     14905        psFree(md);
     14906        return false;
     14907    }
     14908    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, object->p3_version)) {
     14909        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     14910        psFree(md);
     14911        return false;
     14912    }
     14913    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     14914        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     14915        psFree(md);
     14916        return false;
     14917    }
     14918    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     14919        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     14920        psFree(md);
     14921        return false;
     14922    }
     14923    if (!psMetadataAdd(md, PS_LIST_TAIL, "b1_uri", PS_DATA_STRING, NULL, object->b1_uri)) {
     14924        psError(PS_ERR_UNKNOWN, false, "failed to add item b1_uri");
     14925        psFree(md);
     14926        return false;
     14927    }
     14928    if (!psMetadataAdd(md, PS_LIST_TAIL, "b2_uri", PS_DATA_STRING, NULL, object->b2_uri)) {
     14929        psError(PS_ERR_UNKNOWN, false, "failed to add item b2_uri");
     14930        psFree(md);
     14931        return false;
     14932    }
     14933
     14934
     14935    return md;
     14936}
     14937
     14938p4PDiffImfileRow *p4PDiffImfileObjectFromMetadata(psMetadata *md)
     14939{
     14940
     14941bool status = false;
     14942    psS32 p4_id = psMetadataLookupS32(&status, md, "p4_id");
     14943    if (!status) {
     14944        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p4_id");
     14945        return false;
     14946    }
     14947    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
     14948    if (!status) {
     14949        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
     14950        return false;
     14951    }
     14952    psS32 p3_version = psMetadataLookupS32(&status, md, "p3_version");
     14953    if (!status) {
     14954        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p3_version");
     14955        return false;
     14956    }
     14957    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     14958    if (!status) {
     14959        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     14960        return false;
     14961    }
     14962    char* uri = psMetadataLookupPtr(&status, md, "uri");
     14963    if (!status) {
     14964        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     14965        return false;
     14966    }
     14967    char* b1_uri = psMetadataLookupPtr(&status, md, "b1_uri");
     14968    if (!status) {
     14969        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b1_uri");
     14970        return false;
     14971    }
     14972    char* b2_uri = psMetadataLookupPtr(&status, md, "b2_uri");
     14973    if (!status) {
     14974        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item b2_uri");
     14975        return false;
     14976    }
     14977
     14978    return p4PDiffImfileRowAlloc(p4_id, exp_tag, p3_version, class_id, uri, b1_uri, b2_uri);
     14979}
     14980psArray *p4PDiffImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     14981{
     14982    psArray         *rowSet;
     14983    psArray         *returnSet;
     14984    psU64           i;
     14985
     14986    rowSet = psDBSelectRows(dbh, P4PDIFFIMFILE_TABLE_NAME, where, limit);
     14987    if (!rowSet) {
     14988        return NULL;
     14989    }
     14990
     14991    // convert psMetadata rows to row objects
     14992
     14993    returnSet = psArrayAllocEmpty(rowSet->n);
     14994
     14995    for (i = 0; i < rowSet->n; i++) {
     14996        p4PDiffImfileRow *object = p4PDiffImfileObjectFromMetadata(rowSet->data[i]);
     14997        psArrayAdd(returnSet, 0, object);
     14998        psFree(object);
     14999    }
     15000
     15001    psFree(rowSet);
     15002
     15003    return returnSet;
     15004}
     15005bool p4PDiffImfileDeleteObject(psDB *dbh, const p4PDiffImfileRow *object)
     15006{
     15007    psMetadata *where = p4PDiffImfileMetadataFromObject(object);
     15008    long long count = psDBDeleteRows(dbh, P4PDIFFIMFILE_TABLE_NAME, where, 0);
     15009    psFree(where)
     15010    if (count < 0) {
     15011        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PDiffImfile");
     15012        return false;
     15013    }
     15014    if (count > 1) {
     15015        // XXX should this be a psAbort() instead?  It is possible that
     15016        // having an object match multiple rows was by design.
     15017        psError(PS_ERR_UNKNOWN, true, "p4PDiffImfileRow object matched more then one row.  Check your database schema");
     15018        return false;
     15019    }
     15020
     15021    return true;
     15022}
     15023long long p4PDiffImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     15024{
     15025    long long       deleted = 0;
     15026
     15027    for (long long i = 0; i < objects->n; i++) {
     15028        p4PDiffImfileRow *object = objects->data[i];
     15029        psMetadata *where = p4PDiffImfileMetadataFromObject(object);
     15030        long long count = psDBDeleteRows(dbh, P4PDIFFIMFILE_TABLE_NAME, where, limit);
     15031        psFree(where)
     15032        if (count < 0) {
     15033            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PDiffImfile");
     15034            return count;
     15035        }
     15036
     15037        deleted += count;
     15038    }
     15039
     15040    return deleted;
     15041}
     15042bool p4PDiffImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     15043{
     15044    PS_ASSERT_PTR_NON_NULL(objects, false);
     15045
     15046    psMetadata *output = psMetadataAlloc();
     15047    for (long i = 0; i < psArrayLength(objects); i++) {
     15048        psMetadata *md = p4PDiffImfileMetadataFromObject(objects->data[i]);
     15049        if (!psMetadataAddMetadata(
     15050            output,
     15051            PS_LIST_TAIL,
     15052            P4PDIFFIMFILE_TABLE_NAME,
     15053            PS_META_DUPLICATE_OK,
     15054            NULL,
     15055            md
     15056        )) {
     15057            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     15058            psFree(md);
     15059            psFree(output);
     15060            return false;
     15061        }
     15062        psFree(md);
     15063    }
     15064
     15065    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     15066        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     15067        psFree(output);
     15068    }
     15069    psFree(output);
     15070
     15071    return true;
     15072}
     15073static void p4PMagicMaskImfileRowFree(p4PMagicMaskImfileRow *object);
     15074
     15075p4PMagicMaskImfileRow *p4PMagicMaskImfileRowAlloc(psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id, const char *uri)
     15076{
     15077    p4PMagicMaskImfileRow *_object;
     15078
     15079    _object = psAlloc(sizeof(p4PMagicMaskImfileRow));
     15080    psMemSetDeallocator(_object, (psFreeFunc)p4PMagicMaskImfileRowFree);
     15081
     15082    _object->p4_id = p4_id;
     15083    _object->exp_tag = psStringCopy(exp_tag);
     15084    _object->p3_version = p3_version;
     15085    _object->class_id = psStringCopy(class_id);
     15086    _object->uri = psStringCopy(uri);
     15087
     15088    return _object;
     15089}
     15090
     15091static void p4PMagicMaskImfileRowFree(p4PMagicMaskImfileRow *object)
     15092{
     15093    psFree(object->exp_tag);
     15094    psFree(object->class_id);
     15095    psFree(object->uri);
     15096}
     15097
     15098bool p4PMagicMaskImfileCreateTable(psDB *dbh)
     15099{
     15100    psMetadata *md = psMetadataAlloc();
     15101    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, "Primary Key", 0)) {
     15102        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     15103        psFree(md);
     15104        return false;
     15105    }
     15106    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, "Primary Key", "64")) {
     15107        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     15108        psFree(md);
     15109        return false;
     15110    }
     15111    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, "Primary Key", 0)) {
     15112        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     15113        psFree(md);
     15114        return false;
     15115    }
     15116    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, "Primary Key", "64")) {
     15117        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     15118        psFree(md);
     15119        return false;
     15120    }
     15121    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, "255")) {
     15122        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     15123        psFree(md);
     15124        return false;
     15125    }
     15126
     15127    bool status = psDBCreateTable(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, md);
     15128
     15129    psFree(md);
     15130
     15131    return status;
     15132}
     15133
     15134bool p4PMagicMaskImfileDropTable(psDB *dbh)
     15135{
     15136    return psDBDropTable(dbh, P4PMAGICMASKIMFILE_TABLE_NAME);
     15137}
     15138
     15139bool p4PMagicMaskImfileInsert(psDB * dbh, psS32 p4_id, const char *exp_tag, psS32 p3_version, const char *class_id, const char *uri)
     15140{
     15141    psMetadata *md = psMetadataAlloc();
     15142    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, p4_id)) {
     15143        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     15144        psFree(md);
     15145        return false;
     15146    }
     15147    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, exp_tag)) {
     15148        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     15149        psFree(md);
     15150        return false;
     15151    }
     15152    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, p3_version)) {
     15153        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     15154        psFree(md);
     15155        return false;
     15156    }
     15157    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, class_id)) {
     15158        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     15159        psFree(md);
     15160        return false;
     15161    }
     15162    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, uri)) {
     15163        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     15164        psFree(md);
     15165        return false;
     15166    }
     15167
     15168    bool status = psDBInsertOneRow(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, md);
     15169    psFree(md);
     15170
     15171    return status;
     15172}
     15173
     15174long long p4PMagicMaskImfileDelete(psDB *dbh, const psMetadata *where, unsigned long long limit)
     15175{
     15176    long long       deleted = 0;
     15177
     15178    long long count = psDBDeleteRows(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, where, limit);
     15179    if (count < 0) {
     15180        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PMagicMaskImfile");
     15181        return count;
     15182
     15183        deleted += count;
     15184    }
     15185
     15186    return deleted;
     15187}
     15188bool p4PMagicMaskImfileInsertObject(psDB *dbh, p4PMagicMaskImfileRow *object)
     15189{
     15190    return p4PMagicMaskImfileInsert(dbh, object->p4_id, object->exp_tag, object->p3_version, object->class_id, object->uri);
     15191}
     15192
     15193bool p4PMagicMaskImfileInsertObjects(psDB *dbh, psArray *objects)
     15194{
     15195    for (long i = 0; i < psArrayLength(objects); i++) {
     15196        if (!p4PMagicMaskImfileInsertObject(dbh, objects->data[i])) {
     15197            return false;
     15198        }
     15199    }
     15200
     15201    return true;
     15202}
     15203
     15204bool p4PMagicMaskImfileInsertFits(psDB *dbh, const psFits *fits)
     15205{
     15206    psArray         *rowSet;
     15207
     15208    // move to (the first?) extension named  P4PMAGICMASKIMFILE_TABLE_NAME
     15209    if (!psFitsMoveExtName(fits, P4PMAGICMASKIMFILE_TABLE_NAME)) {
     15210        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P4PMAGICMASKIMFILE_TABLE_NAME);
     15211        return false;
     15212    }
     15213
     15214    // check HDU type
     15215    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
     15216        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
     15217        return false;
     15218    }
     15219
     15220    // read fits table
     15221    rowSet = psFitsReadTable(fits);
     15222    if (!rowSet) {
     15223        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
     15224        psFree(rowSet);
     15225        return false;
     15226    }
     15227
     15228    if (!psDBInsertRows(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, rowSet)) {
     15229        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
     15230        psFree(rowSet);
     15231        return false;
     15232    }
     15233
     15234    psFree(rowSet);
     15235
     15236    return true;
     15237}
     15238
     15239bool p4PMagicMaskImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
     15240{
     15241    psArray         *rowSet;
     15242
     15243    rowSet = psDBSelectRows(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, where, limit);
     15244    if (!rowSet) {
     15245        return false;
     15246    }
     15247
     15248    // output to fits
     15249    if (!psFitsWriteTable(fits, NULL, rowSet, P4PMAGICMASKIMFILE_TABLE_NAME)) {
     15250        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
     15251        psFree(rowSet);
     15252        return false;
     15253    }
     15254
     15255    psFree(rowSet);
     15256
     15257    return true;
     15258}
     15259
     15260psMetadata *p4PMagicMaskImfileMetadataFromObject(const p4PMagicMaskImfileRow *object)
     15261{
     15262    psMetadata *md = psMetadataAlloc();
     15263    if (!psMetadataAdd(md, PS_LIST_TAIL, "p4_id", PS_DATA_S32, NULL, object->p4_id)) {
     15264        psError(PS_ERR_UNKNOWN, false, "failed to add item p4_id");
     15265        psFree(md);
     15266        return false;
     15267    }
     15268    if (!psMetadataAdd(md, PS_LIST_TAIL, "exp_tag", PS_DATA_STRING, NULL, object->exp_tag)) {
     15269        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_tag");
     15270        psFree(md);
     15271        return false;
     15272    }
     15273    if (!psMetadataAdd(md, PS_LIST_TAIL, "p3_version", PS_DATA_S32, NULL, object->p3_version)) {
     15274        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
     15275        psFree(md);
     15276        return false;
     15277    }
     15278    if (!psMetadataAdd(md, PS_LIST_TAIL, "class_id", PS_DATA_STRING, NULL, object->class_id)) {
     15279        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
     15280        psFree(md);
     15281        return false;
     15282    }
     15283    if (!psMetadataAdd(md, PS_LIST_TAIL, "uri", PS_DATA_STRING, NULL, object->uri)) {
     15284        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
     15285        psFree(md);
     15286        return false;
     15287    }
     15288
     15289
     15290    return md;
     15291}
     15292
     15293p4PMagicMaskImfileRow *p4PMagicMaskImfileObjectFromMetadata(psMetadata *md)
     15294{
     15295
     15296bool status = false;
     15297    psS32 p4_id = psMetadataLookupS32(&status, md, "p4_id");
     15298    if (!status) {
     15299        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p4_id");
     15300        return false;
     15301    }
     15302    char* exp_tag = psMetadataLookupPtr(&status, md, "exp_tag");
     15303    if (!status) {
     15304        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_tag");
     15305        return false;
     15306    }
     15307    psS32 p3_version = psMetadataLookupS32(&status, md, "p3_version");
     15308    if (!status) {
     15309        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p3_version");
     15310        return false;
     15311    }
     15312    char* class_id = psMetadataLookupPtr(&status, md, "class_id");
     15313    if (!status) {
     15314        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
     15315        return false;
     15316    }
     15317    char* uri = psMetadataLookupPtr(&status, md, "uri");
     15318    if (!status) {
     15319        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
     15320        return false;
     15321    }
     15322
     15323    return p4PMagicMaskImfileRowAlloc(p4_id, exp_tag, p3_version, class_id, uri);
     15324}
     15325psArray *p4PMagicMaskImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
     15326{
     15327    psArray         *rowSet;
     15328    psArray         *returnSet;
     15329    psU64           i;
     15330
     15331    rowSet = psDBSelectRows(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, where, limit);
     15332    if (!rowSet) {
     15333        return NULL;
     15334    }
     15335
     15336    // convert psMetadata rows to row objects
     15337
     15338    returnSet = psArrayAllocEmpty(rowSet->n);
     15339
     15340    for (i = 0; i < rowSet->n; i++) {
     15341        p4PMagicMaskImfileRow *object = p4PMagicMaskImfileObjectFromMetadata(rowSet->data[i]);
     15342        psArrayAdd(returnSet, 0, object);
     15343        psFree(object);
     15344    }
     15345
     15346    psFree(rowSet);
     15347
     15348    return returnSet;
     15349}
     15350bool p4PMagicMaskImfileDeleteObject(psDB *dbh, const p4PMagicMaskImfileRow *object)
     15351{
     15352    psMetadata *where = p4PMagicMaskImfileMetadataFromObject(object);
     15353    long long count = psDBDeleteRows(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, where, 0);
     15354    psFree(where)
     15355    if (count < 0) {
     15356        psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PMagicMaskImfile");
     15357        return false;
     15358    }
     15359    if (count > 1) {
     15360        // XXX should this be a psAbort() instead?  It is possible that
     15361        // having an object match multiple rows was by design.
     15362        psError(PS_ERR_UNKNOWN, true, "p4PMagicMaskImfileRow object matched more then one row.  Check your database schema");
     15363        return false;
     15364    }
     15365
     15366    return true;
     15367}
     15368long long p4PMagicMaskImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
     15369{
     15370    long long       deleted = 0;
     15371
     15372    for (long long i = 0; i < objects->n; i++) {
     15373        p4PMagicMaskImfileRow *object = objects->data[i];
     15374        psMetadata *where = p4PMagicMaskImfileMetadataFromObject(object);
     15375        long long count = psDBDeleteRows(dbh, P4PMAGICMASKIMFILE_TABLE_NAME, where, limit);
     15376        psFree(where)
     15377        if (count < 0) {
     15378            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p4PMagicMaskImfile");
     15379            return count;
     15380        }
     15381
     15382        deleted += count;
     15383    }
     15384
     15385    return deleted;
     15386}
     15387bool p4PMagicMaskImfilePrintObjects(FILE *stream, psArray *objects, bool mdcf)
     15388{
     15389    PS_ASSERT_PTR_NON_NULL(objects, false);
     15390
     15391    psMetadata *output = psMetadataAlloc();
     15392    for (long i = 0; i < psArrayLength(objects); i++) {
     15393        psMetadata *md = p4PMagicMaskImfileMetadataFromObject(objects->data[i]);
     15394        if (!psMetadataAddMetadata(
     15395            output,
     15396            PS_LIST_TAIL,
     15397            P4PMAGICMASKIMFILE_TABLE_NAME,
     15398            PS_META_DUPLICATE_OK,
     15399            NULL,
     15400            md
     15401        )) {
     15402            psError(PS_ERR_UNKNOWN, false, "failed to add metadata");
     15403            psFree(md);
     15404            psFree(output);
     15405            return false;
     15406        }
     15407        psFree(md);
     15408    }
     15409
     15410    if (!ippdbPrintMetadataRaw(stream, output, mdcf)) {
     15411        psError(PS_ERR_UNKNOWN, false, "failed to print metadata");
     15412        psFree(output);
     15413    }
     15414    psFree(output);
     15415
     15416    return true;
     15417}
Note: See TracChangeset for help on using the changeset viewer.