/********************************************************************************
*
* File: evaluation.h
* Title: The evaluator for the relational database system SDB.
* Programmer: Leonidas Fegaras, UTA
* Date: 2/21/97
*
* SDB is actually an in-memory database system: the database state is read
* from the file "database" when SDB starts, manipulated in memory, and
* then written back to the same file when SDB exits. Even though these
* evaluation operations are in-memory, they have the same semantics as
* their disk counterparts. Currently, only sorting, merging, nest-loops,
* and aggregation are supported.
*
********************************************************************************/

/* change this constant to true if you want to trace the evaluation of a plan */
const bool trace_evaluation = false;

/* the block size in bytes */
const short block_size = 2048;


/*--------------------------------------------------------------------------------
- Class relation describes a relational table (both schema and data content)
--------------------------------------------------------------------------------*/

class relation;

typedef Expr Type;

/* the relation schema is a binding of attribute names to types */
typedef binding<Type>* Schema;

typedef relation* Relation;


/* the current tuple for a relation holds the relation itself
*  plus a pointer to the relational row (tuple) currently being read */
typedef struct { Relation relation; Expr tuple; }  current_tuple;

/* an evaluation environment is a binding from names of relations to current tuples */
typedef binding<current_tuple*>* Environment;


class relation: public gc {
  /* hidden */
  int compare ( Expr, Expr, Expr );
  bool equal_to ( Expr, Expr, list<Expr>* );
  bool less_than ( Expr, Expr, list<Expr>* );

public:
  String name;			/* name of the relation */
  Expr primary_key;		/* the primary key of relation */
  list<Expr>* foreign_keys;
  int record_size;		/* the size of a tuple in bytes */
  Schema schema;		/* relation schema */
  binding<Expr>* indexes;	/* the list of indexes (B+-trees) */
  list<Expr>* data;		/* the actual database as a list of tuples */
  int cardinality;		/* number of tuples in relation */
  int size;			/* the size of relation in blocks */

  /* relation constructors */
  relation ( Expr e, list<Expr>* constraints );
  relation ( String n, Schema s, Expr key );
  relation ( Relation r );

  /* copy a relation */
  Relation copy ();

  /* update a relation */
  drop_table ();					/* implements the sql DROP TABLE */
  insert ( Expr values );				/* implements the sql INSERT */
  remove ( Expr predicate );				/* implements the sql DELETE */
  update ( Expr predicate, binding<Expr>* values );	/* implements the sql UPDATE */

  /* relational unary operators */
  Relation select ( Expr predicate );
  Relation project ( list<Expr>* attributes );
  Relation sort ( Expr attributes );

  /* relational binary operators */
  Relation nested_loop ( Relation r, Expr predicate );
  Relation merge_join ( Relation r, Expr predicate, Expr x_order, Expr y_order );
  Relation group_by ( list<Expr>* groups );
  Relation append ( Relation r );

  /* is the relation empty? */
  bool is_empty () { return data->nullp(); }

  /* find an index for this relation that delivers this order */
  Expr find_index ( Expr order );

  /* put the name as a prefix to the attribute names */
  Relation append_name ( String name );

  /* print schema and data content of a relation */
  print();

  /* I/O stuff */
  friend Relation relation_read ( ifstream& from );
  relation_write ( ofstream& to );

};


/*--------------------------------------------------------------------------------
-  The tuple manipulation code; ie. it evaluates an expression or a predicate
-  over a tuple.
--------------------------------------------------------------------------------*/

class evaluator;


typedef evaluator* Evaluator;


class evaluator: public gc {

  list<Expr>* values;	/* one relational tuple */

public:

  /* constructors */
  evaluator ( list<Expr>* r ) { values = r; };
  evaluator ( Expr e ) { values = e->arguments(); };
  friend Evaluator tuple ( list<Expr>* r ) { return new evaluator(r); }
  friend Evaluator tuple ( Expr e ) { return new evaluator(e); }

  /* evaluate a projection */
  Expr projection ( Expr column, Schema schema );

  /* evaluate a grouping */
  Expr grouping ( Expr fnc );

  /* evaluate an sql expression */
  Expr expression ( Expr e, Schema schema );

  /* evaluate an sql predicate */
  bool predicate ( Expr pred, Schema schema );

};



/*--------------------------------------------------------------------------------
- a database holds both the database schema and the database content
--------------------------------------------------------------------------------*/


class database: public gc {
public:
  binding<Relation>* content;
  database () { content = new binding<Relation>; };

  /* read a database from a file */
  database ( String file_name );

  /* write a database to a file */
  close ( String file_name );

  /* print the entire database schema and content; long output */
  print ();

  /* find a relation in the database */
  Relation find_relation ( String name );

};



/*--------------------------------------------------------------------------------
-  High-level functions
--------------------------------------------------------------------------------*/


/* evaluate a plan */
Relation evaluate_plan ( Expr plan );


/* compile and execute an sql DDL command (eg. CREATE TABLE) */
do_DDL ( Expr e, list<Expr>* constraints );


/* compile and execute an sql DML command (eg. an sql query) */
do_DML ( Expr e );
