LOG.debug("left: " + nodes.getLength() + "; right: " + rightSeq.getLength());
	protected Sequence quickNodeSetCompare(Sequence contextSequence) throws XPathException {				/* TODO think about optimising fallback to NodeSetCompare() in the for loop!!!		 * At the moment when we fallback to NodeSetCompare() we are in effect throwing away any nodes		 * we have already processed in quickNodeSetCompare() and reprocessing all the nodes in NodeSetCompare().		 * Instead - Could we create a NodeCompare() (based on NodeSetCompare() code) to only compare a single node and then union the result?		 * - deliriumsky 		 */				/* TODO think about caching of results in this function...		 * also examine and check if correct (line near the end) -		 * 	 boolean canCache = contextSequence instanceof NodeSet && (getRight().getDependencies() & Dependency.VARS) == 0 && (getLeft().getDependencies() & Dependency.VARS) == 0;		 *  - deliriumsky 		 */		        // if the context sequence hasn't changed we can return a cached result		if(cached != null && cached.isValid(contextSequence))		{            if(context.getProfiler().isEnabled())            {                context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Returned cached result");            }            			return(cached.getResult());		}		      		//get the NodeSet on the left		NodeSet nodes = (NodeSet) getLeft().eval(contextSequence);		        if(!(nodes instanceof VirtualNodeSet) && nodes.isEmpty()) //nothing on the left, so nothing to do        {            return(Sequence.EMPTY_SEQUENCE);        }            //get the Sequence on the right		Sequence rightSeq = getRight().eval(contextSequence);		if(rightSeq.isEmpty())	//nothing on the right, so nothing to do		{            return(Sequence.EMPTY_SEQUENCE);		}                		//Holds the result		NodeSet result = null;				//get the type of a possible index		int indexType = nodes.getIndexType();				//See if we have a range index defined on the nodes in this sequence        //TODO : use isSubType ??? -pb	    if(indexType != Type.ITEM)	    {	    	//Get the documents from the node set			DocumentSet docs = nodes.getDocumentSet();				//Iterate through the right hand sequence			for(SequenceIterator itRightSeq = rightSeq.iterate(); itRightSeq.hasNext();)	    	{				//Get the index Key				Item key = itRightSeq.nextItem().atomize();								//if key has truncation convert to string		        if(truncation != Constants.TRUNC_NONE)		        {		        	//truncation is only possible on strings		        	key = key.convertTo(Type.STRING);		        }		        //else if key is not the same type as the index                //TODO : use isSubType ??? -pb		        else if(key.getType() != indexType)		        {		        	//try and convert the key to the index type 	            	try					{	            		key = key.convertTo(indexType);					}	            	catch(XPathException xpe)					{			        	//Could not convert the key to a suitable type for the index, fallback to nodeSetCompare()		                if(context.getProfiler().isEnabled())		                {		                    context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "nodeSetCompare");		                }		                			            return nodeSetCompare(nodes, contextSequence);					}		        }		        		        // If key implements org.exist.storage.Indexable, we can use the index		        if(key instanceof Indexable && Type.subTypeOf(key.getType(), indexType))		        {		        	if(truncation == Constants.TRUNC_NONE)		        	{			        	//key without truncation, find key	                    context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index to find key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");	                    	                    if(result == null)	//if first iteration	                    {	                    	result = context.getBroker().getValueIndex().find(relation, docs, nodes, (Indexable)key);	                    }	                    else	                    {	                    	result = result.union(context.getBroker().getValueIndex().find(relation, docs, nodes, (Indexable)key));	                    }	                }		        	else		        	{			        	//key with truncation, match key	                    context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index to match key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");						try						{														if(result == null) //if first iteration							{								result = context.getBroker().getValueIndex().match(docs, nodes, key.getStringValue().replace('%', '*'), DBBroker.MATCH_WILDCARDS);							}							else							{								result = result.union(context.getBroker().getValueIndex().match(docs, nodes, key.getStringValue().replace('%', '*'), DBBroker.MATCH_WILDCARDS));							}						}						catch (EXistException e)						{							throw new XPathException(getASTNode(), e.getMessage(), e);						}					}		        }		        else		        {		        	//the datatype of our key does not		        	//implement org.exist.storage.Indexable or is not of the correct type	                if(context.getProfiler().isEnabled())	                {	                    context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "nodeSetCompare");	                }                    return(nodeSetCompare(nodes, contextSequence));	            }        		//removed by Pierrick Brihaye        //REMOVED : a *general* comparison should not be dependant of the settings of a fulltext index        /*	    } else if (key.getType() == Type.ATOMIC || Type.subTypeOf(key.getType(), Type.STRING)) {	        if (!nodes.hasMixedContent() && relation == Constants.EQ 	            && nodes.hasTextIndex()) {		        // we can use the fulltext index		        String cmp = rightSeq.getStringValue();		        if(cmp.length() < NativeTextEngine.MAX_WORD_LENGTH)		            nodes = useFulltextIndex(cmp, nodes, docs);		        		        // now compare the input node set to the search expression				result =					context.getBroker().getNodesEqualTo(nodes, docs, relation, truncation, cmp, getCollator(contextSequence));				} else {			    			    // no usable index found. Fall back to a sequential scan of the nodes			    result =					context.getBroker().getNodesEqualTo(nodes, docs, relation, truncation, rightSeq.getStringValue(), 					        getCollator(contextSequence));			}        */	    	/* end */	}		}	    else	    {	    	//no range index defined on the nodes in this sequence, so fallback to nodeSetCompare            if(context.getProfiler().isEnabled())            {                context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "nodeSetCompare");            }            return(nodeSetCompare(nodes, contextSequence));		}				// can this result be cached? Don't cache if the result depends on local variables.	    boolean canCache = contextSequence instanceof NodeSet && 	    	!Dependency.dependsOn(getLeft(), Dependency.VARS) && 	    	!Dependency.dependsOn(getRight(), Dependency.VARS);		if(canCache)		{			cached = new CachedResult((NodeSet)contextSequence, result);		}				//return the result of the range index lookup(s) :-)		return result;	}