//
// See the file LICENSE for redistribution information.
//
// Copyright (c) 2002-2003
//	Sleepycat Software.  All rights reserved.
//

static const char revid[] = "$Id: XmlResults.cpp,v 1.28 2003/10/13 20:19:50 gmf Exp $";

#include "dbxml_config.h"
#include "dbxml/XmlPortability.hpp"
#include "dbxml/XmlException.hpp"
#include "dbxml/XmlResults.hpp"
#include "dbxml/XmlDocument.hpp"
#include "Results.hpp"

using namespace DbXml;

XmlResults::XmlResults(XmlQueryContext &context, DbTxn *txn)
	: results_(new Results(context, txn)),
          context_(new XmlQueryContext(context))
{
	results_->acquire();
}

XmlResults::~XmlResults()
{
	results_->release();
	delete context_;
}

XmlResults::XmlResults(const XmlResults &o)
	: results_(o.results_),
          context_(new XmlQueryContext(*o.context_))
{
	if (results_ != 0)
		results_->acquire();
}

XmlResults &XmlResults::operator=(const XmlResults &o)
{
	if (this != &o && results_ != o.results_) {
		if (results_ != 0)
			results_->release();
		results_ = o.results_;
		*context_ = *o.context_;
		if (results_ != 0)
			results_->acquire();
	}
	return *this;
}

void XmlResults::reset()
{
	results_->reset();
}

size_t XmlResults::size() const
{
	size_t size;
	Results::SizeType type;
	results_->size(size, type);
	if(type==Results::Estimate)
	{
		throw XmlException(XmlException::LAZY_EVALUATION, "This result set is lazily evaluated. size() can only be called for eagerly evaluated result sets.");
	}
	return size;
}

bool XmlResults::next(XmlValue &value)
{
	int err = 0;
	try {
		err = results_->next(value);
	} catch (DbException &e) {
		throw XmlException(e);
	}
	if (err != 0)
		throw XmlException(err);

	return (!value.isNull());
}

bool XmlResults::next(XmlDocument &document, XmlValue &value)
{
	bool r= next(value);
	if (r) {
		document= value.asDocument(); // throws if incorrect value type
	}
	return r;
}

bool XmlResults::next(XmlDocument &document)
{
	XmlValue value;
	return next(document, value);
}

void XmlResults::add(const XmlValue &value)
{
	results_->add(value);
}

// these 3 next() methods are deprecated, and the txn paramter is ignored.
bool XmlResults::next(DbTxn *txn, XmlValue &value)
{
	int err = 0;
	try {
		err = results_->next(value);
	} catch (DbException &e) {
		throw XmlException(e);
	}
	if (err != 0)
		throw XmlException(err);

	return (!value.isNull());
}

bool XmlResults::next(DbTxn *txn, XmlDocument &document, XmlValue &value)
{
	bool r= next(value);
	if (r) {
		document= value.asDocument(); // throws if incorrect value type
	}
	return r;
}

bool XmlResults::next(DbTxn *txn, XmlDocument &document)
{
	XmlValue value;
	return next(document, value);
}

