/*-------------------------------------------------------------------------
 *
 * libpq++.H
 *    
 *
 *   DESCRIPTION
 *	C++ client interface to Postgres
 *      used for building front-end applications
 *
 *   NOTES
 *
 *   IDENTIFICATION
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 * libpq++.H,v 1.1 1995/01/10 00:41:09 jolly Exp
 *
 *-------------------------------------------------------------------------
 */

#ifndef LIBPQXX_H
#define LIBPQXX_H

// XXX
struct Port;
struct FILE;

// ****************************************************************
//
// PGenv - the environment for setting up a connection to postgres
//
// ****************************************************************
class PGenv {
public:
  char* pqhost;
  int pqport;
  char* pqtty;
  PGenv();  // default ctor will use reasonable defaults
            // will use environment  variables PGHOST, PGPORT, PGTTY
  PGenv(char* host, int port, char* tty);
  setValues(char* host, int port, char* tty);
  ~PGenv();
};

typedef enum {CONNECTION_OK,
	      CONNECTION_BAD}  ConnStatusType;


// ****************************************************************
//
//
// PGconn - a connection made to a postgres backend
//
//
// ****************************************************************
class PGconn {
  friend class PGresult;

  char* databaseName;
  ConnStatusType connStatus;
  char* errorMessage;
  PGenv* env; 
  // socket file descriptors for communicating with the backend
  FILE* Pfout;
  FILE* Pfin;
  // Port defined in pqcomm.h
  Port* port;

public:
  PGconn(); // use reasonable defaults
  PGconn(PGenv* env, char* dbName); // connect to the database with 
                                    // given environment and database name
  int reconnect(); // close down current connection and
                   // re-establish communication with the postmaster
  ConnStatusType status() {return connStatus;};
  //  CONNECTION_OK --> connection successfully open
  //  CONNECTION_BAD --> connection failed, check errMsg();
  
  // the most recent error message from the backend
  char* errMsg() {return errorMessage;};

  // returns the database name of the connection
  char* dbName() {return databaseName;}; 

  PGresult* exec(char* query);  // send a query to the backend
       // the caller is responsible for delete'ing the PGresult when done
       // tuples are in binary or ASCII, depending on the query
       // (i.e. select 

  ~PGconn(); // close connection and clean up
protected:
  ConnStatusType connect(PGenv* env, char* dbName);
  int close();
};


// ****************************************************************
//
// PGresult  - the result from running a query
// 
// ****************************************************************

typedef enum {
  PGRES_FATAL_ERROR = 0,
  PGRES_BAD_CONNECTION,  // connection to backend is faulty
  PGRES_BAD_QUERY,     // query never made it to the backend
  PGRES_EMPTY_QUERY,     // query was empty
  PGRES_NO_RESPONSE,   // query was sent, but no response from the backend
  PGRES_BAD_RESPONSE,   // query was sent, but got an unexpected 
                        // response from the backend
  PGRES_NONFATAL_ERROR,
  PGRES_COMMAND_OK,  // a query command that doesn't return
                    // anything was executed properly by the backend
  PGRES_TUPLES_OK  // a query command that returns tuples
                   // was executed properly by the backend, PGresult
                   // contains the necessary tuples
	     } ExecStatusType;

//
// an array of convenience strings so users can access
// pgresStatus[ExecStatusType] to get a string value of the status
//
extern char* pgresStatus[];

typedef struct PGresAttDesc {
  char* name; // type name
  int adtid;  // type id
  int adtsize; // type size
} PGresAttDesc;

typedef char* PGresAttValue;     // use char* for Attribute values

typedef struct PGresGroup {
  int numTuples;          // number of actual tuples in this gruop
  int numAttributes;
  PGresAttDesc *attDescs; // array of attribute descriptors
  PGresAttValue* *tuples; // each PGresTuple is an array of PGresAttValue's
  int tupArrSize;         // size of tuples array allocated
} PGresGroup;

class PGresult{
  int ntups;
  int ngrps;

public:
  PGresGroup* groups;
  char* pname;
  PGconn* conn;
  FILE* Pfin;
  ExecStatusType resultStatus;

  PGresult(FILE* f, PGconn* conn, char* pname);
  // ctor fills out the result from the stream of tuples from f

  PGresult(ExecStatusType s);  // ctor with status

  ~PGresult();
  ExecStatusType status() { return resultStatus; };
  int ntuples() { return ntups; };// return the number of tuples in a PGresult;
  int ngroups() { return ngrps; };// return the number of groups in a PGresult;

protected:
  PGresGroup* addGroup(); // extend the group array,
                           // return the last element of the array 
  PGresAttValue* getTuple(PGresGroup* grp, int binary); 
      // get the next tuple from the stream and add it to the current group

  void addTuple(PGresGroup* group, PGresAttValue* tuple);
};

//----------------------------------------------------------
//----------------------------------------------------------
// miscellaneous routines defined in pgmisc.c
//

// dupstr:  returns a duplicate of a string,  caller is responsible for
// freeing the space returns NULL if the argument is NULL
extern char* dupstr(char* s);

// PQgetstr and PQputstr,  send strings to the file stream
// returns 0 if successful
extern int pqGets(char* s, int maxlen, FILE* stream);
extern int pqPuts(char* s, FILE* stream );

// get a n-byte integer from the stream into result
// returns 0 if successful
extern int pqGetInt(int* result, int n, FILE* stream );


// backend-dependent constants
// same as ELOG_MAXLEN from elog.h
#define MAX_ERRMSG_LEN 4096

// max length of message to send to 
#define MAX_MESSAGE_LEN 8193

// maximum number of fields in a tuple
#define BYTELEN 8
#define MAX_FIELDS 512


//
// these are the environment variables used for getting defaults
//

#define ENV_DEFAULT_PORT  "PGPORT"
#define ENV_DEFAULT_HOST  "PGHOST"
#define ENV_DEFAULT_TTY   "PGTTY"
#define ENV_DEFAULT_DBASE "PGDATABASE"



#endif /* LIBPQXX_H */
