package simpledb;

import java.io.*;
import java.util.*;

/** Query is a wrapper class to manage the execution of queries.
    It takes a query plan in the form of a high level DbIterator 
    (built by initiating the constructors of query plans)
    and runs it as a part of a specified transaction.
    <p>
    In early assignments, it will seem unnecessary, as all that 
    it does is wrap the iterator, but later assignments will add 
    support for transaction management here.
    <p>
    For an example of how it is used, see test/DemoTest
    
    @see simpledb.test.DemoTest
    @author Sam Madden
*/

public class Query {
    DbIterator op;
    TransactionId tid;
    boolean started = false;

    public Query(DbIterator root, TransactionId t) {
	op = root;
	tid = t;
    }

    public void start() 
	throws IOException, DbException, TransactionAbortedException {
	op.open();

	started = true;
    }

    /** Returns the next tuple, or throws NoSuchElementException if the 
	iterator is closed.
	@return The next tuple in the iterator
	@throws DbException If there is an error in the database system
	@throws NoSuchElementException If the iterator has finished iterating
	@throws TransactionAbortedException If the transaction is aborted (e.g., due to a deadlock)
    */
    public Tuple getNext() 
	throws DbException, NoSuchElementException, TransactionAbortedException {
	
	Tuple tup = null;
	if (!started) throw new DbException("Database not started.");

	    try {
		tup = op.getNext();
	    } catch (NoSuchElementException e){
		op.close();
		throw e;
	    } catch (TransactionAbortedException e) {
		op.close();
		throw e;
	    } catch (DbException e) {
		//not sure what to do -- abort
		op.close();
		throw e;
	    } 

	return tup;
    }

    /** Close the iterator */
    public void close() throws IOException {
	op.close();
    }

}
