#ifndef IPPDB_H
#define IPPDB_H 1

#include <pslib.h>

#ifdef __cplusplus
extern "C" {
#endif

/// @addtogroup ippdb
/// @{

/** Opens a new database connection
 *
 *  @return A new psDB object if the database connection is successful or NULL
 *  on failure.
 */

psDB *ippdbInit(
    const char      *host,              ///< Database server hostname
    const char      *user,              ///< Database username
    const char      *passwd,            ///< Database password
    const char      *dbname             ///< Database table.namespace
);

/** Closes a database connection
 */

void ippdbCleanup(
    psDB            *dbh                ///< Database handle
);

/** weatherRow data structure
 *
 * Structure for representing a single row of weather table data.
 */

typedef struct {
    psF32           temp01;
    psF32           humi01;
    psF32           temp02;
    psF32           humi02;
    psF32           temp03;
    psF32           humi03;
    psF32           pressure;
} weatherRow;

/** Creates a new weatherRow object
 *
 *  @return A new weatherRow object or NULL on failure.
 */

weatherRow *weatherRowAlloc(
    psF32           temp01,
    psF32           humi01,
    psF32           temp02,
    psF32           humi02,
    psF32           temp03,
    psF32           humi03,
    psF32           pressure
);

/** Creates a new weather table
 *
 * @return true on success
 */

bool weatherCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a weather table
 *
 * @return true on success
 */

bool weatherDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool weatherInsert(
    psDB            *dbh,               ///< Database handle
    psF32           temp01,
    psF32           humi01,
    psF32           temp02,
    psF32           humi02,
    psF32           temp03,
    psF32           humi03,
    psF32           pressure
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool weatherPop(
    psDB            *dbh,               ///< Database handle
    psF32           *temp01,
    psF32           *humi01,
    psF32           *temp02,
    psF32           *humi02,
    psF32           *temp03,
    psF32           *humi03,
    psF32           *pressure
);

/** Insert a single weatherRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool weatherInsertObject(
    psDB            *dbh,               ///< Database handle
    weatherRow      *object             ///< weatherRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new weatherRow on success or NULL on failure.
 */

weatherRow *weatherPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table weatherRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool weatherInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool weatherPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool weatherSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a weatherRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *weatherMetadataFromObject(
    const weatherRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A weatherRow pointer or NULL on error
 */

weatherRow *weatherObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as weatherRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *weatherSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long weatherDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** skyp_transparencyRow data structure
 *
 * Structure for representing a single row of skyp_transparency table data.
 */

typedef struct {
    char            *filter;
    psF64           trans;
    psS32           nstars;
    psF64           ra;
    psF64           decl;
    psF32           exptime;
    psF64           sky_bright;
} skyp_transparencyRow;

/** Creates a new skyp_transparencyRow object
 *
 *  @return A new skyp_transparencyRow object or NULL on failure.
 */

skyp_transparencyRow *skyp_transparencyRowAlloc(
    const char      *filter,
    psF64           trans,
    psS32           nstars,
    psF64           ra,
    psF64           decl,
    psF32           exptime,
    psF64           sky_bright
);

/** Creates a new skyp_transparency table
 *
 * @return true on success
 */

bool skyp_transparencyCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a skyp_transparency table
 *
 * @return true on success
 */

bool skyp_transparencyDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_transparencyInsert(
    psDB            *dbh,               ///< Database handle
    const char      *filter,
    psF64           trans,
    psS32           nstars,
    psF64           ra,
    psF64           decl,
    psF32           exptime,
    psF64           sky_bright
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool skyp_transparencyPop(
    psDB            *dbh,               ///< Database handle
    char            **filter,
    psF64           *trans,
    psS32           *nstars,
    psF64           *ra,
    psF64           *decl,
    psF32           *exptime,
    psF64           *sky_bright
);

/** Insert a single skyp_transparencyRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_transparencyInsertObject(
    psDB            *dbh,               ///< Database handle
    skyp_transparencyRow *object             ///< skyp_transparencyRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new skyp_transparencyRow on success or NULL on failure.
 */

skyp_transparencyRow *skyp_transparencyPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table skyp_transparencyRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool skyp_transparencyInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool skyp_transparencyPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool skyp_transparencySelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a skyp_transparencyRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *skyp_transparencyMetadataFromObject(
    const skyp_transparencyRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A skyp_transparencyRow pointer or NULL on error
 */

skyp_transparencyRow *skyp_transparencyObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as skyp_transparencyRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *skyp_transparencySelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long skyp_transparencyDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** skyp_absorptionRow data structure
 *
 * Structure for representing a single row of skyp_absorption table data.
 */

typedef struct {
    char            *disperser_id;
    psF32           atmcomp1;
    psF32           atmcomp2;
    psF32           atmcomp3;
    psS32           nstars;
    psF64           ra;
    psF64           decl;
    psF32           exptime;
    psF64           sky_bright;
} skyp_absorptionRow;

/** Creates a new skyp_absorptionRow object
 *
 *  @return A new skyp_absorptionRow object or NULL on failure.
 */

skyp_absorptionRow *skyp_absorptionRowAlloc(
    const char      *disperser_id,
    psF32           atmcomp1,
    psF32           atmcomp2,
    psF32           atmcomp3,
    psS32           nstars,
    psF64           ra,
    psF64           decl,
    psF32           exptime,
    psF64           sky_bright
);

/** Creates a new skyp_absorption table
 *
 * @return true on success
 */

bool skyp_absorptionCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a skyp_absorption table
 *
 * @return true on success
 */

bool skyp_absorptionDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_absorptionInsert(
    psDB            *dbh,               ///< Database handle
    const char      *disperser_id,
    psF32           atmcomp1,
    psF32           atmcomp2,
    psF32           atmcomp3,
    psS32           nstars,
    psF64           ra,
    psF64           decl,
    psF32           exptime,
    psF64           sky_bright
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool skyp_absorptionPop(
    psDB            *dbh,               ///< Database handle
    char            **disperser_id,
    psF32           *atmcomp1,
    psF32           *atmcomp2,
    psF32           *atmcomp3,
    psS32           *nstars,
    psF64           *ra,
    psF64           *decl,
    psF32           *exptime,
    psF64           *sky_bright
);

/** Insert a single skyp_absorptionRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_absorptionInsertObject(
    psDB            *dbh,               ///< Database handle
    skyp_absorptionRow *object             ///< skyp_absorptionRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new skyp_absorptionRow on success or NULL on failure.
 */

skyp_absorptionRow *skyp_absorptionPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table skyp_absorptionRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool skyp_absorptionInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool skyp_absorptionPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool skyp_absorptionSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a skyp_absorptionRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *skyp_absorptionMetadataFromObject(
    const skyp_absorptionRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A skyp_absorptionRow pointer or NULL on error
 */

skyp_absorptionRow *skyp_absorptionObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as skyp_absorptionRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *skyp_absorptionSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long skyp_absorptionDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** skyp_emissionRow data structure
 *
 * Structure for representing a single row of skyp_emission table data.
 */

typedef struct {
    char            *disperser_id;
    psF32           atmcomp1;
    psF32           atmcomp2;
    psF32           atmcomp3;
    psF32           continuum;
    psF32           exptime;
} skyp_emissionRow;

/** Creates a new skyp_emissionRow object
 *
 *  @return A new skyp_emissionRow object or NULL on failure.
 */

skyp_emissionRow *skyp_emissionRowAlloc(
    const char      *disperser_id,
    psF32           atmcomp1,
    psF32           atmcomp2,
    psF32           atmcomp3,
    psF32           continuum,
    psF32           exptime
);

/** Creates a new skyp_emission table
 *
 * @return true on success
 */

bool skyp_emissionCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a skyp_emission table
 *
 * @return true on success
 */

bool skyp_emissionDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_emissionInsert(
    psDB            *dbh,               ///< Database handle
    const char      *disperser_id,
    psF32           atmcomp1,
    psF32           atmcomp2,
    psF32           atmcomp3,
    psF32           continuum,
    psF32           exptime
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool skyp_emissionPop(
    psDB            *dbh,               ///< Database handle
    char            **disperser_id,
    psF32           *atmcomp1,
    psF32           *atmcomp2,
    psF32           *atmcomp3,
    psF32           *continuum,
    psF32           *exptime
);

/** Insert a single skyp_emissionRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_emissionInsertObject(
    psDB            *dbh,               ///< Database handle
    skyp_emissionRow *object             ///< skyp_emissionRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new skyp_emissionRow on success or NULL on failure.
 */

skyp_emissionRow *skyp_emissionPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table skyp_emissionRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool skyp_emissionInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool skyp_emissionPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool skyp_emissionSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a skyp_emissionRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *skyp_emissionMetadataFromObject(
    const skyp_emissionRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A skyp_emissionRow pointer or NULL on error
 */

skyp_emissionRow *skyp_emissionObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as skyp_emissionRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *skyp_emissionSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long skyp_emissionDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** dimmRow data structure
 *
 * Structure for representing a single row of dimm table data.
 */

typedef struct {
    psF32           sigmax;
    psF32           sigmay;
    psF32           fwhm;
    psF64           ra;
    psF64           decl;
    psF32           expttime;
    char            *telescope_id;
} dimmRow;

/** Creates a new dimmRow object
 *
 *  @return A new dimmRow object or NULL on failure.
 */

dimmRow *dimmRowAlloc(
    psF32           sigmax,
    psF32           sigmay,
    psF32           fwhm,
    psF64           ra,
    psF64           decl,
    psF32           expttime,
    const char      *telescope_id
);

/** Creates a new dimm table
 *
 * @return true on success
 */

bool dimmCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a dimm table
 *
 * @return true on success
 */

bool dimmDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool dimmInsert(
    psDB            *dbh,               ///< Database handle
    psF32           sigmax,
    psF32           sigmay,
    psF32           fwhm,
    psF64           ra,
    psF64           decl,
    psF32           expttime,
    const char      *telescope_id
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool dimmPop(
    psDB            *dbh,               ///< Database handle
    psF32           *sigmax,
    psF32           *sigmay,
    psF32           *fwhm,
    psF64           *ra,
    psF64           *decl,
    psF32           *expttime,
    char            **telescope_id
);

/** Insert a single dimmRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool dimmInsertObject(
    psDB            *dbh,               ///< Database handle
    dimmRow         *object             ///< dimmRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new dimmRow on success or NULL on failure.
 */

dimmRow *dimmPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table dimmRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool dimmInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool dimmPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool dimmSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a dimmRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *dimmMetadataFromObject(
    const dimmRow   *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A dimmRow pointer or NULL on error
 */

dimmRow *dimmObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as dimmRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *dimmSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long dimmDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** skyp_irRow data structure
 *
 * Structure for representing a single row of skyp_ir table data.
 */

typedef struct {
    psF64           sky_bright;
    psF64           sky_var;
    psF64           ra;
    psF64           decl;
    psF32           fov_x;
    psF32           fov_y;
} skyp_irRow;

/** Creates a new skyp_irRow object
 *
 *  @return A new skyp_irRow object or NULL on failure.
 */

skyp_irRow *skyp_irRowAlloc(
    psF64           sky_bright,
    psF64           sky_var,
    psF64           ra,
    psF64           decl,
    psF32           fov_x,
    psF32           fov_y
);

/** Creates a new skyp_ir table
 *
 * @return true on success
 */

bool skyp_irCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a skyp_ir table
 *
 * @return true on success
 */

bool skyp_irDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_irInsert(
    psDB            *dbh,               ///< Database handle
    psF64           sky_bright,
    psF64           sky_var,
    psF64           ra,
    psF64           decl,
    psF32           fov_x,
    psF32           fov_y
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool skyp_irPop(
    psDB            *dbh,               ///< Database handle
    psF64           *sky_bright,
    psF64           *sky_var,
    psF64           *ra,
    psF64           *decl,
    psF32           *fov_x,
    psF32           *fov_y
);

/** Insert a single skyp_irRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool skyp_irInsertObject(
    psDB            *dbh,               ///< Database handle
    skyp_irRow      *object             ///< skyp_irRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new skyp_irRow on success or NULL on failure.
 */

skyp_irRow *skyp_irPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table skyp_irRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool skyp_irInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool skyp_irPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool skyp_irSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a skyp_irRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *skyp_irMetadataFromObject(
    const skyp_irRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A skyp_irRow pointer or NULL on error
 */

skyp_irRow *skyp_irObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as skyp_irRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *skyp_irSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long skyp_irDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** domeRow data structure
 *
 * Structure for representing a single row of dome table data.
 */

typedef struct {
    psF32           az;
    bool            open;
    bool            light;
    bool            track;
} domeRow;

/** Creates a new domeRow object
 *
 *  @return A new domeRow object or NULL on failure.
 */

domeRow *domeRowAlloc(
    psF32           az,
    bool            open,
    bool            light,
    bool            track
);

/** Creates a new dome table
 *
 * @return true on success
 */

bool domeCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a dome table
 *
 * @return true on success
 */

bool domeDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool domeInsert(
    psDB            *dbh,               ///< Database handle
    psF32           az,
    bool            open,
    bool            light,
    bool            track
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool domePop(
    psDB            *dbh,               ///< Database handle
    psF32           *az,
    bool            *open,
    bool            *light,
    bool            *track
);

/** Insert a single domeRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool domeInsertObject(
    psDB            *dbh,               ///< Database handle
    domeRow         *object             ///< domeRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new domeRow on success or NULL on failure.
 */

domeRow *domePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table domeRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool domeInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool domePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool domeSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a domeRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *domeMetadataFromObject(
    const domeRow   *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A domeRow pointer or NULL on error
 */

domeRow *domeObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as domeRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *domeSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long domeDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** telescopeRow data structure
 *
 * Structure for representing a single row of telescope table data.
 */

typedef struct {
    char            *guide;
    psF32           alt;
    psF32           az;
    psF64           ra;
    psF64           decl;
} telescopeRow;

/** Creates a new telescopeRow object
 *
 *  @return A new telescopeRow object or NULL on failure.
 */

telescopeRow *telescopeRowAlloc(
    const char      *guide,
    psF32           alt,
    psF32           az,
    psF64           ra,
    psF64           decl
);

/** Creates a new telescope table
 *
 * @return true on success
 */

bool telescopeCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a telescope table
 *
 * @return true on success
 */

bool telescopeDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool telescopeInsert(
    psDB            *dbh,               ///< Database handle
    const char      *guide,
    psF32           alt,
    psF32           az,
    psF64           ra,
    psF64           decl
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool telescopePop(
    psDB            *dbh,               ///< Database handle
    char            **guide,
    psF32           *alt,
    psF32           *az,
    psF64           *ra,
    psF64           *decl
);

/** Insert a single telescopeRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool telescopeInsertObject(
    psDB            *dbh,               ///< Database handle
    telescopeRow    *object             ///< telescopeRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new telescopeRow on success or NULL on failure.
 */

telescopeRow *telescopePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table telescopeRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool telescopeInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool telescopePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool telescopeSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a telescopeRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *telescopeMetadataFromObject(
    const telescopeRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A telescopeRow pointer or NULL on error
 */

telescopeRow *telescopeObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as telescopeRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *telescopeSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long telescopeDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** summitExpRow data structure
 *
 * Structure for representing a single row of summitExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    char            *uri;
} summitExpRow;

/** Creates a new summitExpRow object
 *
 *  @return A new summitExpRow object or NULL on failure.
 */

summitExpRow *summitExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    const char      *uri
);

/** Creates a new summitExp table
 *
 * @return true on success
 */

bool summitExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a summitExp table
 *
 * @return true on success
 */

bool summitExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool summitExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    const char      *uri
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool summitExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    char            **uri
);

/** Insert a single summitExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool summitExpInsertObject(
    psDB            *dbh,               ///< Database handle
    summitExpRow    *object             ///< summitExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new summitExpRow on success or NULL on failure.
 */

summitExpRow *summitExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table summitExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool summitExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool summitExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool summitExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a summitExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *summitExpMetadataFromObject(
    const summitExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A summitExpRow pointer or NULL on error
 */

summitExpRow *summitExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as summitExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *summitExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long summitExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** pzPendingExpRow data structure
 *
 * Structure for representing a single row of pzPendingExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
} pzPendingExpRow;

/** Creates a new pzPendingExpRow object
 *
 *  @return A new pzPendingExpRow object or NULL on failure.
 */

pzPendingExpRow *pzPendingExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles
);

/** Creates a new pzPendingExp table
 *
 * @return true on success
 */

bool pzPendingExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pzPendingExp table
 *
 * @return true on success
 */

bool pzPendingExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzPendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool pzPendingExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles
);

/** Insert a single pzPendingExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzPendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    pzPendingExpRow *object             ///< pzPendingExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new pzPendingExpRow on success or NULL on failure.
 */

pzPendingExpRow *pzPendingExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table pzPendingExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pzPendingExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool pzPendingExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pzPendingExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pzPendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzPendingExpMetadataFromObject(
    const pzPendingExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pzPendingExpRow pointer or NULL on error
 */

pzPendingExpRow *pzPendingExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pzPendingExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pzPendingExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzPendingExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** pzPendingImfileRow data structure
 *
 * Structure for representing a single row of pzPendingImfile table data.
 */

typedef struct {
    char            *exp_id;
    psS32           bytes;
    char            *md5sum;
    char            *class;
    char            *class_id;
    char            *uri;
} pzPendingImfileRow;

/** Creates a new pzPendingImfileRow object
 *
 *  @return A new pzPendingImfileRow object or NULL on failure.
 */

pzPendingImfileRow *pzPendingImfileRowAlloc(
    const char      *exp_id,
    psS32           bytes,
    const char      *md5sum,
    const char      *class,
    const char      *class_id,
    const char      *uri
);

/** Creates a new pzPendingImfile table
 *
 * @return true on success
 */

bool pzPendingImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a pzPendingImfile table
 *
 * @return true on success
 */

bool pzPendingImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzPendingImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    psS32           bytes,
    const char      *md5sum,
    const char      *class,
    const char      *class_id,
    const char      *uri
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool pzPendingImfilePop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    psS32           *bytes,
    char            **md5sum,
    char            **class,
    char            **class_id,
    char            **uri
);

/** Insert a single pzPendingImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool pzPendingImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    pzPendingImfileRow *object             ///< pzPendingImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new pzPendingImfileRow on success or NULL on failure.
 */

pzPendingImfileRow *pzPendingImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table pzPendingImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool pzPendingImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool pzPendingImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool pzPendingImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a pzPendingImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *pzPendingImfileMetadataFromObject(
    const pzPendingImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A pzPendingImfileRow pointer or NULL on error
 */

pzPendingImfileRow *pzPendingImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as pzPendingImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *pzPendingImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long pzPendingImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** newExpRow data structure
 *
 * Structure for representing a single row of newExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
} newExpRow;

/** Creates a new newExpRow object
 *
 *  @return A new newExpRow object or NULL on failure.
 */

newExpRow *newExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles
);

/** Creates a new newExp table
 *
 * @return true on success
 */

bool newExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a newExp table
 *
 * @return true on success
 */

bool newExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool newExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles
);

/** Insert a single newExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newExpInsertObject(
    psDB            *dbh,               ///< Database handle
    newExpRow       *object             ///< newExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new newExpRow on success or NULL on failure.
 */

newExpRow *newExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table newExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool newExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool newExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool newExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a newExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *newExpMetadataFromObject(
    const newExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A newExpRow pointer or NULL on error
 */

newExpRow *newExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as newExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *newExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long newExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** newImfileRow data structure
 *
 * Structure for representing a single row of newImfile table data.
 */

typedef struct {
    char            *exp_id;
    char            *class;
    char            *class_id;
    char            *uri;
} newImfileRow;

/** Creates a new newImfileRow object
 *
 *  @return A new newImfileRow object or NULL on failure.
 */

newImfileRow *newImfileRowAlloc(
    const char      *exp_id,
    const char      *class,
    const char      *class_id,
    const char      *uri
);

/** Creates a new newImfile table
 *
 * @return true on success
 */

bool newImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a newImfile table
 *
 * @return true on success
 */

bool newImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *class,
    const char      *class_id,
    const char      *uri
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool newImfilePop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **class,
    char            **class_id,
    char            **uri
);

/** Insert a single newImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool newImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    newImfileRow    *object             ///< newImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new newImfileRow on success or NULL on failure.
 */

newImfileRow *newImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table newImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool newImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool newImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool newImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a newImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *newImfileMetadataFromObject(
    const newImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A newImfileRow pointer or NULL on error
 */

newImfileRow *newImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as newImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *newImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long newImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** rawDetrendExpRow data structure
 *
 * Structure for representing a single row of rawDetrendExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
} rawDetrendExpRow;

/** Creates a new rawDetrendExpRow object
 *
 *  @return A new rawDetrendExpRow object or NULL on failure.
 */

rawDetrendExpRow *rawDetrendExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats
);

/** Creates a new rawDetrendExp table
 *
 * @return true on success
 */

bool rawDetrendExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a rawDetrendExp table
 *
 * @return true on success
 */

bool rawDetrendExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawDetrendExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool rawDetrendExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats
);

/** Insert a single rawDetrendExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawDetrendExpInsertObject(
    psDB            *dbh,               ///< Database handle
    rawDetrendExpRow *object             ///< rawDetrendExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new rawDetrendExpRow on success or NULL on failure.
 */

rawDetrendExpRow *rawDetrendExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table rawDetrendExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool rawDetrendExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool rawDetrendExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool rawDetrendExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a rawDetrendExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *rawDetrendExpMetadataFromObject(
    const rawDetrendExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A rawDetrendExpRow pointer or NULL on error
 */

rawDetrendExpRow *rawDetrendExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as rawDetrendExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *rawDetrendExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawDetrendExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** rawScienceExpRow data structure
 *
 * Structure for representing a single row of rawScienceExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
} rawScienceExpRow;

/** Creates a new rawScienceExpRow object
 *
 *  @return A new rawScienceExpRow object or NULL on failure.
 */

rawScienceExpRow *rawScienceExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats
);

/** Creates a new rawScienceExp table
 *
 * @return true on success
 */

bool rawScienceExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a rawScienceExp table
 *
 * @return true on success
 */

bool rawScienceExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawScienceExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool rawScienceExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats
);

/** Insert a single rawScienceExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawScienceExpInsertObject(
    psDB            *dbh,               ///< Database handle
    rawScienceExpRow *object             ///< rawScienceExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new rawScienceExpRow on success or NULL on failure.
 */

rawScienceExpRow *rawScienceExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table rawScienceExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool rawScienceExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool rawScienceExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool rawScienceExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a rawScienceExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *rawScienceExpMetadataFromObject(
    const rawScienceExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A rawScienceExpRow pointer or NULL on error
 */

rawScienceExpRow *rawScienceExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as rawScienceExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *rawScienceExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawScienceExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** rawImfileRow data structure
 *
 * Structure for representing a single row of rawImfile table data.
 */

typedef struct {
    char            *exp_id;
    char            *class_id;
    char            *uri;
    char            *stats;
} rawImfileRow;

/** Creates a new rawImfileRow object
 *
 *  @return A new rawImfileRow object or NULL on failure.
 */

rawImfileRow *rawImfileRowAlloc(
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats
);

/** Creates a new rawImfile table
 *
 * @return true on success
 */

bool rawImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a rawImfile table
 *
 * @return true on success
 */

bool rawImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool rawImfilePop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **class_id,
    char            **uri,
    char            **stats
);

/** Insert a single rawImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool rawImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    rawImfileRow    *object             ///< rawImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new rawImfileRow on success or NULL on failure.
 */

rawImfileRow *rawImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table rawImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool rawImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool rawImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool rawImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a rawImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *rawImfileMetadataFromObject(
    const rawImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A rawImfileRow pointer or NULL on error
 */

rawImfileRow *rawImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as rawImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *rawImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long rawImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** p1PendingExpRow data structure
 *
 * Structure for representing a single row of p1PendingExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
    char            *recipe;
    psS32           p1_version;
} p1PendingExpRow;

/** Creates a new p1PendingExpRow object
 *
 *  @return A new p1PendingExpRow object or NULL on failure.
 */

p1PendingExpRow *p1PendingExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version
);

/** Creates a new p1PendingExp table
 *
 * @return true on success
 */

bool p1PendingExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a p1PendingExp table
 *
 * @return true on success
 */

bool p1PendingExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p1PendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool p1PendingExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats,
    char            **recipe,
    psS32           *p1_version
);

/** Insert a single p1PendingExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p1PendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p1PendingExpRow *object             ///< p1PendingExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new p1PendingExpRow on success or NULL on failure.
 */

p1PendingExpRow *p1PendingExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table p1PendingExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool p1PendingExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool p1PendingExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool p1PendingExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a p1PendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p1PendingExpMetadataFromObject(
    const p1PendingExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A p1PendingExpRow pointer or NULL on error
 */

p1PendingExpRow *p1PendingExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as p1PendingExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *p1PendingExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long p1PendingExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** p2PendingExpRow data structure
 *
 * Structure for representing a single row of p2PendingExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
    char            *recipe;
    psS32           p1_version;
    psS32           p2_version;
} p2PendingExpRow;

/** Creates a new p2PendingExpRow object
 *
 *  @return A new p2PendingExpRow object or NULL on failure.
 */

p2PendingExpRow *p2PendingExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Creates a new p2PendingExp table
 *
 * @return true on success
 */

bool p2PendingExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a p2PendingExp table
 *
 * @return true on success
 */

bool p2PendingExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2PendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool p2PendingExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats,
    char            **recipe,
    psS32           *p1_version,
    psS32           *p2_version
);

/** Insert a single p2PendingExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2PendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p2PendingExpRow *object             ///< p2PendingExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new p2PendingExpRow on success or NULL on failure.
 */

p2PendingExpRow *p2PendingExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table p2PendingExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool p2PendingExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool p2PendingExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool p2PendingExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a p2PendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2PendingExpMetadataFromObject(
    const p2PendingExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A p2PendingExpRow pointer or NULL on error
 */

p2PendingExpRow *p2PendingExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as p2PendingExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *p2PendingExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long p2PendingExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** p2PendingImfileRow data structure
 *
 * Structure for representing a single row of p2PendingImfile table data.
 */

typedef struct {
    char            *exp_id;
    char            *class_id;
    char            *uri;
    char            *stats;
    char            *recipe;
    psS32           p1_version;
    psS32           p2_version;
} p2PendingImfileRow;

/** Creates a new p2PendingImfileRow object
 *
 *  @return A new p2PendingImfileRow object or NULL on failure.
 */

p2PendingImfileRow *p2PendingImfileRowAlloc(
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Creates a new p2PendingImfile table
 *
 * @return true on success
 */

bool p2PendingImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a p2PendingImfile table
 *
 * @return true on success
 */

bool p2PendingImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2PendingImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool p2PendingImfilePop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **class_id,
    char            **uri,
    char            **stats,
    char            **recipe,
    psS32           *p1_version,
    psS32           *p2_version
);

/** Insert a single p2PendingImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2PendingImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p2PendingImfileRow *object             ///< p2PendingImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new p2PendingImfileRow on success or NULL on failure.
 */

p2PendingImfileRow *p2PendingImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table p2PendingImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool p2PendingImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool p2PendingImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool p2PendingImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a p2PendingImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2PendingImfileMetadataFromObject(
    const p2PendingImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A p2PendingImfileRow pointer or NULL on error
 */

p2PendingImfileRow *p2PendingImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as p2PendingImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *p2PendingImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long p2PendingImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** p2DoneExpRow data structure
 *
 * Structure for representing a single row of p2DoneExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
    char            *recipe;
    psS32           p1_version;
    psS32           p2_version;
} p2DoneExpRow;

/** Creates a new p2DoneExpRow object
 *
 *  @return A new p2DoneExpRow object or NULL on failure.
 */

p2DoneExpRow *p2DoneExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Creates a new p2DoneExp table
 *
 * @return true on success
 */

bool p2DoneExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a p2DoneExp table
 *
 * @return true on success
 */

bool p2DoneExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2DoneExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool p2DoneExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats,
    char            **recipe,
    psS32           *p1_version,
    psS32           *p2_version
);

/** Insert a single p2DoneExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2DoneExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p2DoneExpRow    *object             ///< p2DoneExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new p2DoneExpRow on success or NULL on failure.
 */

p2DoneExpRow *p2DoneExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table p2DoneExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool p2DoneExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool p2DoneExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool p2DoneExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a p2DoneExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2DoneExpMetadataFromObject(
    const p2DoneExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A p2DoneExpRow pointer or NULL on error
 */

p2DoneExpRow *p2DoneExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as p2DoneExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *p2DoneExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long p2DoneExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** p2DoneImfileRow data structure
 *
 * Structure for representing a single row of p2DoneImfile table data.
 */

typedef struct {
    char            *exp_id;
    char            *class_id;
    char            *uri;
    char            *stats;
    char            *recipe;
    psS32           p1_version;
    psS32           p2_version;
} p2DoneImfileRow;

/** Creates a new p2DoneImfileRow object
 *
 *  @return A new p2DoneImfileRow object or NULL on failure.
 */

p2DoneImfileRow *p2DoneImfileRowAlloc(
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Creates a new p2DoneImfile table
 *
 * @return true on success
 */

bool p2DoneImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a p2DoneImfile table
 *
 * @return true on success
 */

bool p2DoneImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2DoneImfileInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe,
    psS32           p1_version,
    psS32           p2_version
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool p2DoneImfilePop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **class_id,
    char            **uri,
    char            **stats,
    char            **recipe,
    psS32           *p1_version,
    psS32           *p2_version
);

/** Insert a single p2DoneImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p2DoneImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    p2DoneImfileRow *object             ///< p2DoneImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new p2DoneImfileRow on success or NULL on failure.
 */

p2DoneImfileRow *p2DoneImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table p2DoneImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool p2DoneImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool p2DoneImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool p2DoneImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a p2DoneImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p2DoneImfileMetadataFromObject(
    const p2DoneImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A p2DoneImfileRow pointer or NULL on error
 */

p2DoneImfileRow *p2DoneImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as p2DoneImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *p2DoneImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long p2DoneImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** p3PendingExpRow data structure
 *
 * Structure for representing a single row of p3PendingExp table data.
 */

typedef struct {
    char            *exp_id;
    char            *camera;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
    char            *recipe;
    psS32           p2_version;
    psS32           p3_version;
} p3PendingExpRow;

/** Creates a new p3PendingExpRow object
 *
 *  @return A new p3PendingExpRow object or NULL on failure.
 */

p3PendingExpRow *p3PendingExpRowAlloc(
    const char      *exp_id,
    const char      *camera,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p2_version,
    psS32           p3_version
);

/** Creates a new p3PendingExp table
 *
 * @return true on success
 */

bool p3PendingExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a p3PendingExp table
 *
 * @return true on success
 */

bool p3PendingExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p3PendingExpInsert(
    psDB            *dbh,               ///< Database handle
    const char      *exp_id,
    const char      *camera,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats,
    const char      *recipe,
    psS32           p2_version,
    psS32           p3_version
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool p3PendingExpPop(
    psDB            *dbh,               ///< Database handle
    char            **exp_id,
    char            **camera,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats,
    char            **recipe,
    psS32           *p2_version,
    psS32           *p3_version
);

/** Insert a single p3PendingExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool p3PendingExpInsertObject(
    psDB            *dbh,               ///< Database handle
    p3PendingExpRow *object             ///< p3PendingExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new p3PendingExpRow on success or NULL on failure.
 */

p3PendingExpRow *p3PendingExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table p3PendingExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool p3PendingExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool p3PendingExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool p3PendingExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a p3PendingExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *p3PendingExpMetadataFromObject(
    const p3PendingExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A p3PendingExpRow pointer or NULL on error
 */

p3PendingExpRow *p3PendingExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as p3PendingExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *p3PendingExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long p3PendingExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detRunRow data structure
 *
 * Structure for representing a single row of detRun table data.
 */

typedef struct {
    char            *det_type;
} detRunRow;

/** Creates a new detRunRow object
 *
 *  @return A new detRunRow object or NULL on failure.
 */

detRunRow *detRunRowAlloc(
    const char      *det_type
);

/** Creates a new detRun table
 *
 * @return true on success
 */

bool detRunCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detRun table
 *
 * @return true on success
 */

bool detRunDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRunInsert(
    psDB            *dbh,               ///< Database handle
    const char      *det_type
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detRunPop(
    psDB            *dbh,               ///< Database handle
    char            **det_type
);

/** Insert a single detRunRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detRunInsertObject(
    psDB            *dbh,               ///< Database handle
    detRunRow       *object             ///< detRunRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detRunRow on success or NULL on failure.
 */

detRunRow *detRunPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detRunRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detRunInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detRunPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detRunSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detRunRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detRunMetadataFromObject(
    const detRunRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detRunRow pointer or NULL on error
 */

detRunRow *detRunObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detRunRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detRunSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detRunDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detInputExpRow data structure
 *
 * Structure for representing a single row of detInputExp table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *exp_id;
    char            *camera;
    char            *telescope;
    char            *exp_type;
    psS32           imfiles;
    char            *filter;
    char            *stats;
} detInputExpRow;

/** Creates a new detInputExpRow object
 *
 *  @return A new detInputExpRow object or NULL on failure.
 */

detInputExpRow *detInputExpRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats
);

/** Creates a new detInputExp table
 *
 * @return true on success
 */

bool detInputExpCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detInputExp table
 *
 * @return true on success
 */

bool detInputExpDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detInputExpInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    psS32           iteration,
    const char      *exp_id,
    const char      *camera,
    const char      *telescope,
    const char      *exp_type,
    psS32           imfiles,
    const char      *filter,
    const char      *stats
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detInputExpPop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    psS32           *iteration,
    char            **exp_id,
    char            **camera,
    char            **telescope,
    char            **exp_type,
    psS32           *imfiles,
    char            **filter,
    char            **stats
);

/** Insert a single detInputExpRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detInputExpInsertObject(
    psDB            *dbh,               ///< Database handle
    detInputExpRow  *object             ///< detInputExpRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detInputExpRow on success or NULL on failure.
 */

detInputExpRow *detInputExpPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detInputExpRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detInputExpInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detInputExpPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detInputExpSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detInputExpRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detInputExpMetadataFromObject(
    const detInputExpRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detInputExpRow pointer or NULL on error
 */

detInputExpRow *detInputExpObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detInputExpRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detInputExpSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detInputExpDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detProcessedImfileRow data structure
 *
 * Structure for representing a single row of detProcessedImfile table data.
 */

typedef struct {
    psS32           det_id;
    char            *exp_id;
    char            *class_id;
    char            *uri;
    char            *stats;
    char            *recipe;
} detProcessedImfileRow;

/** Creates a new detProcessedImfileRow object
 *
 *  @return A new detProcessedImfileRow object or NULL on failure.
 */

detProcessedImfileRow *detProcessedImfileRowAlloc(
    psS32           det_id,
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Creates a new detProcessedImfile table
 *
 * @return true on success
 */

bool detProcessedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detProcessedImfile table
 *
 * @return true on success
 */

bool detProcessedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    const char      *exp_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detProcessedImfilePop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    char            **exp_id,
    char            **class_id,
    char            **uri,
    char            **stats,
    char            **recipe
);

/** Insert a single detProcessedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detProcessedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detProcessedImfileRow *object             ///< detProcessedImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detProcessedImfileRow on success or NULL on failure.
 */

detProcessedImfileRow *detProcessedImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detProcessedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detProcessedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detProcessedImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detProcessedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detProcessedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detProcessedImfileMetadataFromObject(
    const detProcessedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detProcessedImfileRow pointer or NULL on error
 */

detProcessedImfileRow *detProcessedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detProcessedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detProcessedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detProcessedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detStackedImfileRow data structure
 *
 * Structure for representing a single row of detStackedImfile table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    char            *stats;
    char            *recipe;
} detStackedImfileRow;

/** Creates a new detStackedImfileRow object
 *
 *  @return A new detStackedImfileRow object or NULL on failure.
 */

detStackedImfileRow *detStackedImfileRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Creates a new detStackedImfile table
 *
 * @return true on success
 */

bool detStackedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detStackedImfile table
 *
 * @return true on success
 */

bool detStackedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detStackedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detStackedImfilePop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    psS32           *iteration,
    char            **class_id,
    char            **uri,
    char            **stats,
    char            **recipe
);

/** Insert a single detStackedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detStackedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detStackedImfileRow *object             ///< detStackedImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detStackedImfileRow on success or NULL on failure.
 */

detStackedImfileRow *detStackedImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detStackedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detStackedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detStackedImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detStackedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detStackedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detStackedImfileMetadataFromObject(
    const detStackedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detStackedImfileRow pointer or NULL on error
 */

detStackedImfileRow *detStackedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detStackedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detStackedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detStackedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detNormalizedImfileRow data structure
 *
 * Structure for representing a single row of detNormalizedImfile table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *class_id;
    char            *uri;
    char            *stats;
    char            *recipe;
} detNormalizedImfileRow;

/** Creates a new detNormalizedImfileRow object
 *
 *  @return A new detNormalizedImfileRow object or NULL on failure.
 */

detNormalizedImfileRow *detNormalizedImfileRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Creates a new detNormalizedImfile table
 *
 * @return true on success
 */

bool detNormalizedImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detNormalizedImfile table
 *
 * @return true on success
 */

bool detNormalizedImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    psS32           iteration,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detNormalizedImfilePop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    psS32           *iteration,
    char            **class_id,
    char            **uri,
    char            **stats,
    char            **recipe
);

/** Insert a single detNormalizedImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detNormalizedImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detNormalizedImfileRow *object             ///< detNormalizedImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detNormalizedImfileRow on success or NULL on failure.
 */

detNormalizedImfileRow *detNormalizedImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detNormalizedImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detNormalizedImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detNormalizedImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detNormalizedImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detNormalizedImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detNormalizedImfileMetadataFromObject(
    const detNormalizedImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detNormalizedImfileRow pointer or NULL on error
 */

detNormalizedImfileRow *detNormalizedImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detNormalizedImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detNormalizedImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detNormalizedImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detMasterFrameRow data structure
 *
 * Structure for representing a single row of detMasterFrame table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *comment;
} detMasterFrameRow;

/** Creates a new detMasterFrameRow object
 *
 *  @return A new detMasterFrameRow object or NULL on failure.
 */

detMasterFrameRow *detMasterFrameRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *comment
);

/** Creates a new detMasterFrame table
 *
 * @return true on success
 */

bool detMasterFrameCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detMasterFrame table
 *
 * @return true on success
 */

bool detMasterFrameDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detMasterFrameInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    psS32           iteration,
    const char      *comment
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detMasterFramePop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    psS32           *iteration,
    char            **comment
);

/** Insert a single detMasterFrameRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detMasterFrameInsertObject(
    psDB            *dbh,               ///< Database handle
    detMasterFrameRow *object             ///< detMasterFrameRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detMasterFrameRow on success or NULL on failure.
 */

detMasterFrameRow *detMasterFramePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detMasterFrameRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detMasterFrameInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detMasterFramePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detMasterFrameSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detMasterFrameRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detMasterFrameMetadataFromObject(
    const detMasterFrameRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detMasterFrameRow pointer or NULL on error
 */

detMasterFrameRow *detMasterFrameObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detMasterFrameRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detMasterFrameSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detMasterFrameDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detMasterImfileRow data structure
 *
 * Structure for representing a single row of detMasterImfile table data.
 */

typedef struct {
    psS32           det_id;
    char            *class_id;
    char            *uri;
    char            *stats;
    char            *recipe;
} detMasterImfileRow;

/** Creates a new detMasterImfileRow object
 *
 *  @return A new detMasterImfileRow object or NULL on failure.
 */

detMasterImfileRow *detMasterImfileRowAlloc(
    psS32           det_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Creates a new detMasterImfile table
 *
 * @return true on success
 */

bool detMasterImfileCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detMasterImfile table
 *
 * @return true on success
 */

bool detMasterImfileDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detMasterImfileInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    const char      *class_id,
    const char      *uri,
    const char      *stats,
    const char      *recipe
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detMasterImfilePop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    char            **class_id,
    char            **uri,
    char            **stats,
    char            **recipe
);

/** Insert a single detMasterImfileRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detMasterImfileInsertObject(
    psDB            *dbh,               ///< Database handle
    detMasterImfileRow *object             ///< detMasterImfileRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detMasterImfileRow on success or NULL on failure.
 */

detMasterImfileRow *detMasterImfilePopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detMasterImfileRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detMasterImfileInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detMasterImfilePopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detMasterImfileSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detMasterImfileRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detMasterImfileMetadataFromObject(
    const detMasterImfileRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detMasterImfileRow pointer or NULL on error
 */

detMasterImfileRow *detMasterImfileObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detMasterImfileRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detMasterImfileSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detMasterImfileDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detResidImfileAnalysisRow data structure
 *
 * Structure for representing a single row of detResidImfileAnalysis table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *exp_id;
    char            *class_id;
    char            *stats;
    char            *recipe;
} detResidImfileAnalysisRow;

/** Creates a new detResidImfileAnalysisRow object
 *
 *  @return A new detResidImfileAnalysisRow object or NULL on failure.
 */

detResidImfileAnalysisRow *detResidImfileAnalysisRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *exp_id,
    const char      *class_id,
    const char      *stats,
    const char      *recipe
);

/** Creates a new detResidImfileAnalysis table
 *
 * @return true on success
 */

bool detResidImfileAnalysisCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detResidImfileAnalysis table
 *
 * @return true on success
 */

bool detResidImfileAnalysisDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidImfileAnalysisInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    psS32           iteration,
    const char      *exp_id,
    const char      *class_id,
    const char      *stats,
    const char      *recipe
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detResidImfileAnalysisPop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    psS32           *iteration,
    char            **exp_id,
    char            **class_id,
    char            **stats,
    char            **recipe
);

/** Insert a single detResidImfileAnalysisRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidImfileAnalysisInsertObject(
    psDB            *dbh,               ///< Database handle
    detResidImfileAnalysisRow *object             ///< detResidImfileAnalysisRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detResidImfileAnalysisRow on success or NULL on failure.
 */

detResidImfileAnalysisRow *detResidImfileAnalysisPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detResidImfileAnalysisRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detResidImfileAnalysisInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detResidImfileAnalysisPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detResidImfileAnalysisSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detResidImfileAnalysisRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detResidImfileAnalysisMetadataFromObject(
    const detResidImfileAnalysisRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detResidImfileAnalysisRow pointer or NULL on error
 */

detResidImfileAnalysisRow *detResidImfileAnalysisObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detResidImfileAnalysisRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detResidImfileAnalysisSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detResidImfileAnalysisDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);
/** detResidExpAnalysisRow data structure
 *
 * Structure for representing a single row of detResidExpAnalysis table data.
 */

typedef struct {
    psS32           det_id;
    psS32           iteration;
    char            *exp_id;
    char            *stats;
    char            *recipe;
    bool            accept;
} detResidExpAnalysisRow;

/** Creates a new detResidExpAnalysisRow object
 *
 *  @return A new detResidExpAnalysisRow object or NULL on failure.
 */

detResidExpAnalysisRow *detResidExpAnalysisRowAlloc(
    psS32           det_id,
    psS32           iteration,
    const char      *exp_id,
    const char      *stats,
    const char      *recipe,
    bool            accept
);

/** Creates a new detResidExpAnalysis table
 *
 * @return true on success
 */

bool detResidExpAnalysisCreateTable(
    psDB            *dbh                ///< Database handle
);

/** Deletes a detResidExpAnalysis table
 *
 * @return true on success
 */

bool detResidExpAnalysisDropTable(
    psDB            *dbh                ///< Database handle
);

/** Insert a single row into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidExpAnalysisInsert(
    psDB            *dbh,               ///< Database handle
    psS32           det_id,
    psS32           iteration,
    const char      *exp_id,
    const char      *stats,
    const char      *recipe,
    bool            accept
);

/** Removes the last row from the database and returns it
 *
 * @return true on success
 */

bool detResidExpAnalysisPop(
    psDB            *dbh,               ///< Database handle
    psS32           *det_id,
    psS32           *iteration,
    char            **exp_id,
    char            **stats,
    char            **recipe,
    bool            *accept
);

/** Insert a single detResidExpAnalysisRow object into a table
 *
 * This function constructs and inserts a single row based on it's parameters.
 *
 * @return true on success
 */

bool detResidExpAnalysisInsertObject(
    psDB            *dbh,               ///< Database handle
    detResidExpAnalysisRow *object             ///< detResidExpAnalysisRow object
);

/** Removes the last row from the database and returns it
 *
 * @return A new detResidExpAnalysisRow on success or NULL on failure.
 */

detResidExpAnalysisRow *detResidExpAnalysisPopObject(
    psDB            *dbh                ///< Database handle
);

/** Insert data from a binary FITS table detResidExpAnalysisRow into the database
 *
 * This function expects a psFits object with a FITS table as the first
 * extension.  The table must have at least one row of data in it, that is of
 * the appropriate format (number of columns and their type).  All other
 * extensions are ignored.
 *
 * @return true on success
 */

bool detResidExpAnalysisInsertFits(
    psDB            *dbh,               ///< Database handle
    const psFits    *fits               ///< psFits object
);

/** Removes the last limit row from the database and returns them in a binary FITS table.
 *
 * This function assumes an empty psFits object and will create a FITS table as
 * the first extension. 
 *
 * @return true on success
 */

bool detResidExpAnalysisPopFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Selects up to limit from the database and returns them in a binary FITS table
 *
 * This function assumes an empty psFits object and will create a FITS table
 * as the first extension.
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return true on success
 */

bool detResidExpAnalysisSelectRowsFits(
    psDB            *dbh,               ///< Database handle
    psFits          *fits,              ///< psFits object
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);

/** Convert a detResidExpAnalysisRow into an equivalent psMetadata
 *
 * @return A psMetadata pointer or NULL on error
 */

psMetadata *detResidExpAnalysisMetadataFromObject(
    const detResidExpAnalysisRow *object             ///< fooRow to convert into a psMetadata
);

/** Convert a psMetadata into an equivalent fooRow
 *
 * @return A detResidExpAnalysisRow pointer or NULL on error
 */

detResidExpAnalysisRow *detResidExpAnalysisObjectFromMetadata(
    psMetadata      *md                 ///< psMetadata to convert into a fooRow
);
/** Selects up to limit rows from the database and returns as detResidExpAnalysisRow objects in a psArray
 *
 *  See psDBSelectRows() for documentation on the format of where.
 *
 * @return A psArray pointer or NULL on error
 */

psArray *detResidExpAnalysisSelectRowObjects(
    psDB            *dbh,               ///< Database handle
    const psMetadata *where,            ///< Row match criteria
    unsigned long long limit            ///< Maximum number of elements to return
);
/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
 *
 *  Note that a 'where' search psMetadata is constructed from each object and
 *  used to find rows to delete.
 *
 * @return A The number of rows removed or a negative value on error
 */

long long detResidExpAnalysisDeleteRowObjects(
    psDB            *dbh,               ///< Database handle
    const psArray   *objects,           ///< Array of objects to delete
    unsigned long long limit            ///< Maximum number of elements to delete 
);

/// @}

#ifdef __cplusplus
}
#endif

#endif // DETRESIDEXPANALYSIS_DB_H
