/**************************************************************************
 * Source Id :
 *
 * $Id: dbobj.h,v 1.1 2001/04/03 20:10:26 aleksandras Exp $
 *-------------------------------------------------------------------------
 * Project Notes :
 *
 *  Diamond Base
 *  ============
 *      A solid database implementation, spurred on by the continuing
 *  Metal (Lead) Base saga.
 *
 *  Project Team :
 *        A. Davison
 *        K. Lentin
 *        D. Platt
 *
 *	Project Commenced : 05-02-1993
 *
 *-------------------------------------------------------------------------
 *  Module Notes :
 *
 *		dbObject     : This is an object which handles low-level requests
 *                     from the diamondBase.
 *
 *  Original Author :
 *		Andy
 *
 **************************************************************************/

#ifndef __DB_DBOBJ_H__
#define __DB_DBOBJ_H__

#include <diamond/idxinfo.h>
#include <diamond/rserv.h>
#include <diamond/btree.h>
#include <diamond/object.h>
#include <diamond/mserv.h>
#include <diamond/d_types.h>
#include <iostream.h>
#include <fstream.h>

const int NO_REC = -1;

class dbObject;
class dbRegInfo;
class diamondBase;

class dbQueryInfo
{
	int32	queryId;
	int32	queryIdx;
	int32	queryRec;
	bool	queryLock;
public:
//-----
//	dbError status;

//	inline dberror(dbError err) { return status = err; };

	const char* verStr(void) const { return "$Id: dbobj.h,v 1.1 2001/04/03 20:10:26 aleksandras Exp $"; }
	dbQueryInfo(const int32 id, const int32 idx)
	{
		queryId = id;
		queryIdx = idx;
		queryRec = NO_REC;
		queryLock = false;
	}

#if 0
	void pError(char *s)
	{
		cerr << ": ";
		switch (status)
		{
			case db_ok: cerr << "OK"; break;
			case db_locked: cerr << "Query locked"; break;
			case db_unlocked: cerr << "Query not locked"; break;
			default: cerr << "GURGLE GURGLE SPLAT"; break;
		}
		cerr << endl;
	}
#endif

	// Lock the query. If it's already locked, tell them
	dbError lock(void)
	{
		dbError err = db_locked;
		if (queryLock == false)
		{
			queryLock = true;
			err = db_ok;
		}
		return dbErr(err);
	}

	// Unlock the query. If it's already unlocked, tell them
	dbError unlock(void)
	{
		dbError err = db_unlocked;
		if (queryLock == true)
		{
			queryLock = false;
			err = db_ok;
		}
		return dbErr(err);
	}

	// If the query is not locked, set the record this query used.
	dbError setRec(const int32 recIdx)
	{
		dbError err = db_locked;
		if (queryLock == false)
		{
			queryRec = recIdx;
			err = db_ok;
		}
		return dbErr(err);
	}

	// We locked?
	bool locked(void) const
	{
		return queryLock;
	}

friend dbObject;

};

#define MFII MAX_FIELDS_IN_INDEX
class dbObjData
{
public:
	// ----------------------------
	// Data which is used to carry out the requested
	// operations on the relation.
	// ----------------------------
	int16			uniqOff;		// unique offset - -1 if not present
	size_t			numIndices;		// How many indices are there ?
	size_t			numFields;		// How many fields are there ?
	size_t			dataLength;		// What is the total length of the rec ?
	size_t			stringCount;	// How many of the buggers we got?
	size_t			*stringField;	// What are the numbers of the strings;
	size_t			*theLongs;		// Array of offsets;
	size_t			*containsUniq;	// Index contains a unique field.
	size_t			*keyLength;		// Key lengths.
	size_t			*fieldLength;	// How long each field is.
	size_t			*fieldOffset;	// Where each field is.
	unsigned char	*fieldType;		// What type each field is.
	dbString		*fieldName;		// The field names.

	// These next two arrays are a real nightmare.
	// They list which fields the indexes are compared
	// on. There are two arrays, b/c they are compared in a
	// different order to their packing order. C=comparison order
	// P = packing order (during storage into btree)
	// We make these 32 bit, since they come from the file system
	// there will be a fracas under things like DOS every time they
	// are copied into a size_t !

	int32	(*indexedOnC)[MFII];// Which fields are in each index.
	int32	(*indexedOnP)[MFII];// Which fields are in each index.

	// This one is the offsets into the reordered keys of each field.
	int32	(*keyOffset)[MFII]; // Offset of fields in each key.
};

class dbObject : public dbObjData
{
public:
//-----

	dbError status;
//	inline dbError dboerror(dbError err) { return status = err; };
//	void pError(char *s);

private:
//------
	dbString	path;
	dbString	prefix;
	fieldList	fldList;
	indexList	idxList;
	recServer*	theRecServer;
	bTree**		theBTreeList;
	memServer*	theMemServer;

	dbQueryInfo*	queryInfo[MAX_QUERY];

