Patches for Berkeley DB XML version 2.4.13

  1. Consolidated patch for 2.4 support issues (SRs): 16177, 16179, 16180, 16181, 16186

    [#16177]
    Fixed problem in the XmlQueryContext copy constructor where the XmlManager object was not being copied.
    [#16179]
    Fixed a problem where an XmlValue.getAttributes() call on an XmlValue object that was not the result of a query (e.g. directly from an XmlDocument) could result in an error.
    [#16180]
    Fixed a problem in the BDB XML XQuery Extension function dbxml:node-to-handle() where it could return an exception/error when attempting to create a handle for an attribute node.
    [#16181]
    Fixed a bug in query optimization which resulted in exponential query preparation time increases as the number of negative predicates used was increased.
    [#16186]
    Fixed a problem where it was not possible to open a container using the DB_RDONLY flag.

  2. Apply the following patch to the dbxml-2.4.13 release.  
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/ConfigurationDatabase.cpp dbxml-2.4.13/dbxml/src/dbxml/ConfigurationDatabase.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/ConfigurationDatabase.cpp	Tue Jan 15 16:27:16 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/ConfigurationDatabase.cpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: ConfigurationDatabase.cpp,v 1.43 2008/01/15 15:35:02 jpcs Exp $
      //
      
      #include "DbXmlInternal.hpp"
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: ConfigurationDatabase.cpp,v 1.43.2.1 2008/05/13 20:23:52 gmf Exp $
      //
      
      #include "DbXmlInternal.hpp"
    ***************
    *** 91,107 ****
      		// which will fail for pre-2.2 containers
      		if (err == 0 && doVersionCheck)
      			err = checkVersion(txn, rdonly);
    ! 		if (err == 0)
      			err = seqDatabase_.open(txn, DB_BTREE, flags, mode);
    ! 
    ! 		if (err == 0)
    ! 			seq_ = initDbSequence(txn, seqDatabase_.getDb(),
    ! 					      seqIncr_, flags);
    ! 
    ! 		// Add the default index specification, if there
    ! 		// isn't one already
    ! 		if(err == 0 && !rdonly)
    ! 			err = checkIndexSpecification(txn);
      
      		// Add, or set the container type.  If this is
      		// a create, it won't be there. "type" is by ref
    --- 91,106 ----
      		// which will fail for pre-2.2 containers
      		if (err == 0 && doVersionCheck)
      			err = checkVersion(txn, rdonly);
    ! 		if (err == 0 && !rdonly) {
      			err = seqDatabase_.open(txn, DB_BTREE, flags, mode);
    ! 			if (err == 0)
    ! 				seq_ = initDbSequence(txn, seqDatabase_.getDb(),
    ! 						      seqIncr_, flags);
    ! 			// Add the default index specification, if there
    ! 			// isn't one already and not read-only
    ! 			if(err == 0)
    ! 				err = checkIndexSpecification(txn);
    ! 		}
      
      		// Add, or set the container type.  If this is
      		// a create, it won't be there. "type" is by ref
    ***************
    *** 154,159 ****
    --- 153,159 ----
      	db_seq_t newValue = 0;
      	u_int32_t flags = 0;
      	DbTxn *dbtxn = 0;
    + 	DBXML_ASSERT(seq_);
      	if (txn) flags |= DB_AUTO_COMMIT|DB_TXN_NOSYNC;
      	try {
      		err = seq_->get(dbtxn, 1, &newValue, flags);
    ***************
    *** 166,171 ****
    --- 166,172 ----
      
      void ConfigurationDatabase::resetSequenceCache()
      {
    + 	DBXML_ASSERT(seq_);
      	try {
      		seq_->set_cachesize(seqIncr_);
      	} catch (DbException &e) {
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/Container.cpp dbxml-2.4.13/dbxml/src/dbxml/Container.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/Container.cpp	Tue Apr 15 13:26:17 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/Container.cpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: Container.cpp,v 1.326 2008/04/15 15:14:00 gmf Exp $
      //
      
      #include "DbXmlInternal.hpp"
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: Container.cpp,v 1.326.2.1 2008/05/13 20:23:52 gmf Exp $
      //
      
      #include "DbXmlInternal.hpp"
    ***************
    *** 138,143 ****
    --- 138,144 ----
      	  id_(-1),
      	  usingTxns_((txn != 0) || (flags & DBXML_TRANSACTIONAL)),
      	  usingCDB_(false),
    + 	  readOnly_(false),
      	  indexDbNotify_(0)
      {
      	if (pagesize != 0 && (pagesize < 512 || pagesize > 65536)) {
    ***************
    *** 157,163 ****
      
      	try {
      		TransactionGuard txnGuard;
    ! 		txn = autoTransact(txn, txnGuard);
      
      		err = openInternal(txn, flags, mode, doVersionCheck);
      		if(err == 0) txnGuard.commit();
    --- 158,165 ----
      
      	try {
      		TransactionGuard txnGuard;
    ! 		// do not check read-only status in this call
    ! 		txn = autoTransact(txn, txnGuard, false);
      
      		err = openInternal(txn, flags, mode, doVersionCheck);
      		if(err == 0) txnGuard.commit();
    ***************
    *** 243,249 ****
      
      	// Remove flags that aren't passed to DB
      	flags &= ~(DBXML_INDEX_NODES|DBXML_NO_INDEX_NODES|
    ! 		DBXML_STATISTICS|DBXML_NO_STATISTICS|DBXML_ALLOW_VALIDATION);
      	
      	// set default page sizes if creating, and not already set
      	//
    --- 245,254 ----
      
      	// Remove flags that aren't passed to DB
      	flags &= ~(DBXML_INDEX_NODES|DBXML_NO_INDEX_NODES|
    ! 		   DBXML_STATISTICS|DBXML_NO_STATISTICS|DBXML_ALLOW_VALIDATION);
    ! 
    ! 	if (flags & DB_RDONLY)
    ! 		readOnly_ = true;
      	
      	// set default page sizes if creating, and not already set
      	//
    ***************
    *** 1916,1929 ****
      	delete toDel;
      }
      
    ! Transaction *Container::autoTransact(Transaction *txn, TransactionGuard &txnGuard) const
      {
      	return Transaction::autoTransact(txn, mgr_, txnGuard, usingTxns_, usingCDB_);
      }
      
      /////////////////////////////////
      // Implemention of ContainerBase methods
      
      void Container::getIndexSpecification(Transaction *txn,
      				      IndexSpecification &is)
      {
    --- 1921,1948 ----
      	delete toDel;
      }
      
    ! Transaction *Container::autoTransact(Transaction *txn,
    ! 				     TransactionGuard &txnGuard,
    ! 				     bool ckReadOnly) const
      {
    + 	if (ckReadOnly)
    + 		checkReadOnly(); // may throw
      	return Transaction::autoTransact(txn, mgr_, txnGuard, usingTxns_, usingCDB_);
      }
      
      /////////////////////////////////
      // Implemention of ContainerBase methods
      
    + void Container::checkReadOnly() const
    + {
    + 	if (readOnly_) {
    + 		string msg = "Cannot perform updating operation on read-only container: ";
    + 		msg += getName();
    + 		throw XmlException(XmlException::INVALID_VALUE,
    + 				   msg);
    + 	}
    + }
    + 
      void Container::getIndexSpecification(Transaction *txn,
      				      IndexSpecification &is)
      {
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/Container.hpp dbxml-2.4.13/dbxml/src/dbxml/Container.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/Container.hpp	Wed Jan 23 13:57:37 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/Container.hpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: Container.hpp,v 1.172 2008/01/23 18:57:37 gmf Exp $
      //
      
      #ifndef __CONTAINER_HPP
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: Container.hpp,v 1.172.2.1 2008/05/13 20:23:52 gmf Exp $
      //
      
      #ifndef __CONTAINER_HPP
    ***************
    *** 134,139 ****
    --- 134,141 ----
      	void getIndexSpecification(Transaction *txn,
      				   IndexSpecification &index);
      
    + 	virtual void checkReadOnly() const; // throws if read-only
    + 
      	virtual Cost getDocumentSSCost(OperationContext &oc, StructuralStatsCache &cache);
      	virtual Cost getIndexCost(OperationContext &oc,
      		DbWrapper::Operation op1, const Key &key1,
    ***************
    *** 351,357 ****
      	void openIndexDbs(Transaction *txn, u_int32_t flags, int mode);
      	void logDocumentOperation(const Document &doc, const char *msg);
      
    ! 	Transaction *autoTransact(Transaction *txn, TransactionGuard &txnGuard) const;
      private:
      	XmlManager xmlMgr_;
      	u_int32_t flags_;
    --- 353,361 ----
      	void openIndexDbs(Transaction *txn, u_int32_t flags, int mode);
      	void logDocumentOperation(const Document &doc, const char *msg);
      
    ! 	Transaction *autoTransact(Transaction *txn,
    ! 				  TransactionGuard &txnGuard,
    ! 				  bool checkReadonly = true) const;
      private:
      	XmlManager xmlMgr_;
      	u_int32_t flags_;
    ***************
    *** 365,370 ****
    --- 369,375 ----
      	int id_;
      	bool usingTxns_;
      	bool usingCDB_; // ignored if not using DB 4.5 or greater
    + 	bool readOnly_;
      
      	IndexDbNotify *indexDbNotify_;
      
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/ContainerBase.hpp dbxml-2.4.13/dbxml/src/dbxml/ContainerBase.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/ContainerBase.hpp	Wed Jan 16 13:23:24 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/ContainerBase.hpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: ContainerBase.hpp,v 1.17 2008/01/16 18:23:24 gmf Exp $
      //
      
      #ifndef __CONTAINERBASE_HPP
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: ContainerBase.hpp,v 1.17.2.1 2008/05/13 20:23:52 gmf Exp $
      //
      
      #ifndef __CONTAINERBASE_HPP
    ***************
    *** 64,69 ****
    --- 64,70 ----
      	virtual int getContainerID() const { return 0; }
      	virtual void getIndexSpecification(Transaction *txn,
      					   IndexSpecification &index);
    + 	virtual void checkReadOnly() const { return; }
      
      	// get the estimated cost of an operation
      	virtual Cost getDocumentSSCost(OperationContext &oc, StructuralStatsCache &cache);
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/RawNodeValue.cpp dbxml-2.4.13/dbxml/src/dbxml/RawNodeValue.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/RawNodeValue.cpp	Tue Apr 15 13:26:17 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/RawNodeValue.cpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: RawNodeValue.cpp,v 1.19 2008/04/11 14:07:35 lauren Exp $
      //
      
      #include "DbXmlInternal.hpp"
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: RawNodeValue.cpp,v 1.19.2.1 2008/05/09 19:44:18 gmf Exp $
      //
      
      #include "DbXmlInternal.hpp"
    ***************
    *** 98,104 ****
      	ContainerBase *cont = ((Manager&)mgr).getContainerFromID(cid_, false);
      	if(!cont)
      		throw XmlException(XmlException::CONTAINER_CLOSED, "Cannot complete operation because container is closed.");
    ! 	return cont->getDbWrapper();
      }
      
      DictionaryDatabase *RawNodeValue::getDictDB() const
    --- 98,111 ----
      	ContainerBase *cont = ((Manager&)mgr).getContainerFromID(cid_, false);
      	if(!cont)
      		throw XmlException(XmlException::CONTAINER_CLOSED, "Cannot complete operation because container is closed.");
    ! 	 DbWrapper *docDb = cont->getDbWrapper();
    ! 	 //Materialize whole documents that have not already been parsed into the temporary nodestorage db
    ! 	 if(!docDb){
    ! 		XmlDocument doc = asDocument();
    ! 		(*doc).getElement(*NsNid::getRootNid(),0);
    ! 		docDb = (*doc).getDocDb();
    ! 	 }
    ! 	 return docDb;
      }
      
      DictionaryDatabase *RawNodeValue::getDictDB() const
    ***************
    *** 112,118 ****
      }
      
      void RawNodeValue::getNsDomNode() const
    ! {
      	if (!node_) {
      		doc_.init(GET_RESULTS().getOperationContext().txn(),
      			  getDocDB(), getDictDB(),
    --- 119,125 ----
      }
      
      void RawNodeValue::getNsDomNode() const
    ! { 
      	if (!node_) {
      		doc_.init(GET_RESULTS().getOperationContext().txn(),
      			  getDocDB(), getDictDB(),
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/Value.cpp dbxml-2.4.13/dbxml/src/dbxml/Value.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/Value.cpp	Mon Mar  3 13:33:19 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/Value.cpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: Value.cpp,v 1.140 2008/03/03 17:53:18 gmf Exp $
      //
      
      #include "DbXmlInternal.hpp"
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: Value.cpp,v 1.140.2.1 2008/05/09 16:21:06 gmf Exp $
      //
      
      #include "DbXmlInternal.hpp"
    ***************
    *** 526,532 ****
      {
      	if (((Document&)d_).getContainerID() == 0) {
      		throw XmlException(XmlException::INVALID_VALUE,
    ! 				   "getNodeHandle() requires a live node");
      	}
      
      	IndexEntry ie;
    --- 526,532 ----
      {
      	if (((Document&)d_).getContainerID() == 0) {
      		throw XmlException(XmlException::INVALID_VALUE,
    ! 				   "Node handles are only available for nodes from a container");
      	}
      
      	IndexEntry ie;
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.cpp dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.cpp	Wed Mar 26 15:35:19 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.cpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: DbXmlNodeImpl.cpp,v 1.103 2008/03/26 19:35:19 gmf Exp $
      //
      
      #include "../DbXmlInternal.hpp"
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: DbXmlNodeImpl.cpp,v 1.103.2.2 2008/05/13 20:23:52 gmf Exp $
      //
      
      #include "../DbXmlInternal.hpp"
    ***************
    *** 313,318 ****
    --- 313,365 ----
      	return XMLString::replicate((XMLCh*)target.getRawBuffer(), mm);
      }
      
    + string DbXmlNodeImpl::getNodeHandle() const
    + {
    + 	// this method will only work on nodes from a real container
    + 	if (getContainerID() == 0) {
    + 		throw XmlException(XmlException::INVALID_VALUE,
    + 				   "Node handles are only available for nodes from a container");
    + 	}
    + 	IndexEntry ie;
    + 	ie.setDocID(getDocID());
    + 
    + 	short type = getNodeType();
    + 	if(type != nsNodeDocument) {
    + 		ie.setNodeID(getNodeID());
    + 
    + 		if(type == nsNodeElement) {
    + 			ie.setFormat(IndexEntry::NH_ELEMENT_FORMAT);
    + 		} else if(type == nsNodeAttr) {
    + 			ie.setFormat(IndexEntry::NH_ATTRIBUTE_FORMAT);
    + 			ie.setIndex(getIndex());
    + 		} else if(type == nsNodeText ||
    + 			type == nsNodeCDATA) {
    + 			ie.setFormat(IndexEntry::NH_TEXT_FORMAT);
    + 			ie.setIndex(getIndex());
    + 		} else if(type == nsNodeComment) {
    + 			ie.setFormat(IndexEntry::NH_COMMENT_FORMAT);
    + 			ie.setIndex(getIndex());
    + 		} else if(type == nsNodePinst) {
    + 			ie.setFormat(IndexEntry::NH_PI_FORMAT);
    + 			ie.setIndex(getIndex());
    + 		} else {
    + 			throw XmlException(XmlException::INVALID_VALUE,
    + 				"Node handle unavailable for node type");
    + 		}
    + 	} else {
    + 		ie.setFormat(IndexEntry::NH_DOCUMENT_FORMAT);
    + 	}
    + 
    + 	return ie.getNodeHandle();
    + }
    + 
    + void DbXmlNodeImpl::checkReadOnly() const
    + {
    + 	ContainerBase *base = getContainer();
    + 	if (base)
    + 		base->checkReadOnly();
    + }
    + 	
      //
      // DbxmlNsDomNode Implementation
      //
    ***************
    *** 434,439 ****
    --- 481,487 ----
      bool DbXmlNsDomNode::isUpdateAble() const
      {
      	MATERIALISE_NODE;
    + 	checkReadOnly();
      	if ((Document*)document_ &&
      	    ((Document*)document_)->getDocDb())
      		return true;
    ***************
    *** 575,615 ****
      	return node_->getLastDescendantNid();
      }
      
    - string DbXmlNsDomNode::getNodeHandle() const
    - {
    - 	IndexEntry ie;
    - 	ie.setDocID(getDocID());
    - 
    - 	short type = getNodeType();
    - 	if(type != nsNodeDocument) {
    - 		ie.setNodeID(getNodeID());
    - 
    - 		if(type == nsNodeElement) {
    - 			ie.setFormat(IndexEntry::NH_ELEMENT_FORMAT);
    - 		} else if(type == nsNodeAttr) {
    - 			ie.setFormat(IndexEntry::NH_ATTRIBUTE_FORMAT);
    - 			ie.setIndex(getIndex());
    - 		} else if(type == nsNodeText ||
    - 			type == nsNodeCDATA) {
    - 			ie.setFormat(IndexEntry::NH_TEXT_FORMAT);
    - 			ie.setIndex(getIndex());
    - 		} else if(type == nsNodeComment) {
    - 			ie.setFormat(IndexEntry::NH_COMMENT_FORMAT);
    - 			ie.setIndex(getIndex());
    - 		} else if(type == nsNodePinst) {
    - 			ie.setFormat(IndexEntry::NH_PI_FORMAT);
    - 			ie.setIndex(getIndex());
    - 		} else {
    - 			throw XmlException(XmlException::INVALID_VALUE,
    - 				"Node handle unavailable for node type");
    - 		}
    - 	} else {
    - 		ie.setFormat(IndexEntry::NH_DOCUMENT_FORMAT);
    - 	}
    - 
    - 	return ie.getNodeHandle();
    - }
    - 
      const XMLCh* DbXmlNsDomNode::getLocalName() const
      {
      	switch(getNodeType())
    --- 623,628 ----
    ***************
    *** 1306,1311 ****
    --- 1319,1325 ----
      
      bool DbXmlAttributeNode::isUpdateAble() const
      {
    + 	checkReadOnly();
      	// attributes are only updateable if they
      	// exist in a real container (vs constructed)
      	// TBD -- maybe think about updating standalone
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.hpp dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.hpp	Wed Mar 26 15:35:19 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlNodeImpl.hpp	Tue May 13 16:33:12 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: DbXmlNodeImpl.hpp,v 1.61 2008/03/26 19:35:19 gmf Exp $
      //
      
      #ifndef __DBXMLNODEIMPL_HPP
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: DbXmlNodeImpl.hpp,v 1.61.2.2 2008/05/13 20:23:52 gmf Exp $
      //
      
      #ifndef __DBXMLNODEIMPL_HPP
    ***************
    *** 152,158 ****
      				      DynamicContext *context) const {
      		return 0;
      	}
    ! 	virtual std::string getNodeHandle() const { return 0; }
      	virtual DbXmlResult getAxisDbXmlResult(XQStep::Axis axis,
      					       const NodeTest *nodeTest,
      					       const DynamicContext *context,
    --- 152,158 ----
      				      DynamicContext *context) const {
      		return 0;
      	}
    ! 	virtual std::string getNodeHandle() const;
      	virtual DbXmlResult getAxisDbXmlResult(XQStep::Axis axis,
      					       const NodeTest *nodeTest,
      					       const DynamicContext *context,
    ***************
    *** 166,171 ****
    --- 166,173 ----
      	virtual const XMLCh *getPrefix() const { return 0; }
      	virtual const XMLCh *getValue() const { return 0; }
      	virtual const XMLCh *getPITarget() const { return 0; }
    + protected:
    + 	void checkReadOnly() const;
      };
      	
      class DbXmlNsDomNode: public DbXmlNodeImpl
    ***************
    *** 232,238 ****
      	virtual Item::Ptr getMetaData(const XMLCh *uri,
      				      const XMLCh *name,
      				      DynamicContext *context) const;
    - 	virtual std::string getNodeHandle() const;
      	virtual const XMLCh *getLocalName() const;
      	virtual const XMLCh *getUri() const;
      	virtual const XMLCh *getPrefix() const;
    --- 234,239 ----
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/query/BufferQP.cpp dbxml-2.4.13/dbxml/src/dbxml/query/BufferQP.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/query/BufferQP.cpp	Wed Jan  9 09:49:45 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/query/BufferQP.cpp	Tue May 13 16:33:13 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: BufferQP.cpp,v 1.22 2008/01/08 21:54:25 bostic Exp $
      //
      
      #include "../DbXmlInternal.hpp"
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: BufferQP.cpp,v 1.22.2.1 2008/05/09 16:04:41 gmf Exp $
      //
      
      #include "../DbXmlInternal.hpp"
    ***************
    *** 33,39 ****
      	: QueryPlan(BUFFER, flags, mm),
      	  parent_(parent),
      	  arg_(arg),
    ! 	  bufferId_(bufferId)
      {
      }
      
    --- 33,41 ----
      	: QueryPlan(BUFFER, flags, mm),
      	  parent_(parent),
      	  arg_(arg),
    ! 	  bufferId_(bufferId),
    ! 	  parentCost_(),
    ! 	  parentCostSet_(false)
      {
      }
      
    ***************
    *** 66,71 ****
    --- 68,74 ----
      	_src.clear();
      
      	parent_ = parent_->staticTyping(context);
    + 	parentCostSet_ = false;
      	// Do not add the StaticAnalysis, as
      	// that is handled by the BufferEndQP objects
      
    ***************
    *** 82,87 ****
    --- 85,91 ----
      	_src.clear();
      
      	parent_->staticTypingLite(context);
    + 	parentCostSet_ = false;
      	// Do not add the StaticAnalysis, as
      	// that is handled by the BufferEndQP objects
      
    ***************
    *** 95,100 ****
    --- 99,105 ----
      {
      	// Optimise the parent QueryPlan
      	parent_ = parent_->optimize(opt);
    + 	parentCostSet_ = false;
      
      	BufferReferenceSetter().run(this);
      
    ***************
    *** 253,258 ****
    --- 258,264 ----
      		mm = memMgr_;
      	}
      
    + 	// We deliberately don't copy the parentCost_ - it's only a cache
      	BufferQP *result = new (mm) BufferQP(parent_->copy(mm), arg_->copy(mm), bufferId_, flags_, mm);
      	result->setLocationInfo(this);
      	BufferReferenceSetter().run(result);
    ***************
    *** 273,287 ****
      	arg_->findQueryPlanRoots(qprset);
      }
      
      Cost BufferQP::cost(OperationContext &context, QueryExecutionContext &qec) const
      {
    ! 	Cost parentCost = parent_->cost(context, qec);
      
      	Cost cost = arg_->cost(context, qec);
    ! 	cost.pagesOverhead += parentCost.totalPages();
      
      	// Add the cost of storing the buffered data
    ! 	cost.pagesOverhead += parentCost.keys * INLINE_BYTES_PER_KEY_THRESHOLD;
      
      	return cost;
      }
    --- 279,302 ----
      	arg_->findQueryPlanRoots(qprset);
      }
      
    + Cost BufferQP::getParentCost(OperationContext &context, QueryExecutionContext &qec) const
    + {
    + 	if(!parentCostSet_) {
    + 		parentCost_ = parent_->cost(context, qec);
    + 		parentCostSet_ = true;
    + 	}
    + 	return parentCost_;
    + }
    + 
      Cost BufferQP::cost(OperationContext &context, QueryExecutionContext &qec) const
      {
    ! 	getParentCost(context, qec);
      
      	Cost cost = arg_->cost(context, qec);
    ! 	cost.pagesOverhead += parentCost_.totalPages();
      
      	// Add the cost of storing the buffered data
    ! 	cost.pagesOverhead += parentCost_.keys * INLINE_BYTES_PER_KEY_THRESHOLD;
      
      	return cost;
      }
    ***************
    *** 370,376 ****
      Cost BufferReferenceQP::cost(OperationContext &context, QueryExecutionContext &qec) const
      {
      	Cost cost;
    ! 	cost.keys = bqp_->getParent()->cost(context, qec).keys;
      
      	// Add the cost of retriving the buffered data
      	cost.pagesForKeys = cost.keys * INLINE_BYTES_PER_KEY_THRESHOLD;
    --- 385,391 ----
      Cost BufferReferenceQP::cost(OperationContext &context, QueryExecutionContext &qec) const
      {
      	Cost cost;
    ! 	cost.keys = bqp_->getParentCost(context, qec).keys;
      
      	// Add the cost of retriving the buffered data
      	cost.pagesForKeys = cost.keys * INLINE_BYTES_PER_KEY_THRESHOLD;
    diff -cr dbxml-2.4.13.orig/dbxml/src/dbxml/query/BufferQP.hpp dbxml-2.4.13/dbxml/src/dbxml/query/BufferQP.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/query/BufferQP.hpp	Wed Jan  9 09:49:45 2008
    --- dbxml-2.4.13/dbxml/src/dbxml/query/BufferQP.hpp	Tue May 13 16:33:13 2008
    ***************
    *** 3,9 ****
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: BufferQP.hpp,v 1.10 2008/01/08 21:54:25 bostic Exp $
      //
      
      #ifndef __BUFFERQP_HPP
    --- 3,9 ----
      //
      // Copyright (c) 2002,2008 Oracle.  All rights reserved.
      //
    ! // $Id: BufferQP.hpp,v 1.10.2.1 2008/05/09 16:04:41 gmf Exp $
      //
      
      #ifndef __BUFFERQP_HPP
    ***************
    *** 45,50 ****
    --- 45,51 ----
      
      	virtual NodeIterator *createNodeIterator(DynamicContext *context) const;
      	virtual Cost cost(OperationContext &context, QueryExecutionContext &qec) const;
    + 	Cost getParentCost(OperationContext &context, QueryExecutionContext &qec) const;
      
      	virtual void findQueryPlanRoots(QPRSet &qprset) const;
      	virtual bool isSubsetOf(const QueryPlan *o) const;
    ***************
    *** 57,62 ****
    --- 58,66 ----
      	QueryPlan *parent_;
      	QueryPlan *arg_;
      	unsigned int bufferId_;
    + 
    + 	mutable Cost parentCost_;
    + 	mutable bool parentCostSet_;
      };
      
      class BufferReferenceQP : public QueryPlan
    diff -cr dbxml-2.4.13.orig/dbxml/src/java/com/sleepycat/dbxml/XmlQueryContext.java dbxml-2.4.13/dbxml/src/java/com/sleepycat/dbxml/XmlQueryContext.java
    *** dbxml-2.4.13.orig/dbxml/src/java/com/sleepycat/dbxml/XmlQueryContext.java	Fri Mar 21 13:29:32 2008
    --- dbxml-2.4.13/dbxml/src/java/com/sleepycat/dbxml/XmlQueryContext.java	Tue May 13 16:33:13 2008
    ***************
    *** 39,44 ****
    --- 39,45 ----
      	if(o.namespaces != null) namespaces = new HashMap(o.namespaces);
      	if(o.variables != null)variables = new HashMap(o.variables);
      	interrupt = new Interrupter();
    + 	mgr = o.mgr;
          }
      
          public void delete(){}
    diff -cr dbxml-2.4.13.orig/dbxml/src/java/com/sleepycat/dbxml/XmlValue.java dbxml-2.4.13/dbxml/src/java/com/sleepycat/dbxml/XmlValue.java
    *** dbxml-2.4.13.orig/dbxml/src/java/com/sleepycat/dbxml/XmlValue.java	Wed Apr  2 12:34:40 2008
    --- dbxml-2.4.13/dbxml/src/java/com/sleepycat/dbxml/XmlValue.java	Tue May 13 16:33:13 2008
    ***************
    *** 3,9 ****
      
      //Copyright (c) 2002,2008 Oracle.  All rights reserved.
      
    ! //$Id: XmlValue.java,v 1.75 2008/03/21 17:23:54 lauren Exp $
      
      
      package com.sleepycat.dbxml;
    --- 3,9 ----
      
      //Copyright (c) 2002,2008 Oracle.  All rights reserved.
      
    ! //$Id: XmlValue.java,v 1.75.2.1 2008/05/09 19:44:18 gmf Exp $
      
      
      package com.sleepycat.dbxml;
    ***************
    *** 1000,1008 ****
      	    checkConstructedDocument();
      	    XmlResults xmlresults = HelperFunctions.getAttributes(ID, getResult());
      	    if(tempResults != null)
    ! 		tempResults.delete();
    ! 	    XmlResults origResults = getResult();
    ! 	    xmlresults.resultsMapPut(new Long(XmlResults.getCPtr(origResults)), origResults);
      	    return xmlresults;
      	}
      		
    --- 1000,1011 ----
      	    checkConstructedDocument();
      	    XmlResults xmlresults = HelperFunctions.getAttributes(ID, getResult());
      	    if(tempResults != null)
    ! 		xmlresults.resultsMapPut(new Long(XmlResults.getCPtr(tempResults)), tempResults);
    ! 	    else{
    ! 		XmlResults origResults = getResult();
    ! 		xmlresults.resultsMapPut(new Long(XmlResults.getCPtr(origResults)), origResults);
    ! 	    }
    ! 	    
      	    return xmlresults;
      	}
      		
    diff -cr dbxml-2.4.13.orig/dbxml/test/java/XmlQueryContext/QueryContextTest.java dbxml-2.4.13/dbxml/test/java/XmlQueryContext/QueryContextTest.java
    *** dbxml-2.4.13.orig/dbxml/test/java/XmlQueryContext/QueryContextTest.java	Wed Apr 30 10:59:54 2008
    --- dbxml-2.4.13/dbxml/test/java/XmlQueryContext/QueryContextTest.java	Tue May 13 16:33:14 2008
    ***************
    *** 75,80 ****
    --- 75,105 ----
      	XmlValue origValue = original.getVariableValue("name");
      	XmlValue copiedValue = copied.getVariableValue("name");
      	assertTrue(origValue.equals(copiedValue));
    + 	
    + 	String docString = "Other text"
    + 	    + "";
    + 	String query = "collection('" + CON_NAME + "')/old:a_node/c_node";
    + 	XmlTransaction txn = null;
    + 	XmlResults res = null;
    + 	try{
    + 	    if(hp.isTransactional()){
    + 		txn = mgr.createTransaction();
    + 		cont.putDocument(txn, docName, docString);
    + 		res = mgr.query(txn, query, copied);
    + 	    }else{
    + 		cont.putDocument(docName, docString);
    + 		res = mgr.query(query, copied);
    + 	    }    
    + 	    assert(res.size() > 0);
    + 	}catch(XmlException e){
    + 	    throw e;
    + 	}finally{
    + 	    if(txn != null) txn.commit();
    + 	    if(res != null) res.delete();
    + 	    res = null;
    + 	}
      
      	try{
      	    copied = new XmlQueryContext(null);
    diff -cr dbxml-2.4.13.orig/dbxml/test/java/XmlValue/ValueTest.java dbxml-2.4.13/dbxml/test/java/XmlValue/ValueTest.java
    *** dbxml-2.4.13.orig/dbxml/test/java/XmlValue/ValueTest.java	Wed Apr 30 10:59:54 2008
    --- dbxml-2.4.13/dbxml/test/java/XmlValue/ValueTest.java	Tue May 13 16:33:14 2008
    ***************
    *** 3,9 ****
       *
       * Copyright (c) 2007,2008 Oracle.  All rights reserved.
       *
    !  * $Id: ValueTest.java,v 1.18 2008/04/30 13:02:58 lauren Exp $
       */
      
      package dbxmltest;
    --- 3,9 ----
       *
       * Copyright (c) 2007,2008 Oracle.  All rights reserved.
       *
    !  * $Id: ValueTest.java,v 1.17.2.2 2008/05/09 19:47:35 gmf Exp $
       */
      
      package dbxmltest;
    ***************
    *** 2721,2726 ****
    --- 2721,2755 ----
      	    if(results != null)results.delete();
      	    results = null;
      	}
    + 	
    + 	try{
    + 	    if(hp.isTransactional())
    + 		results = mgr.query(txn, "collection('"+ CON_NAME+"')/old:a_node", context);
    + 	    else
    + 		results = mgr.query("collection('"+ CON_NAME+"')/old:a_node", context);
    + 
    + 	    value = results.next();
    + 	    tempResults = value.getAttributes();
    + 	    tempValue = tempResults.next(); 
    + 	    assertTrue(tempValue.getNodeName().matches("atr1") || tempValue.getNodeName().matches("atr2") || tempValue.getNodeName().matches("xmlns:old"));
    + 	    assertTrue(tempValue.getNodeValue().matches("test") || tempValue.getNodeValue().matches("test2") || tempValue.getNodeValue().matches("http://dbxmltest.test/test"));
    + 	    results.delete();
    + 	    results = null;
    + 	    try{
    + 		tempValue = tempResults.next();
    + 		tempValue.getNodeName();
    + 		fail("Failure in ValueTest.testGetAttributes()");
    + 	    }catch(XmlException e){
    + 		assertEquals(e.getErrorCode(), XmlException.INVALID_VALUE);
    + 	    }
    + 	}catch(XmlException e){
    + 	    throw e;
    + 	}finally{
    + 	    if(tempResults != null) tempResults.delete();
    + 	    tempResults = null;
    + 	    if(results != null)results.delete();
    + 	    results = null;
    + 	}
      
      	XmlDocument contextDoc = mgr.createDocument();
      	contextDoc.setContent(docString);
    ***************
    *** 2753,2758 ****
    --- 2782,2808 ----
      	    results = null;
      	}
      
    + 	XmlResults atts = null;
    + 	try{
    + 	    if(hp.isTransactional())
    + 		contextDoc = cont.getDocument(txn, docName);
    + 	    else
    + 		contextDoc = cont.getDocument(docName);
    + 	    docValue = new XmlValue(contextDoc);
    + 	    XmlValue xmlValue = docValue.getFirstChild();
    + 	    atts = xmlValue.getAttributes();
    + 	    while (atts.hasNext()) {
    + 		tempValue = atts.next();
    + 		assertTrue(tempValue.getNodeName().matches("atr1") || tempValue.getNodeName().matches("atr2") || tempValue.getNodeName().matches("xmlns:old"));
    + 		assertTrue(tempValue.getNodeValue().matches("test") || tempValue.getNodeValue().matches("test2") || tempValue.getNodeValue().matches("http://dbxmltest.test/test"));
    + 	    }
    + 	}catch(XmlException e){
    + 	    throw e;
    + 	}finally{
    + 	    if(atts != null)atts.delete();
    + 	    atts = null;
    + 	}
    + 
      	// test null XmlValue
      	try {
      	    vl_NONE.getAttributes();
    diff -cr dbxml-2.4.13.orig/dbxml/test/queries/queries.xml dbxml-2.4.13/dbxml/test/queries/queries.xml
    *** dbxml-2.4.13.orig/dbxml/test/queries/queries.xml	Fri Apr 25 11:00:36 2008
    --- dbxml-2.4.13/dbxml/test/queries/queries.xml	Tue May 13 16:33:14 2008
    ***************
    *** 1,4 ****
    ! 
    --- 1,4 ----
    ! 
    ***************
    *** 124,129 ****
    --- 124,135 ----
            aCollection
            ancestor-Q8.out
          
    +     
    +       
    +       
    +       aCollection
    +       FORG0001
    +     
        
      
        
    diff -cr dbxml-2.4.13.orig/dbxml/test/tcl/xml008.tcl dbxml-2.4.13/dbxml/test/tcl/xml008.tcl
    *** dbxml-2.4.13.orig/dbxml/test/tcl/xml008.tcl	Tue Apr 15 15:33:55 2008
    --- dbxml-2.4.13/dbxml/test/tcl/xml008.tcl	Tue May 13 16:33:14 2008
    ***************
    *** 2,8 ****
      #
      # Copyright (c) 2000,2008 Oracle.  All rights reserved.
      #
    ! # $Id: xml008.tcl,v 1.6 2008/04/15 19:33:45 gmf Exp $
      #
      # TEST	xml008
      # TEST	Container Management
    --- 2,8 ----
      #
      # Copyright (c) 2000,2008 Oracle.  All rights reserved.
      #
    ! # $Id: xml008.tcl,v 1.6.2.1 2008/05/13 20:23:53 gmf Exp $
      #
      # TEST	xml008
      # TEST	Container Management
    ***************
    *** 47,53 ****
          }
      
          set basename $tnum
    !     
          # multiple containers
          xml008_1 $env $txnenv $basename.1 $oargs
          
    --- 47,53 ----
          }
      
          set basename $tnum
    ! 
          # multiple containers
          xml008_1 $env $txnenv $basename.1 $oargs
          
    ***************
    *** 71,76 ****
    --- 71,79 ----
      
          # container not found
          xml008_9 $env $txnenv $basename.9 $oargs
    + 
    +     # container read only
    +     xml008_10 $env $txnenv $basename.10 $oargs
          
          return
      }
    ***************
    *** 829,831 ****
    --- 832,942 ----
          delete mgr
      }
      
    + # Container read only
    + proc xml008_10 { {env "NULL"} {txnenv 0} {basename $tnum} oargs } {
    +     puts "\t8.10: Container read only"
    +     source ./include.tcl
    +     set txn "0"
    + 
    +     xml_cleanup $testdir $env
    +     xml_database mgr $testdir $env
    +     wrap XmlUpdateContext uc [$mgr createUpdateContext]
    + 
    +     set container_name "readonly.dbxml"
    +     set doc_name "doc"
    +     set doc_name1 "doc1"
    +     set doc_content ""
    + 
    +     # create a container and insert a document
    +     if { $txnenv == 1 } {
    + 	wrap XmlTransaction txn [$mgr createTransaction]
    + 	wrap XmlContainer container [$mgr createContainer $txn $container_name $oargs $global_container_type]
    + 	$container putDocument $txn $doc_name $doc_content $uc
    + 	$txn commit
    + 	delete txn
    +     } else {
    + 	wrap XmlContainer container [$mgr createContainer $container_name $oargs $global_container_type]
    + 	$container putDocument $doc_name $doc_content $uc
    +     }
    +     # close the container
    +     delete container
    + 
    +     # open it read-only
    +     set ronly_args [expr $oargs + $DB_RDONLY]
    +     if { $txnenv == 1 } {
    + 	wrap XmlTransaction txn [$mgr createTransaction]
    + 	wrap XmlContainer container [$mgr openContainer $txn $container_name $ronly_args]
    + 	$txn commit
    + 	delete txn
    +     } else {
    + 	wrap XmlContainer container [$mgr openContainer $container_name $ronly_args]
    +     }
    +     $container addAlias "alias"
    + 
    +     wrap XmlQueryContext qc [$mgr createQueryContext]
    + 
    +     # try to putdocument
    +     if { $txnenv == 1 } {
    + 	wrap XmlTransaction txn [$mgr createTransaction]
    + 	catch { $container putDocument $txn $doc_name1 $doc_content $uc } ret
    + 	$txn commit
    + 	delete txn
    +     } else {
    + 	wrap XmlContainer container [$mgr openContainer $container_name $ronly_args]
    + 	catch { $container putDocument $doc_name1 $doc_content $uc } ret
    +     }
    +     dbxml_error_check_good $basename [string match "*read-only*" $ret] 1
    + 
    +     # try to add an index
    +     if { $txnenv == 1 } {
    + 	wrap XmlTransaction txn [$mgr createTransaction]
    + 	wrap XmlIndexSpecification is [$container getIndexSpecification]
    + 	catch { $container setIndexSpecification $txn $is $uc } ret
    + 	$txn commit
    + 	delete txn
    +     } else {
    + 	wrap XmlIndexSpecification is [$container getIndexSpecification]
    + 	catch { $container setIndexSpecification $is $uc } ret
    +     }
    +     delete is;
    +     dbxml_error_check_good $basename [string match "*read-only*" $ret] 1
    +     
    + 
    +     # basic query  (will work)
    +     set query "collection('alias')/root/a"
    +     if { $txnenv == 1 } {
    + 	wrap XmlTransaction txn [$mgr createTransaction]
    + 	wrap XmlResults res [$mgr query $txn $query $qc]
    +     } else {
    + 	wrap XmlResults res [$mgr query $query $qc]
    +     }
    +     
    +     new XmlValue value
    +     while { [$res next $value] } {
    + 	set v [$value asString]
    +     }
    +     if { $txnenv == 1 } {
    + 	$txn commit
    + 	delete txn
    +     }
    +     delete res
    +     delete value
    + 
    +     # update query (will fail)
    +     set query "for \$i in collection('alias')/root/a return rename node \$i as 'b'"
    +     if { $txnenv == 1 } {
    + 	wrap XmlTransaction txn [$mgr createTransaction]
    + 	catch {wrap XmlResults res [$mgr query $txn $query $qc]} ret
    + 	$txn commit
    + 	delete txn
    +     } else {
    + 	catch {wrap XmlResults res [$mgr query $query $qc]} ret
    +     }
    +     dbxml_error_check_good $basename [string match "*read-only*" $ret] 1
    +     
    +     delete qc
    +     delete container
    +     delete uc
    +     delete mgr
    + }
    + 
    

  3. Consolidated patch for 2.4 support issues (SRs): 16206, 16230, 16236

    [#16206]
    Fixed the generation of an incorrect query plan for a numeric predicate in a where clause, and a memory corruption when JIT optimizing a DecisionPointQP nested inside another DecisionPointQP.
    [#16230]
    Fixed a query problem where expressions starting with "/" would succeed on XML without a document node (e.g. constructed XML) when they should fail.
    [#16236]
    Fixed a Java-specific problem where some context queries against constructed XML could cause a SIGSEGV.

  4. Apply the following patch to the dbxml-2.4.13 release.  
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.cpp dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.cpp
    --- dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.cpp
    ***************
    *** 35,41 ****
      	  xmlDoc_(0),
      	  doingSequence_(0),
      	  writer_(0),
    ! 	  seq_(context->getMemoryManager())
      {
      	rootNid_.setLen(0, false);
      }
    --- 35,42 ----
      	  xmlDoc_(0),
      	  doingSequence_(0),
      	  writer_(0),
    ! 	  seq_(context->getMemoryManager()),
    ! 	  nextIsRoot_(false)
      {
      	rootNid_.setLen(0, false);
      }
    ***************
    *** 80,88 ****
      	// get the "root" of the sequence and create a node
      	NsDomElement *root = ((Document&)xmlDoc_).getElement(NsNid(&rootNid_), 0);
      	DBXML_ASSERT(root);
    - 	// Tell NsDom that this is the "root" of the tree, whether it's
    - 	// a Document node or not
    - 	root->setIsRoot();
      	
      	seq_.addItem(((DbXmlFactoryImpl*)context_->getItemFactory())->
      		     createNode(root, xmlDoc_, context_));
    --- 81,86 ----
    ***************
    *** 98,104 ****
    --- 96,104 ----
      {
      	DBXML_ASSERT(!writer_);
      	DBXML_ASSERT(!doingSequence_);
    + 	DBXML_ASSERT(!nextIsRoot_);
      	writer_ = createWriter(xmlDoc_, context_, &rootNid_);
    + 	nextIsRoot_ = true;
      	doingSequence_++;
      	((Document*)xmlDoc_)->setDocumentURI(documentURI);
      	((Document*)xmlDoc_)->getNsDocument()->
    ***************
    *** 121,131 ****
      					     const XMLCh *uri,
      					     const XMLCh *localname)
      {
    ! 	bool isRoot = false;
      	if (writer_ == 0) {
      		DBXML_ASSERT(!doingSequence_);
      		writer_ = createWriter(xmlDoc_, context_, 0);
    ! 		isRoot = true;
      	}
      	doingSequence_++;
      	XMLChToUTF8Null pfx(prefix);
    --- 121,132 ----
      					     const XMLCh *uri,
      					     const XMLCh *localname)
      {
    ! 	bool initRootNid = false;
      	if (writer_ == 0) {
      		DBXML_ASSERT(!doingSequence_);
      		writer_ = createWriter(xmlDoc_, context_, 0);
    ! 		initRootNid = true;
    ! 		nextIsRoot_ = true;
      	}
      	doingSequence_++;
      	XMLChToUTF8Null pfx(prefix);
    ***************
    *** 133,139 ****
      	XMLChToUTF8Null lname(localname);
      	writer_->writeStartElementInternal(lname.ucstr(), pfx.ucstr(),
      					   turi.ucstr(),
    ! 					   (isRoot ? &rootNid_ : 0));
      }
      
      void DbXmlSequenceBuilder::endElementEvent(const XMLCh *prefix,
    --- 134,142 ----
      	XMLChToUTF8Null lname(localname);
      	writer_->writeStartElementInternal(lname.ucstr(), pfx.ucstr(),
      					   turi.ucstr(),
    ! 					   (initRootNid ? &rootNid_ : 0),
    ! 					   nextIsRoot_);
    ! 	nextIsRoot_ = false; // unconditionally clear
      }
      
      void DbXmlSequenceBuilder::endElementEvent(const XMLCh *prefix,
    diff dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.hpp dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.hpp
    --- dbxml-2.4.13/dbxml/src/dbxml/dataItem/DbXmlSequenceBuilder.hpp
    53a54
    >        bool nextIsRoot_;
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsDom.cpp dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsDom.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsDom.cpp
    --- dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsDom.cpp
    ***************
    *** 102,108 ****
      			   NsDoc *document) :
      
      	NsDomNode(document), node_(node),
    ! 	lname_(0), isRoot_(false)
      {
      	if (isDocumentNode()) {
      		qname_.set(_nsDomDocName, false);
    --- 102,108 ----
      			   NsDoc *document) :
      
      	NsDomNode(document), node_(node),
    ! 	lname_(0)
      {
      	if (isDocumentNode()) {
      		qname_.set(_nsDomDocName, false);
    ***************
    *** 120,125 ****
    --- 120,137 ----
      	return new NsDomElement(*node_, doc_);
      }
      
    + void NsDomElement::setIsRoot()
    + {
    + 	DBXML_ASSERT(node_);
    + 	node_->setIsRoot();
    + }
    + 
    + bool NsDomElement::isRoot() const
    + {
    + 	DBXML_ASSERT(node_);
    + 	return node_->isRoot();
    + }
    + 
      void NsDomElement::refreshNode(OperationContext &oc,
      			       bool forWrite)
      {
    ***************
    *** 275,281 ****
      NsDomElement *
      NsDomElement::getElemParent()
      {
    ! 	if (isRoot_ || isDocumentNode())
      		return 0;
      	NsDomElement *ret = new NsDomElement(getParentNode(), doc_);
      	if (!ret)
    --- 287,293 ----
      NsDomElement *
      NsDomElement::getElemParent()
      {
    ! 	if (isRoot() || isDocumentNode())
      		return 0;
      	NsDomElement *ret = new NsDomElement(getParentNode(), doc_);
      	if (!ret)
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsDom.hpp dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsDom.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsDom.hpp
    --- dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsDom.hpp
    ***************
    *** 155,167 ****
      		return node_->numAttrs();
      	}
      		
    - 	
      	// TBD GMF Hack to indicate that a constructed element
      	// is the "root" of its tree -- i.e. don't navigate to
      	// the parent (document) node.  A better solution is to
      	// allow trees without a document node in node storage
    ! 	void setIsRoot() { isRoot_ = true; }
    ! 	bool isRoot() const { return isRoot_; }
      
      	//
      	// Navigational methods that operate on element nodes
    --- 155,166 ----
      		return node_->numAttrs();
      	}
      		
      	// TBD GMF Hack to indicate that a constructed element
      	// is the "root" of its tree -- i.e. don't navigate to
      	// the parent (document) node.  A better solution is to
      	// allow trees without a document node in node storage
    ! 	void setIsRoot();
    ! 	bool isRoot() const;
      
      	//
      	// Navigational methods that operate on element nodes
    ***************
    *** 190,196 ****
      	mutable NsString baseUri_;
      	mutable NsString uri_;
      	mutable NsString prefix_;
    - 	bool isRoot_;
      };
      
      //
    --- 189,194 ----
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsEventWriter.cpp dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsEventWriter.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsEventWriter.cpp
    --- dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsEventWriter.cpp
    ***************
    *** 576,582 ****
      void NsEventWriter::writeStartElementInternal(const unsigned char *localName,
      					      const unsigned char *prefix,
      					      const unsigned char *uri,
    ! 					      NsFullNid *nid)
      {
      	DBXML_ASSERT(!writer_);
      	DBXML_ASSERT(!_ewriter);
    --- 576,582 ----
      void NsEventWriter::writeStartElementInternal(const unsigned char *localName,
      					      const unsigned char *prefix,
      					      const unsigned char *uri,
    ! 					      NsFullNid *nid, bool setIsRoot)
      {
      	DBXML_ASSERT(!writer_);
      	DBXML_ASSERT(!_ewriter);
    ***************
    *** 589,594 ****
    --- 589,596 ----
      		node->acquire();
      		if (nid)
      			nid->copyNid(node->getFullNid());
    + 		if (setIsRoot)
    + 			node->setIsRoot();
      		startElem(node, localName, (const char *)uri,
      			  (const char *)prefix, false);
      		isEmpty_ = false; // don't know if empty or not
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsEventWriter.hpp dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsEventWriter.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsEventWriter.hpp
    --- dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsEventWriter.hpp
    ***************
    *** 130,136 ****
      	void writeStartElementInternal(const unsigned char *localName,
      				       const unsigned char *prefix,
      				       const unsigned char *uri,
    ! 				       NsFullNid *nid);
      	void writeEndElementInternal();
      	void writeAttributeInternal(const unsigned char *localName,
      				    const unsigned char *prefix,
    --- 130,136 ----
      	void writeStartElementInternal(const unsigned char *localName,
      				       const unsigned char *prefix,
      				       const unsigned char *uri,
    ! 				       NsFullNid *nid, bool setIsRoot);
      	void writeEndElementInternal();
      	void writeAttributeInternal(const unsigned char *localName,
      				    const unsigned char *prefix,
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsNode.hpp dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsNode.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/nodeStore/NsNode.hpp
    --- dbxml-2.4.13/dbxml/src/dbxml/nodeStore/NsNode.hpp
    ***************
    *** 279,285 ****
      	NS_HASTEXTCHILD =  0x00000008, /**< has a text child attached */
      	NS_HASNEXT =       0x00000010, /**< has next sibling */
      	NS_HASPREV =       0x00000020, /**< has prev sibling */
    ! 	NS_NOT_USED_1 =    0x00000040, /**< NOT USED */
      	NS_LAST_IS_LAST_DESC = 0x00000080, /**< last child is a leaf */
      	NS_NAMEPREFIX =    0x00000100, /**< name has a prefix */
      	NS_HASURI =        0x00000200, /**< has a namespace URI */
    --- 279,286 ----
      	NS_HASTEXTCHILD =  0x00000008, /**< has a text child attached */
      	NS_HASNEXT =       0x00000010, /**< has next sibling */
      	NS_HASPREV =       0x00000020, /**< has prev sibling */
    ! 	NS_ISROOT =        0x00000040, /**< only set for constructed XML where node is the
    ! 					  root element */
      	NS_LAST_IS_LAST_DESC = 0x00000080, /**< last child is a leaf */
      	NS_NAMEPREFIX =    0x00000100, /**< name has a prefix */
      	NS_HASURI =        0x00000200, /**< has a namespace URI */
    ***************
    *** 373,378 ****
    --- 374,382 ----
      	bool isDoc() const {
      		return ((nd_header.nh_flags & NS_ISDOCUMENT) != 0);
      	}
    + 	bool isRoot() const {
    + 		return ((nd_header.nh_flags & NS_ISROOT) != 0);
    + 	}
      	bool hasChildElem() const {
      		return ((nd_header.nh_flags & NS_HASCHILD) != 0);
      	}
    ***************
    *** 653,658 ****
    --- 657,666 ----
      	void setIsDocument() {
      		setFlag(NS_ISDOCUMENT);
      	}
    + 
    + 	void setIsRoot() {
    + 		setFlag(NS_ISROOT);
    + 	}
      	
      	void setHasChildElem() {
      		setFlag(NS_HASCHILD);
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/Modify.hpp dbxml-2.4.13/dbxml/src/dbxml/Modify.hpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/Modify.hpp
    --- dbxml-2.4.13/dbxml/src/dbxml/Modify.hpp
    ***************
    *** 19,24 ****
    --- 19,25 ----
      #include "ReferenceCounted.hpp"
      #include "nodeStore/NsDom.hpp"
      #include "UTF8.hpp"
    + #include "QueryExpression.hpp"
      
      #include 
      
    diff -c dbxml-2.4.13.orig/dbxml/src/dbxml/RawNodeValue.cpp dbxml-2.4.13/dbxml/src/dbxml/RawNodeValue.cpp
    *** dbxml-2.4.13.orig/dbxml/src/dbxml/RawNodeValue.cpp
    --- dbxml-2.4.13/dbxml/src/dbxml/RawNodeValue.cpp
    ***************
    *** 520,528 ****
      		doc->setID(did_);
      		doc->setContainerID(cid_);
      		doc->setTransaction(GET_RESULTS().getOperationContext().txn());
    ! 		if(cid_ == 0)
      			doc->setDbMinder(GET_RESULTS().getDbMinder());
    ! 		else
      			doc->setAsNotMaterialized();
      	}
      	return xdoc_;
    --- 520,533 ----
      		doc->setID(did_);
      		doc->setContainerID(cid_);
      		doc->setTransaction(GET_RESULTS().getOperationContext().txn());
    ! 		if (cid_ == 0) {
      			doc->setDbMinder(GET_RESULTS().getDbMinder());
    ! 			//Set query constructed documents as DOM
    ! 			if(!doc->getDbMinder().isNull()) { 
    ! 				doc->getDocDb();
    ! 				doc->setContentAsNsDom(did_, doc->getCacheDatabase());
    ! 			}
    ! 		} else
      			doc->setAsNotMaterialized();
      	}
      	return xdoc_;
    diff -c dbxml-2.4.13.orig/dbxml/src/java/dbxml_java_wrap.cpp dbxml-2.4.13/dbxml/src/java/dbxml_java_wrap.cpp
    *** dbxml-2.4.13.orig/dbxml/src/java/dbxml_java_wrap.cpp
    --- dbxml-2.4.13/dbxml/src/java/dbxml_java_wrap.cpp
    ***************
    *** 464,470 ****
      	#include "../dbxml/RawNodeValue.hpp"
      	#include "../dbxml/Results.hpp"
      	#include "../dbxml/Document.hpp"
    ! 	#include "../dbxml/ScopedDbt.hpp"
      
      	using namespace DbXml;
          typedef struct
    --- 464,471 ----
      	#include "../dbxml/RawNodeValue.hpp"
      	#include "../dbxml/Results.hpp"
      	#include "../dbxml/Document.hpp"
    !         #include "../dbxml/ScopedDbt.hpp"
    ! 	#include "../dbxml/Modify.hpp"
      
      	using namespace DbXml;
          typedef struct
    ***************
    *** 1309,1316 ****
      			    break;
      		    }
      		    default:
    ! 			    if(docid != 0)
    ! 				    (*cdoc).setAsNotMaterialized();
      		    }
      		    
      		    createCPPMetaData(jenv, jdoc, cdoc);
    --- 1310,1324 ----
      			    break;
      		    }
      		    default:
    ! 			    if (docid != 0 && cid != 0)
    !                                     (*cdoc).setAsNotMaterialized();
    ! 			    else if (!(*cdoc).getDbMinder().isNull() &&
    ! 				     cid == 0) {
    ! 				    //set query constructed documents as DOM
    ! 				    (*cdoc).getDocDb();
    ! 				    (*cdoc).setContentAsNsDom(
    ! 					    docid, (*cdoc).getCacheDatabase());
    ! 			    }
      		    }
      		    
      		    createCPPMetaData(jenv, jdoc, cdoc);
    diff -ru dbxml-2.4.13-orig/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp dbxml-2.4.13/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp
    --- dbxml-2.4.13-orig/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp	2008-04-25 15:46:28.000000000 +0100
    +++ dbxml-2.4.13/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp	2008-05-16 17:10:50.000000000 +0100
    @@ -1321,7 +1321,7 @@
     		}
     	}
    
    -	return ast;
    +	return optimize(ast);
     }
    
     QueryPlanGenerator::ReverseResult QueryPlanGenerator::reverseNav(XQNav::Steps::iterator i, XQNav::Steps::iterator end, const ReverseResult &context, const QName &contextName)
    @@ -1450,7 +1450,7 @@
    
     QueryPlanGenerator::ReverseResult QueryPlanGenerator::reverseVariable(XQVariable *item, const ReverseResult &context, const QName &contextName)
     {
    -	if(!XPath2Utils::equals(item->getName(), contextName.name) ||
    +	if(context.ast != 0 || !XPath2Utils::equals(item->getName(), contextName.name) ||
     		!XPath2Utils::equals(item->getURI(), contextName.uri))
     		return ReverseResult(reverseJoin(context, item, item), contextName);
    
    diff -ru dbxml-2.4.13-orig/dbxml/src/dbxml/query/DecisionPointQP.cpp dbxml-2.4.13/dbxml/src/dbxml/query/DecisionPointQP.cpp
    --- dbxml-2.4.13-orig/dbxml/src/dbxml/query/DecisionPointQP.cpp	2008-01-09 14:49:45.000000000 +0000
    +++ dbxml-2.4.13/dbxml/src/dbxml/query/DecisionPointQP.cpp	2008-05-16 17:10:50.000000000 +0100
    @@ -19,6 +19,7 @@
     #include "../optimizer/QueryPlanOptimizer.hpp"
    
     #include 
    +#include 
    
     #include 
    
    @@ -151,8 +152,10 @@
    
     	// Save the compile time mutex, in case we need to just-in-time
     	// optimise at runtime
    -	compileTimeMinder_ = GET_CONFIGURATION(opt.getContext())->getMinder();
    -	compileTimeContext_ = opt.getContext();
    +	if(compileTimeMinder_ == 0) {
    +		compileTimeMinder_ = GET_CONFIGURATION(opt.getContext())->getMinder();
    +		compileTimeContext_ = opt.getContext();
    +	}
    
     	bool unknownContainers = true;
     	if(!qpListDone_ && opt.getPhase() == OptimizationContext::RESOLVE_INDEXES) {
    @@ -246,21 +249,43 @@
     	combinations.push_back(result);
     }
    
    +class AutoMemoryManagerReset
    +{
    +public:
    +  AutoMemoryManagerReset(StaticContext* context, XPath2MemoryManager *mm)
    +  {
    +    context_ = context;
    +    mm_ = context->getMemoryManager();
    +    context->setMemoryManager(mm);
    +  }
    +
    +  ~AutoMemoryManagerReset()
    +  {
    +    context_->setMemoryManager(mm_);
    +  }
    +
    +protected:
    +  StaticContext* context_;
    +  XPath2MemoryManager *mm_;
    +};
    +
     DecisionPointQP::ListItem *DecisionPointQP::justInTimeOptimize(int contID, DynamicContext *context)
     {
     	// **** IMPORTANT - This algorithm is very carefully arranged to avoid
     	// **** deadlocks and race-conditions. Don't rearrange things unless you
     	// **** know what you are doing!
    
    -	// Get the runtime memory manager and configuration
    -	XPath2MemoryManager *mm = context->getMemoryManager();
    +	// Get the runtime configuration
     	DbXmlConfiguration *conf = GET_CONFIGURATION(context);
    
     	// Lookup the container
     	ScopedContainer scont((Manager&)conf->getManager(), contID, /*mustExist*/true);
    
    -	// Just-in-time optimise the QueryPlan, using the runtime memory manager for thread safety
    -	QueryPlan *qp = arg_->copy(mm);
    +	// Just-in-time optimise the QueryPlan, using a temporary memory manager for thread safety
    +	XPath2MemoryManagerImpl tmpMM;
    +	AutoMemoryManagerReset resetMM(context, &tmpMM);
    +
    +	QueryPlan *qp = arg_->copy(&tmpMM);
     	try {
     		AutoDecisionPointReset reset(conf, this);
     		justInTimeOptimize(qp, scont.get(), context);