	int32		usageCount;

public:
//-----
	dbObject(void)
	{
		idxList.numIndicies=0;
		theBTreeList=0;
		theRecServer=0;
		theMemServer=0;
		path.dispose();
		prefix.dispose();
	} // Use with care.
	dbObject(dbString& newpath, dbString& newname);
	~dbObject();
	dbObjData* getObjData(void) { return (dbObjData*)this; }
	const char* verStr(void) const;
	dbError checkRec(const int32 qId, const int32 recIdx, const bool lockit = false);
	dbError qBegin(const int32 idxId, int32& qId);
	dbError qEnd(int32& qId);
	dbError qSeekFirst(const int32 qId, DIA_object& theObject);
	dbError qSeekLast(const int32 qId, DIA_object& theObject);
	dbError qNext(const int32 qId, DIA_object& theObject, const bool lockit = false);
	dbError qPeekNext(const int32 qId, DIA_object& theObject);
	dbError qPrev(const int32 qId, DIA_object& theObject, const bool lockit = false);
	dbError qPeekPrev(const int32 qId, DIA_object& theObject);
	dbError qSeek(const int32 qId, DIA_object& theObject);
	dbError qWrite(const int32 qId, DIA_object& theObject);
	dbError add(DIA_object& theObject);
	dbError del(const DIA_object& theObject);
	dbError lock(const bool lockit, const bool block) { return theRecServer->lock(lockit, block); }
	void	stats(void) const;
	void	flush(void);
	dbError	getStrings(const DIA_object& theObject);
	int32	recordCount(void) { return theRecServer?(theRecServer->recordCount()):-1; }

friend class dbRegInfo;
friend class diamondBase;

};

#endif

//////////////////////////////////////////////////////////////////////////
// Revision History:
//
// $Log: dbobj.h,v $
// Revision 1.1  2001/04/03 20:10:26  aleksandras
// big one 3.1 (comments later)
//
// Revision 1.34  1996/08/22  12:42:10  dmb
// Improved file I/O error handling
//
// Revision 1.33  1996/02/01 22:49:31  dmb
// int32.
//
// Revision 1.32  1995/10/04  02:13:39  davison
// Changed references to objects to DIA_objects to prevent namespace clashes.
//
// Revision 1.31  1994/09/30 08:37:36  kevinl
// Added keyOffset array
//
// Revision 1.30  1994/05/15  05:04:54  kevinl
// Type fixups. Conversion of char* to dbString
//
// Revision 1.29  1994/04/23  02:40:29  kevinl
// recordCount added for diarel record counting
//
// Revision 1.28  1994/03/17  04:34:45  kevinl
// Added lock and flush
//
// Revision 1.27  1994/02/25  03:11:27  darrenp
// Changes to make DOS binary compatible witht eh world
//
// Revision 1.26  1994/02/03  05:54:19  kevinl
// Moved include files to diamond/ and fixed HAVE_MALLOC_H
//
// Revision 1.25  1993/12/23  22:58:48  kevinl
// dbErr uses dbString, autoconf stuff, moved logs, added const and size_t
//
// Revision 1.24  1993/11/04  14:59:41  kevinl
// Fixed record locking
//
// Revision 1.23  1993/10/28  07:49:01  kevinl
// Added diaGRel dbString/dbData support
//
// Revision 1.22  1993/10/18  11:18:40  kevinl
// Added fieldName array
//
// Revision 1.21  1993/10/05  07:29:57  kevinl
// Added in dbObjData (previously in diaGRel)
//
// Revision 1.20  1993/06/23  05:21:22  kevinl
// Mallocs are now in angular brackets
//
// Revision 1.19  1993/06/20  13:39:23  kevinl
// theMemServer etc for String support
//
// Revision 1.18  1993/05/11  14:44:50  kevinl
// Added version number output
//
// Revision 1.17  1993/05/03  01:34:25  kevinl
// No more extern consts
//
// Revision 1.16  1993/05/01  14:38:08  kevinl
// Got rid of ints
// Reowrked inlie funcs to have 1 return
//
// Revision 1.15  1993/04/27  07:15:24  kevinl
// Added qWrite
// Fixed qId bounds checks on all query functions
//
// Revision 1.14  1993/04/25  13:19:57  kevinl
// Comments
//
// Revision 1.13  1993/04/15  07:58:55  kevinl
// Added del
//
// Revision 1.12  1993/04/15  04:28:17  kevinl
// Move malloc.h
//
// Revision 1.11  1993/04/11  05:49:02  kevinl
// Rationalised find/seek/peek methods etc
//
// Revision 1.10  1993/04/09  13:00:29  kevinl
// Stats can be called from diaRel now.
//
// Revision 1.9  1993/04/07  02:29:21  kevinl
// Changed qEnd to reset qId to -1
//
// Revision 1.8  1993/04/01  04:23:18  kevinl
// Fixed locking
// Added qFind, fixed the rest
//
// Revision 1.7  1993/03/30  07:15:19  davison
// Added the usage count stuff.
//
// Revision 1.6  1993/03/29  08:06:01  darrenp
// Nuked pathinfo
//
// Revision 1.5  1993/03/29  06:12:49  darrenp
// Nuked pathinfo structure
//
// Revision 1.4  1993/03/28  10:32:05  davison
// Modified for dbErr.
//
// Revision 1.3  1993/03/28  04:53:59  root
// more error code standardization.
//
// Revision 1.2  1993/03/26  06:16:38  darrenp
// standardized error codes.
//
// Revision 1.1  1993/03/25  22:29:25  davison
// Initial revision
//
//////////////////////////////////////////////////////////////////////////
