Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.vxquery.xmlquery.translator; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.namespace.QName; import org.apache.commons.lang3.mutable.Mutable; import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.tuple.Pair; import org.apache.vxquery.compiler.CompilerControlBlock; import org.apache.vxquery.compiler.algebricks.VXQueryConstantValue; import org.apache.vxquery.context.StaticContext; import org.apache.vxquery.context.StaticContextImpl; import org.apache.vxquery.context.ThinStaticContextImpl; import org.apache.vxquery.context.XQueryVariable; import org.apache.vxquery.datamodel.builders.atomic.StringValueBuilder; import org.apache.vxquery.datamodel.values.ValueTag; import org.apache.vxquery.exceptions.ErrorCode; import org.apache.vxquery.exceptions.SystemException; import org.apache.vxquery.functions.BuiltinFunctions; import org.apache.vxquery.functions.BuiltinOperators; import org.apache.vxquery.functions.ExternalFunction; import org.apache.vxquery.functions.Function; import org.apache.vxquery.functions.Signature; import org.apache.vxquery.functions.UserDefinedXQueryFunction; import org.apache.vxquery.metadata.QueryResultSetDataSink; import org.apache.vxquery.runtime.functions.cast.CastToDecimalOperation; import org.apache.vxquery.types.AnyItemType; import org.apache.vxquery.types.AnyNodeType; import org.apache.vxquery.types.AnyType; import org.apache.vxquery.types.AtomicType; import org.apache.vxquery.types.AttributeType; import org.apache.vxquery.types.BuiltinTypeConstants; import org.apache.vxquery.types.BuiltinTypeRegistry; import org.apache.vxquery.types.CommentType; import org.apache.vxquery.types.DocumentType; import org.apache.vxquery.types.ElementType; import org.apache.vxquery.types.EmptySequenceType; import org.apache.vxquery.types.ItemType; import org.apache.vxquery.types.NameTest; import org.apache.vxquery.types.NodeType; import org.apache.vxquery.types.ProcessingInstructionType; import org.apache.vxquery.types.Quantifier; import org.apache.vxquery.types.SchemaType; import org.apache.vxquery.types.SequenceType; import org.apache.vxquery.types.TextType; import org.apache.vxquery.types.TypeUtils; import org.apache.vxquery.xmlquery.ast.ASTNode; import org.apache.vxquery.xmlquery.ast.ASTTag; import org.apache.vxquery.xmlquery.ast.AtomicTypeNode; import org.apache.vxquery.xmlquery.ast.AttributeTestNode; import org.apache.vxquery.xmlquery.ast.AxisStepNode; import org.apache.vxquery.xmlquery.ast.BaseUriDeclNode; import org.apache.vxquery.xmlquery.ast.BoundarySpaceDeclNode; import org.apache.vxquery.xmlquery.ast.CDataSectionNode; import org.apache.vxquery.xmlquery.ast.ComputedAttributeConstructorNode; import org.apache.vxquery.xmlquery.ast.ComputedCommentConstructorNode; import org.apache.vxquery.xmlquery.ast.ComputedDocumentConstructorNode; import org.apache.vxquery.xmlquery.ast.ComputedElementConstructorNode; import org.apache.vxquery.xmlquery.ast.ComputedPIConstructorNode; import org.apache.vxquery.xmlquery.ast.ComputedTextConstructorNode; import org.apache.vxquery.xmlquery.ast.ConstructionDeclNode; import org.apache.vxquery.xmlquery.ast.ContentCharsNode; import org.apache.vxquery.xmlquery.ast.CopyNamespacesDeclNode; import org.apache.vxquery.xmlquery.ast.DefaultCollationDeclNode; import org.apache.vxquery.xmlquery.ast.DefaultElementNamespaceDeclNode; import org.apache.vxquery.xmlquery.ast.DefaultFunctionNamespaceDeclNode; import org.apache.vxquery.xmlquery.ast.DirectAttributeConstructorNode; import org.apache.vxquery.xmlquery.ast.DirectCommentConstructorNode; import org.apache.vxquery.xmlquery.ast.DirectElementConstructorNode; import org.apache.vxquery.xmlquery.ast.DirectPIConstructorNode; import org.apache.vxquery.xmlquery.ast.DocumentTestNode; import org.apache.vxquery.xmlquery.ast.ElementTestNode; import org.apache.vxquery.xmlquery.ast.EmptyOrderDeclNode; import org.apache.vxquery.xmlquery.ast.EnclosedExprNode; import org.apache.vxquery.xmlquery.ast.ExprNode; import org.apache.vxquery.xmlquery.ast.ExtensionExprNode; import org.apache.vxquery.xmlquery.ast.FLWORClauseNode; import org.apache.vxquery.xmlquery.ast.FLWORExprNode; import org.apache.vxquery.xmlquery.ast.FilterExprNode; import org.apache.vxquery.xmlquery.ast.ForClauseNode; import org.apache.vxquery.xmlquery.ast.ForVarDeclNode; import org.apache.vxquery.xmlquery.ast.FunctionDeclNode; import org.apache.vxquery.xmlquery.ast.FunctionExprNode; import org.apache.vxquery.xmlquery.ast.IfExprNode; import org.apache.vxquery.xmlquery.ast.InfixExprNode; import org.apache.vxquery.xmlquery.ast.InfixExprNode.InfixOperator; import org.apache.vxquery.xmlquery.ast.LetClauseNode; import org.apache.vxquery.xmlquery.ast.LetVarDeclNode; import org.apache.vxquery.xmlquery.ast.LibraryModuleNode; import org.apache.vxquery.xmlquery.ast.LiteralNode; import org.apache.vxquery.xmlquery.ast.MainModuleNode; import org.apache.vxquery.xmlquery.ast.ModuleImportNode; import org.apache.vxquery.xmlquery.ast.ModuleNode; import org.apache.vxquery.xmlquery.ast.NCNameNode; import org.apache.vxquery.xmlquery.ast.NameTestNode; import org.apache.vxquery.xmlquery.ast.NamespaceDeclNode; import org.apache.vxquery.xmlquery.ast.OptionDeclNode; import org.apache.vxquery.xmlquery.ast.OrderSpecNode; import org.apache.vxquery.xmlquery.ast.OrderbyClauseNode; import org.apache.vxquery.xmlquery.ast.OrderedExprNode; import org.apache.vxquery.xmlquery.ast.OrderingModeDeclNode; import org.apache.vxquery.xmlquery.ast.PITestNode; import org.apache.vxquery.xmlquery.ast.ParamNode; import org.apache.vxquery.xmlquery.ast.ParenthesizedExprNode; import org.apache.vxquery.xmlquery.ast.PathExprNode; import org.apache.vxquery.xmlquery.ast.PrologNode; import org.apache.vxquery.xmlquery.ast.QNameNode; import org.apache.vxquery.xmlquery.ast.QuantifiedExprNode; import org.apache.vxquery.xmlquery.ast.QuantifiedExprNode.QuantifierType; import org.apache.vxquery.xmlquery.ast.QuantifiedVarDeclNode; import org.apache.vxquery.xmlquery.ast.QueryBodyNode; import org.apache.vxquery.xmlquery.ast.RelativePathExprNode; import org.apache.vxquery.xmlquery.ast.SchemaImportNode; import org.apache.vxquery.xmlquery.ast.SequenceTypeNode; import org.apache.vxquery.xmlquery.ast.SingleTypeNode; import org.apache.vxquery.xmlquery.ast.TypeDeclNode; import org.apache.vxquery.xmlquery.ast.TypeExprNode; import org.apache.vxquery.xmlquery.ast.UnaryExprNode; import org.apache.vxquery.xmlquery.ast.UnorderedExprNode; import org.apache.vxquery.xmlquery.ast.ValidateExprNode; import org.apache.vxquery.xmlquery.ast.VarDeclNode; import org.apache.vxquery.xmlquery.ast.VarRefNode; import org.apache.vxquery.xmlquery.ast.VersionDeclNode; import org.apache.vxquery.xmlquery.ast.WhereClauseNode; import org.apache.vxquery.xmlquery.query.Module; import org.apache.vxquery.xmlquery.query.ModuleType; import org.apache.vxquery.xmlquery.query.XMLQueryCompilerConstants; import org.apache.vxquery.xmlquery.query.XQueryConstants; import org.apache.vxquery.xmlquery.query.XQueryConstants.PathType; import org.apache.vxquery.xmlquery.query.XQueryConstants.TypeQuantifier; import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan; import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag; import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.DistributeResultOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.OrderOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SelectOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl; import edu.uci.ics.hyracks.data.std.primitive.DoublePointable; import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage; import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream; public class XMLQueryTranslator { private static final Pattern UNQUOTER = Pattern .compile("(<)|(>)|(')|(&)|(")|(\"\")|('')|(&#\\d+;)|(&#x(?:[A-Fa-f0-9])+;)"); private final CompilerControlBlock ccb; private final StaticContext rootCtx; private StaticContext moduleCtx; private IVariableScope rootVarScope; private StaticContext currCtx; private int varCounter; private final ByteArrayAccessibleOutputStream baaos; private final DataOutput dOut; private final StringValueBuilder stringVB; public XMLQueryTranslator(CompilerControlBlock ccb) { this.ccb = ccb; varCounter = 0; rootCtx = ccb.getStaticContext(); baaos = new ByteArrayAccessibleOutputStream(); dOut = new DataOutputStream(baaos); stringVB = new StringValueBuilder(); } private void pushContext() { currCtx = new ThinStaticContextImpl(currCtx); } private void popContext() { currCtx = currCtx.getParent(); } public Module translateModule(ModuleNode moduleNode) throws SystemException { Module module = new Module(); moduleCtx = new StaticContextImpl(rootCtx); moduleCtx.registerVariable(new XQueryVariable(XMLQueryCompilerConstants.DOT_VAR_NAME, SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_ONE), newLogicalVariable())); rootVarScope = new RootVariableScope(); currCtx = moduleCtx; module.setModuleContext(moduleCtx); module.setCompilerControlBlock(ccb); VersionDeclNode ver = moduleNode.getVersion(); if (ver != null) { if (!"1.0".equals(ver.getVersion())) { throw new SystemException(ErrorCode.XQST0031, ver.getSourceLocation()); } } switch (moduleNode.getTag()) { case LIBRARY_MODULE: { module.setModuleType(ModuleType.LIBRARY); LibraryModuleNode lmNode = (LibraryModuleNode) moduleNode; String prefix = lmNode.getModuleDecl().getPrefix(); String uri = unquote(lmNode.getModuleDecl().getTargetNS()); if (prefix != null) { currCtx.registerNamespaceUri(prefix, uri); } module.setNamespaceUri(uri); break; } case MAIN_MODULE: { module.setModuleType(ModuleType.MAIN); break; } default: throw new IllegalStateException("Unknown module type: " + moduleNode.getTag()); } PrologNode prologNode = moduleNode.getProlog(); parsePrologPass1(prologNode); parsePrologPass2(prologNode); ILogicalPlan plan = null; switch (moduleNode.getTag()) { case LIBRARY_MODULE: throw new SystemException(ErrorCode.TODO); case MAIN_MODULE: plan = translateMainModule((MainModuleNode) moduleNode); } module.setBody(plan); return module; } @SuppressWarnings("unchecked") private void parsePrologPass1(PrologNode prologNode) throws SystemException { if (prologNode != null) { List<ASTNode> decls = prologNode.getDecls(); for (ASTNode d : decls) { switch (d.getTag()) { case DEFAULT_ELEMENT_NAMESPACE_DECLARATION: { DefaultElementNamespaceDeclNode node = (DefaultElementNamespaceDeclNode) d; moduleCtx.setDefaultElementNamespaceUri(node.getUri()); break; } case DEFAULT_FUNCTION_NAMESPACE_DECLARATION: { DefaultFunctionNamespaceDeclNode node = (DefaultFunctionNamespaceDeclNode) d; moduleCtx.setDefaultFunctionNamespaceUri(node.getUri()); break; } case BOUNDARY_SPACE_DECLARATION: { BoundarySpaceDeclNode node = (BoundarySpaceDeclNode) d; moduleCtx.setBoundarySpaceProperty(node.getMode()); break; } case DEFAULT_COLLATION_DECLARATION: { DefaultCollationDeclNode node = (DefaultCollationDeclNode) d; moduleCtx.setDefaultCollation(node.getCollation()); break; } case BASE_URI_DECLARATION: { BaseUriDeclNode node = (BaseUriDeclNode) d; moduleCtx.setBaseUri(node.getUri()); break; } case CONSTRUCTION_DECLARATION: { ConstructionDeclNode node = (ConstructionDeclNode) d; moduleCtx.setConstructionModeProperty(node.getMode()); break; } case ORDERING_MODE_DECLARATION: { OrderingModeDeclNode node = (OrderingModeDeclNode) d; moduleCtx.setOrderingModeProperty(node.getMode()); break; } case EMPTY_ORDER_DECLARATION: { EmptyOrderDeclNode node = (EmptyOrderDeclNode) d; moduleCtx.setEmptyOrderProperty(node.getMode()); break; } case COPY_NAMESPACES_DECLARATION: { CopyNamespacesDeclNode node = (CopyNamespacesDeclNode) d; moduleCtx.setCopyNamespacesModeProperty(node.getMode()); break; } case NAMESPACE_DECLARATION: { NamespaceDeclNode node = (NamespaceDeclNode) d; moduleCtx.registerNamespaceUri(node.getPrefix(), unquote(node.getUri())); break; } case SCHEMA_IMPORT: { SchemaImportNode node = (SchemaImportNode) d; if (node.isDefaultElementNamespace()) { moduleCtx.setDefaultElementNamespaceUri(node.getTargetNS()); } if (node.getPrefix() != null) { moduleCtx.registerNamespaceUri(node.getPrefix(), unquote(node.getTargetNS())); } moduleCtx.registerSchemaImport(node.getTargetNS(), node.getLocations()); break; } case MODULE_IMPORT: { ModuleImportNode node = (ModuleImportNode) d; if (node.getPrefix() != null) { moduleCtx.registerNamespaceUri(node.getPrefix(), unquote(node.getTargetNS())); } moduleCtx.registerModuleImport(node.getTargetNS(), node.getLocations()); break; } case VARIABLE_DECLARATION: { VarDeclNode node = (VarDeclNode) d; QName name = createQName(node.getName()); SequenceType type = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR); if (node.getType() != null) { type = createSequenceType(node.getType()); } LogicalVariable lVar = newLogicalVariable(); XQueryVariable var = new XQueryVariable(name, type, lVar); moduleCtx.registerVariable(var); break; } case FUNCTION_DECLARATION: { FunctionDeclNode node = (FunctionDeclNode) d; boolean external = node.getBody() == null; QName name = createQName(node.getName(), moduleCtx.getDefaultFunctionNamespaceUri()); String uri = name.getNamespaceURI(); if (XQueryConstants.FN_NSURI.equals(uri) || XQueryConstants.XS_NSURI.equals(uri) || XQueryConstants.XSI_NSURI.equals(uri) || XQueryConstants.XML_NSURI.equals(uri)) { throw new SystemException(ErrorCode.XQST0045, node.getSourceLocation()); } SequenceType rType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR); if (node.getReturnType() != null) { rType = createSequenceType(node.getReturnType()); } Pair<QName, SequenceType> paramTypes[] = new Pair[node.getParameters().size()]; for (int i = 0; i < paramTypes.length; ++i) { ParamNode pNode = node.getParameters().get(i); QName pName = createQName(pNode.getName()); SequenceType pType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR); if (pNode.getType() != null) { pType = createSequenceType(pNode.getType()); } paramTypes[i] = Pair.<QName, SequenceType>of(pName, pType); } Signature sign = new Signature(rType, paramTypes); Function f = external ? new ExternalFunction(name, sign) : new UserDefinedXQueryFunction(name, sign, null); moduleCtx.registerFunction(f); break; } case OPTION_DECLARATION: { OptionDeclNode node = (OptionDeclNode) d; QName name = createQName(node.getName()); moduleCtx.setOption(name, node.getValue()); break; } default: throw new IllegalStateException("Unknown node: " + d.getTag()); } } } } private void parsePrologPass2(PrologNode prologNode) throws SystemException { if (prologNode != null) { List<ASTNode> decls = prologNode.getDecls(); for (ASTNode d : decls) { switch (d.getTag()) { case VARIABLE_DECLARATION: { VarDeclNode node = (VarDeclNode) d; // TODO Support Global variables break; } case FUNCTION_DECLARATION: { FunctionDeclNode node = (FunctionDeclNode) d; boolean external = node.getBody() == null; if (!external) { QName name = createQName(node.getName(), moduleCtx.getDefaultFunctionNamespaceUri()); int arity = node.getParameters().size(); UserDefinedXQueryFunction f = (UserDefinedXQueryFunction) moduleCtx.lookupFunction(name, arity); Signature sign = f.getSignature(); TranslationContext tCtx = new TranslationContext(null, new EmptyTupleSourceOperator()); XQueryVariable[] params = new XQueryVariable[arity]; for (int i = 0; i < arity; ++i) { ParamNode pNode = node.getParameters().get(i); QName pName = createQName(pNode.getName()); SequenceType pType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR); if (pNode.getType() != null) { pType = createSequenceType(pNode.getType()); } XQueryVariable pVar = new XQueryVariable(pName, pType, newLogicalVariable()); params[i] = pVar; tCtx.varScope.registerVariable(pVar); } f.setParameters(params); LogicalVariable var = translateExpression(node.getBody(), tCtx); ILogicalExpression expr = treat(vre(var), sign.getReturnType()); var = createAssignment(expr, tCtx); f.setBody(new ALogicalPlanImpl(mutable(tCtx.op))); } break; } } } } } private SequenceType createSequenceType(ASTNode type) throws SystemException { switch (type.getTag()) { case TYPE_DECLARATION: { TypeDeclNode tDecl = (TypeDeclNode) type; return createSequenceType(tDecl.getType()); } case SEQUENCE_TYPE: { SequenceTypeNode sType = (SequenceTypeNode) type; if (sType.getItemType() == null) { return SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR); } TypeQuantifier tq = sType.getQuantifier(); Quantifier q = Quantifier.QUANT_ONE; if (tq != null) { switch (tq) { case QUANT_QUESTION: q = Quantifier.QUANT_QUESTION; break; case QUANT_PLUS: q = Quantifier.QUANT_PLUS; break; case QUANT_STAR: q = Quantifier.QUANT_STAR; break; } } ItemType iType = createItemType(sType.getItemType()); return SequenceType.create(iType, q); } case EMPTY_SEQUENCE_TYPE: { return SequenceType.create(EmptySequenceType.INSTANCE, Quantifier.QUANT_ZERO); } case SINGLE_TYPE: { SingleTypeNode stNode = (SingleTypeNode) type; ItemType iType = createItemType(stNode.getAtomicType()); return SequenceType.create(iType, stNode.isOptional() ? Quantifier.QUANT_QUESTION : Quantifier.QUANT_ONE); } default: throw new IllegalStateException("Unknown node: " + type.getTag()); } } private ItemType createItemType(ASTNode itemType) throws SystemException { switch (itemType.getTag()) { case ITEM_TYPE: return AnyItemType.INSTANCE; case ATOMIC_TYPE: { AtomicTypeNode atNode = (AtomicTypeNode) itemType; QName tName = createQName(atNode.getName()); SchemaType sType = moduleCtx.lookupSchemaType(tName); if (sType == null || !sType.isAtomicType()) { throw new SystemException(ErrorCode.XPST0051, atNode.getSourceLocation()); } return (ItemType) sType; } case ANY_NODE_TEST: return AnyNodeType.INSTANCE; case DOCUMENT_TEST: { DocumentTestNode dt = (DocumentTestNode) itemType; if (dt.getElementTest() == null) { return DocumentType.ANYDOCUMENT; } ElementType eType = (ElementType) createItemType(dt.getElementTest()); return new DocumentType(eType); } case TEXT_TEST: return TextType.INSTANCE; case COMMENT_TEST: return CommentType.INSTANCE; case PI_TEST: { PITestNode pit = (PITestNode) itemType; if (pit.getTarget() == null) { return ProcessingInstructionType.ANYPI; } return new ProcessingInstructionType(createUTF8String(pit.getTarget())); } case ATTRIBUTE_TEST: { AttributeTestNode at = (AttributeTestNode) itemType; if (at.getNameTest() == null) { return AttributeType.ANYATTRIBUTE; } NameTestNode ntNode = at.getNameTest(); NameTest nt = NameTest.STAR_NAMETEST; if (ntNode.getPrefix() == null && ntNode.getLocalName() == null) { if (at.getTypeName() == null) { return AttributeType.ANYATTRIBUTE; } } else { String uri; if (!"".equals(ntNode.getPrefix())) { uri = currCtx.lookupNamespaceUri(ntNode.getPrefix()); if (uri == null) { throw new SystemException(ErrorCode.XPST0081, ntNode.getSourceLocation()); } } else { uri = ""; } nt = new NameTest(createUTF8String(uri), createUTF8String(ntNode.getLocalName())); } SchemaType cType = BuiltinTypeRegistry.XS_ANY_ATOMIC; if (at.getTypeName() != null) { cType = moduleCtx.lookupSchemaType(createQName(at.getTypeName())); if (cType == null) { throw new SystemException(ErrorCode.XPST0051, at.getSourceLocation()); } } return new AttributeType(nt, cType); } case SCHEMA_ATTRIBUTE_TEST: { throw new UnsupportedOperationException("schema-attribute(...) is not supported"); } case ELEMENT_TEST: { ElementTestNode et = (ElementTestNode) itemType; if (et.getNameTest() == null) { return ElementType.ANYELEMENT; } NameTestNode ntNode = et.getNameTest(); NameTest nt = NameTest.STAR_NAMETEST; if (ntNode.getPrefix() == null && ntNode.getLocalName() == null) { if (et.getTypeName() == null) { return ElementType.ANYELEMENT; } } else { String uri; if (!"".equals(ntNode.getPrefix())) { uri = currCtx.lookupNamespaceUri(ntNode.getPrefix()); if (uri == null) { throw new SystemException(ErrorCode.XPST0081, ntNode.getSourceLocation()); } } else { uri = ""; } nt = new NameTest(createUTF8String(uri), createUTF8String(ntNode.getLocalName())); } SchemaType cType = AnyType.INSTANCE; if (et.getTypeName() != null) { cType = moduleCtx.lookupSchemaType(createQName(et.getTypeName())); if (cType == null) { throw new SystemException(ErrorCode.XPST0051, et.getSourceLocation()); } } return new ElementType(nt, cType, et.isNillable()); } case SCHEMA_ELEMENT_TEST: { throw new UnsupportedOperationException("schema-element(...) is not supported"); } default: throw new IllegalStateException("Unknown node: " + itemType.getTag()); } } private byte[] createUTF8String(String str) { ArrayBackedValueStorage abvs = new ArrayBackedValueStorage(); StringValueBuilder svb = new StringValueBuilder(); try { svb.write(str, abvs.getDataOutput()); } catch (IOException e) { throw new IllegalStateException(e); } return Arrays.copyOf(abvs.getByteArray(), abvs.getLength()); } private ILogicalPlan translateMainModule(MainModuleNode moduleNode) throws SystemException { QueryBodyNode qbn = moduleNode.getQueryBody(); ASTNode queryBody = qbn.getExpression(); TranslationContext tCtx = new TranslationContext(null, new EmptyTupleSourceOperator()); LogicalVariable lVar = translateExpression(queryBody, tCtx); LogicalVariable iLVar = newLogicalVariable(); UnnestOperator unnest = new UnnestOperator(iLVar, mutable(ufce(BuiltinOperators.ITERATE, vre(lVar)))); unnest.getInputs().add(mutable(tCtx.op)); List<Mutable<ILogicalExpression>> exprs = new ArrayList<Mutable<ILogicalExpression>>(); exprs.add(mutable(vre(iLVar))); QueryResultSetDataSink sink = new QueryResultSetDataSink(ccb.getResultSetId(), null); DistributeResultOperator op = new DistributeResultOperator(exprs, sink); op.getInputs().add(mutable(unnest)); ALogicalPlanImpl lp = new ALogicalPlanImpl(mutable(op)); return lp; } private LogicalVariable translateExpression(ASTNode value, TranslationContext tCtx) throws SystemException { switch (value.getTag()) { case EXPRESSION: { ExprNode node = (ExprNode) value; return translateExprNode(tCtx, node); } case UNARY_EXPRESSION: { UnaryExprNode ueNode = (UnaryExprNode) value; return translateUnaryExprNode(tCtx, ueNode); } case INFIX_EXPRESSION: { InfixExprNode ie = (InfixExprNode) value; return translateInfixExprNode(tCtx, ie); } case ENCLOSED_EXPRESSION: { EnclosedExprNode ee = (EnclosedExprNode) value; return translateEnclosedExprNode(tCtx, ee); } case PATH_EXPRESSION: return translatePathExpr((PathExprNode) value, tCtx); case FUNCTION_EXPRESSION: { FunctionExprNode fnNode = (FunctionExprNode) value; return translateFunctionExprNode(tCtx, fnNode); } case TYPE_EXPRESSION: { TypeExprNode teNode = (TypeExprNode) value; return translateTypeExprNode(tCtx, teNode); } case EXTENSION_EXPRESSION: { ExtensionExprNode eNode = (ExtensionExprNode) value; return translateExtensionExprNode(tCtx, eNode); } case PARENTHESIZED_EXPRESSION: { ParenthesizedExprNode peNode = (ParenthesizedExprNode) value; return translateParenthisizedExprNode(tCtx, peNode); } case LITERAL: { LiteralNode lNode = (LiteralNode) value; return translateLiteralNode(tCtx, lNode); } case DIRECT_PI_CONSTRUCTOR: { DirectPIConstructorNode dpicNode = (DirectPIConstructorNode) value; return translateDirectPIConstructorNode(tCtx, dpicNode); } case DIRECT_COMMENT_CONSTRUCTOR: { DirectCommentConstructorNode dccNode = (DirectCommentConstructorNode) value; return translateDirectCommentConstructorNode(tCtx, dccNode); } case DIRECT_ELEMENT_CONSTRUCTOR: { DirectElementConstructorNode decNode = (DirectElementConstructorNode) value; return translateDirectElementConstructorNode(tCtx, decNode); } case DIRECT_ATTRIBUTE_CONSTRUCTOR: { DirectAttributeConstructorNode dacNode = (DirectAttributeConstructorNode) value; return translateDirectAttributeConstructorNode(tCtx, dacNode); } case CONTEXT_ITEM: return tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME).getLogicalVariable(); case IF_EXPRESSION: { IfExprNode ieNode = (IfExprNode) value; return translateIfExprNode(tCtx, ieNode); } case VARIABLE_REFERENCE: { VarRefNode vrNode = (VarRefNode) value; return translateVarRefNode(tCtx, vrNode); } case FLWOR_EXPRESSION: { FLWORExprNode fNode = (FLWORExprNode) value; return translateFLWORExprNode(tCtx, fNode); } case QUANTIFIED_EXPRESSION: { QuantifiedExprNode qeNode = (QuantifiedExprNode) value; return translateQuantifiedExprNode(tCtx, qeNode); } /* case TYPESWITCH_EXPRESSION: { TypeswitchExprNode teNode = (TypeswitchExprNode) value; Expression sExpr = translateExpression(teNode.getSwitchExpr()); ForLetVariable tVar = new ForLetVariable(VarTag.LET, createVarName(), sExpr); tVar.setDeclaredStaticType(SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR)); pushVariableScope(); varScope.registerVariable(tVar); List<TypeswitchExpression.Case> cases = new ArrayList<TypeswitchExpression.Case>(); for (CaseClauseNode ccNode : teNode.getCaseClauses()) { SequenceType type = createSequenceType(ccNode.getType()); ForLetVariable caseVar = null; pushVariableScope(); if (ccNode.getCaseVar() != null) { caseVar = new ForLetVariable(VarTag.LET, createQName(ccNode.getCaseVar()), new TreatExpression( currCtx, new VariableReferenceExpression(currCtx, tVar), type)); caseVar.setDeclaredStaticType(type); varScope.registerVariable(caseVar); } Expression cExpr = translateExpression(ccNode.getValueExpr()); TypeswitchExpression.Case c = new TypeswitchExpression.Case(caseVar, type, cExpr); cases.add(c); popVariableScope(); } Expression dExpr = translateExpression(teNode.getDefaultClause()); popVariableScope(); return new TypeswitchExpression(currCtx, tVar, cases, dExpr); } */ case COMPUTED_TEXT_CONSTRUCTOR: { ComputedTextConstructorNode cNode = (ComputedTextConstructorNode) value; return translateComputedTextConstructorNode(tCtx, cNode); } case COMPUTED_PI_CONSTRUCTOR: { ComputedPIConstructorNode cNode = (ComputedPIConstructorNode) value; return translateComputedPIConstructorNode(tCtx, cNode); } case COMPUTED_COMMENT_CONSTRUCTOR: { ComputedCommentConstructorNode cNode = (ComputedCommentConstructorNode) value; return translateComputedCommentConstructorNode(tCtx, cNode); } case COMPUTED_DOCUMENT_CONSTRUCTOR: { ComputedDocumentConstructorNode cNode = (ComputedDocumentConstructorNode) value; return translateComputedDocumentConstructorNode(tCtx, cNode); } case COMPUTED_ELEMENT_CONSTRUCTOR: { ComputedElementConstructorNode cNode = (ComputedElementConstructorNode) value; return translateComputedElementConstructorNode(tCtx, cNode); } case COMPUTED_ATTRIBUTE_CONSTRUCTOR: { ComputedAttributeConstructorNode cNode = (ComputedAttributeConstructorNode) value; return translateComputedAttributeConstructorNode(tCtx, cNode); } case QNAME: { QNameNode qnNode = (QNameNode) value; return translateQNameNode(tCtx, qnNode); } case NCNAME: { NCNameNode ncnNode = (NCNameNode) value; return translateNCNameNode(tCtx, ncnNode); } case CDATA_SECTION: { CDataSectionNode cdsNode = (CDataSectionNode) value; return translateCDataSectionNode(tCtx, cdsNode); } case ORDERED_EXPRESSION: { OrderedExprNode oeNode = (OrderedExprNode) value; return translateOrderedExprNode(tCtx, oeNode); } case UNORDERED_EXPRESSION: { UnorderedExprNode ueNode = (UnorderedExprNode) value; return translateUnorderedExprNode(tCtx, ueNode); } case VALIDATE_EXPRESSION: { ValidateExprNode vNode = (ValidateExprNode) value; return translateValidateExprNode(tCtx, vNode); } default: throw new IllegalStateException("Unknown node: " + value.getTag()); } } private LogicalVariable translateQuantifiedExprNode(TranslationContext tCtx, QuantifiedExprNode qeNode) throws SystemException { tCtx = tCtx.pushContext(); int pushCount = 0; for (QuantifiedVarDeclNode qvdNode : qeNode.getVariables()) { ILogicalExpression seq = vre(translateExpression(qvdNode.getSequence(), tCtx)); tCtx.pushVariableScope(); LogicalVariable forLVar = newLogicalVariable(); UnnestOperator unnest = new UnnestOperator(forLVar, mutable(ufce(BuiltinOperators.ITERATE, seq))); SequenceType forVarType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_ONE); if (qvdNode.getType() != null) { forVarType = createSequenceType(qvdNode.getType()); } XQueryVariable forVar = new XQueryVariable(createQName(qvdNode.getVariable()), forVarType, forLVar); tCtx.varScope.registerVariable(forVar); unnest.getInputs().add(mutable(tCtx.op)); tCtx.op = unnest; ++pushCount; } ILogicalExpression satExpr = sfce(BuiltinFunctions.FN_BOOLEAN_1, vre(translateExpression(qeNode.getSatisfiesExpr(), tCtx))); if (qeNode.getQuant() == QuantifierType.EVERY) { satExpr = sfce(BuiltinFunctions.FN_NOT_1, satExpr); } SelectOperator select = new SelectOperator(mutable(satExpr), false, null); select.getInputs().add(mutable(tCtx.op)); tCtx.op = select; List<LogicalVariable> vars = new ArrayList<LogicalVariable>(); List<Mutable<ILogicalExpression>> exprs = new ArrayList<Mutable<ILogicalExpression>>(); LogicalVariable var = newLogicalVariable(); vars.add(var); exprs.add(mutable(afce(BuiltinOperators.SEQUENCE, false, ce(SequenceType.create(BuiltinTypeRegistry.XS_BOOLEAN, Quantifier.QUANT_ONE), Boolean.TRUE)))); AggregateOperator aop = new AggregateOperator(vars, exprs); aop.getInputs().add(mutable(tCtx.op)); tCtx.op = aop; for (int i = 0; i < pushCount; ++i) { tCtx.popVariableScope(); } tCtx = tCtx.popContext(); LogicalVariable lVar = createAssignment( sfce(qeNode.getQuant() == QuantifierType.EVERY ? BuiltinFunctions.FN_EMPTY_1 : BuiltinFunctions.FN_EXISTS_1, vre(var)), tCtx); return lVar; } private LogicalVariable translateUnorderedExprNode(TranslationContext tCtx, UnorderedExprNode ueNode) throws SystemException { LogicalVariable lVar = createAssignment( sfce(BuiltinOperators.UNORDERED, vre(translateExpression(ueNode.getExpr(), tCtx))), tCtx); return lVar; } private LogicalVariable translateOrderedExprNode(TranslationContext tCtx, OrderedExprNode oeNode) throws SystemException { LogicalVariable lVar = createAssignment( sfce(BuiltinOperators.ORDERED, vre(translateExpression(oeNode.getExpr(), tCtx))), tCtx); return lVar; } private LogicalVariable translateCDataSectionNode(TranslationContext tCtx, CDataSectionNode cdsNode) throws SystemException { LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.TEXT_CONSTRUCTOR, ce(SequenceType.create(BuiltinTypeRegistry.XS_UNTYPED_ATOMIC, Quantifier.QUANT_ONE), cdsNode.getContent())), tCtx); return lVar; } private LogicalVariable translateNCNameNode(TranslationContext tCtx, NCNameNode ncnNode) throws SystemException { LogicalVariable lVar = createAssignment( ce(SequenceType.create(BuiltinTypeRegistry.XS_STRING, Quantifier.QUANT_ONE), ncnNode.getName()), tCtx); return lVar; } private LogicalVariable translateQNameNode(TranslationContext tCtx, QNameNode qnNode) throws SystemException { LogicalVariable lVar = createAssignment( ce(SequenceType.create(BuiltinTypeRegistry.XS_QNAME, Quantifier.QUANT_ONE), createQName(qnNode)), tCtx); return lVar; } private LogicalVariable translateValidateExprNode(TranslationContext tCtx, ValidateExprNode vNode) throws SystemException { XQueryConstants.ValidationMode mode = vNode.getMode(); Function fn = mode == null || XQueryConstants.ValidationMode.STRICT.equals(mode) ? BuiltinOperators.VALIDATE_STRICT : BuiltinOperators.VALIDATE_LAX; LogicalVariable lVar = createAssignment(sfce(fn, vre(translateExpression(vNode.getExpr(), tCtx))), tCtx); return lVar; } private LogicalVariable translateComputedAttributeConstructorNode(TranslationContext tCtx, ComputedAttributeConstructorNode cNode) throws SystemException { ILogicalExpression name = cast(vre(translateExpression(cNode.getName(), tCtx)), SequenceType.create(BuiltinTypeRegistry.XS_QNAME, Quantifier.QUANT_ONE)); ASTNode content = cNode.getContent(); ILogicalExpression cExpr = content == null ? sfce(BuiltinOperators.CONCATENATE) : vre(translateExpression(content, tCtx)); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.ATTRIBUTE_CONSTRUCTOR, name, cExpr), tCtx); return lVar; } private LogicalVariable translateComputedElementConstructorNode(TranslationContext tCtx, ComputedElementConstructorNode cNode) throws SystemException { ILogicalExpression name = cast(vre(translateExpression(cNode.getName(), tCtx)), SequenceType.create(BuiltinTypeRegistry.XS_QNAME, Quantifier.QUANT_ONE)); ASTNode content = cNode.getContent(); ILogicalExpression cExpr = content == null ? sfce(BuiltinOperators.CONCATENATE) : vre(translateExpression(content, tCtx)); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.ELEMENT_CONSTRUCTOR, name, cExpr), tCtx); return lVar; } private LogicalVariable translateComputedDocumentConstructorNode(TranslationContext tCtx, ComputedDocumentConstructorNode cNode) throws SystemException { LogicalVariable lVar = createAssignment( sfce(BuiltinOperators.DOCUMENT_CONSTRUCTOR, vre(translateExpression(cNode.getContent(), tCtx))), tCtx); return lVar; } private LogicalVariable translateComputedCommentConstructorNode(TranslationContext tCtx, ComputedCommentConstructorNode cNode) throws SystemException { ASTNode content = cNode.getContent(); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.COMMENT_CONSTRUCTOR, content == null ? sfce(BuiltinOperators.CONCATENATE) : vre(translateExpression(content, tCtx))), tCtx); return lVar; } private LogicalVariable translateComputedPIConstructorNode(TranslationContext tCtx, ComputedPIConstructorNode cNode) throws SystemException { ASTNode content = cNode.getContent(); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.PI_CONSTRUCTOR, vre(translateExpression(cNode.getTarget(), tCtx)), content == null ? sfce(BuiltinOperators.CONCATENATE) : vre(translateExpression(content, tCtx))), tCtx); return lVar; } private LogicalVariable translateComputedTextConstructorNode(TranslationContext tCtx, ComputedTextConstructorNode cNode) throws SystemException { ASTNode content = cNode.getContent(); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.TEXT_CONSTRUCTOR, content == null ? ce(SequenceType.create(BuiltinTypeRegistry.XS_UNTYPED_ATOMIC, Quantifier.QUANT_ONE), "") : vre(translateExpression(content, tCtx))), tCtx); return lVar; } private LogicalVariable translateFLWORExprNode(TranslationContext tCtx, FLWORExprNode fNode) throws SystemException { tCtx = tCtx.pushContext(); List<FLWORClauseNode> cNodes = fNode.getClauses(); int pushCount = 0; for (FLWORClauseNode cNode : cNodes) { switch (cNode.getTag()) { case FOR_CLAUSE: { ForClauseNode fcNode = (ForClauseNode) cNode; for (ForVarDeclNode fvdNode : fcNode.getVariables()) { ILogicalExpression seq = vre(translateExpression(fvdNode.getSequence(), tCtx)); tCtx.pushVariableScope(); LogicalVariable forLVar = newLogicalVariable(); LogicalVariable posLVar = fvdNode.getPosVar() != null ? newLogicalVariable() : null; UnnestOperator unnest = new UnnestOperator(forLVar, mutable(ufce(BuiltinOperators.ITERATE, seq)), posLVar, BuiltinTypeRegistry.XS_INTEGER, new VXQueryPositionWriter()); SequenceType forVarType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_ONE); if (fvdNode.getType() != null) { forVarType = createSequenceType(fvdNode.getType()); } XQueryVariable forVar = new XQueryVariable(createQName(fvdNode.getForVar()), forVarType, forLVar); tCtx.varScope.registerVariable(forVar); XQueryVariable posVar = null; if (fvdNode.getPosVar() != null) { posVar = new XQueryVariable(createQName(fvdNode.getPosVar()), SequenceType.create(BuiltinTypeRegistry.XS_INTEGER, Quantifier.QUANT_ONE), posLVar); tCtx.varScope.registerVariable(posVar); } assert fvdNode.getScoreVar() == null; unnest.getInputs().add(mutable(tCtx.op)); tCtx.op = unnest; ++pushCount; } break; } case LET_CLAUSE: { LetClauseNode lcNode = (LetClauseNode) cNode; for (LetVarDeclNode lvdNode : lcNode.getVariables()) { LogicalVariable seqVar = translateExpression(lvdNode.getSequence(), tCtx); tCtx.pushVariableScope(); SequenceType letVarType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_STAR); if (lvdNode.getType() != null) { letVarType = createSequenceType(lvdNode.getType()); } XQueryVariable letVar = new XQueryVariable(createQName(lvdNode.getLetVar()), letVarType, seqVar); tCtx.varScope.registerVariable(letVar); ++pushCount; } break; } case WHERE_CLAUSE: { WhereClauseNode wcNode = (WhereClauseNode) cNode; ILogicalExpression condExpr = sfce(BuiltinFunctions.FN_BOOLEAN_1, vre(translateExpression(wcNode.getCondition(), tCtx))); SelectOperator select = new SelectOperator(mutable(condExpr), false, null); select.getInputs().add(mutable(tCtx.op)); tCtx.op = select; break; } case ORDERBY_CLAUSE: { OrderbyClauseNode ocNode = (OrderbyClauseNode) cNode; List<edu.uci.ics.hyracks.algebricks.common.utils.Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>> oExprs = new ArrayList<edu.uci.ics.hyracks.algebricks.common.utils.Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>>(); List<String> collations = new ArrayList<String>(); for (OrderSpecNode osNode : ocNode.getOrderSpec()) { ILogicalExpression oExpr = vre(translateExpression(osNode.getExpression(), tCtx)); OrderOperator.IOrder o = OrderOperator.ASC_ORDER; XQueryConstants.OrderDirection oDir = osNode.getDirection(); if (oDir != null) { switch (oDir) { case ASCENDING: o = OrderOperator.ASC_ORDER; break; case DESCENDING: o = OrderOperator.DESC_ORDER; break; } } /* StaticContext.EmptyOrderProperty eoProp = osNode.getEmptyOrder(); if (eoProp != null) { switch (osNode.getEmptyOrder()) { case GREATEST: eOrders.add(FLWORExpression.EmptyOrder.GREATEST); break; case LEAST: eOrders.add(FLWORExpression.EmptyOrder.LEAST); break; } } else { eOrders.add(FLWORExpression.EmptyOrder.DEFAULT); } collations.add(osNode.getCollation()); */ oExprs.add( new edu.uci.ics.hyracks.algebricks.common.utils.Pair<OrderOperator.IOrder, Mutable<ILogicalExpression>>( o, mutable(oExpr))); } OrderOperator order = new OrderOperator(oExprs); order.getInputs().add(mutable(tCtx.op)); tCtx.op = order; break; } default: throw new IllegalStateException("Unknown clause: " + cNode.getTag()); } } ILogicalExpression rExpr = vre(translateExpression(fNode.getReturnExpr(), tCtx)); List<LogicalVariable> vars = new ArrayList<LogicalVariable>(); List<Mutable<ILogicalExpression>> exprs = new ArrayList<Mutable<ILogicalExpression>>(); LogicalVariable var = newLogicalVariable(); vars.add(var); exprs.add(mutable(afce(BuiltinOperators.SEQUENCE, false, rExpr))); AggregateOperator aop = new AggregateOperator(vars, exprs); aop.getInputs().add(mutable(tCtx.op)); tCtx.op = aop; for (int i = 0; i < pushCount; ++i) { tCtx.popVariableScope(); } tCtx = tCtx.popContext(); return var; } private LogicalVariable translateVarRefNode(TranslationContext tCtx, VarRefNode vrNode) throws SystemException { QName vName = createQName(vrNode.getVariable()); XQueryVariable var = tCtx.varScope.lookupVariable(vName); if (var == null) { throw new SystemException(ErrorCode.XPST0008, vrNode.getSourceLocation()); } LogicalVariable lVar = createAssignment(treat(vre(var.getLogicalVariable()), var.getType()), tCtx); return lVar; } private LogicalVariable translateIfExprNode(TranslationContext tCtx, IfExprNode ieNode) throws SystemException { ILogicalExpression cond = sfce(BuiltinFunctions.FN_BOOLEAN_1, vre(translateExpression(ieNode.getIfExpr(), tCtx))); ILogicalExpression tExpr = vre(translateExpression(ieNode.getThenExpr(), tCtx)); ILogicalExpression eExpr = vre(translateExpression(ieNode.getElseExpr(), tCtx)); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.IF_THEN_ELSE, cond, tExpr, eExpr), tCtx); return lVar; } private LogicalVariable translateDirectAttributeConstructorNode(TranslationContext tCtx, DirectAttributeConstructorNode dacNode) throws SystemException { QName aQName = createQName(dacNode.getName()); ILogicalExpression name = ce(SequenceType.create(BuiltinTypeRegistry.XS_QNAME, Quantifier.QUANT_ONE), aQName); List<ILogicalExpression> content = new ArrayList<ILogicalExpression>(); for (ASTNode aVal : dacNode.getValue()) { switch (aVal.getTag()) { case CONTENT_CHARS: { String contentChars = ((ContentCharsNode) aVal).getContent(); ILogicalExpression cce = ce( SequenceType.create(BuiltinTypeRegistry.XS_UNTYPED_ATOMIC, Quantifier.QUANT_ONE), contentChars); content.add(cce); break; } default: content.add(vre(translateExpression(aVal, tCtx))); } } ILogicalExpression contentExpr = content.size() == 1 ? content.get(0) : sfce(BuiltinOperators.CONCATENATE, content.toArray(new ILogicalExpression[content.size()])); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.ATTRIBUTE_CONSTRUCTOR, name, contentExpr), tCtx); return lVar; } private LogicalVariable translateDirectElementConstructorNode(TranslationContext tCtx, DirectElementConstructorNode decNode) throws SystemException { QNameNode startName = decNode.getStartTagName(); QNameNode endName = decNode.getEndTagName(); if (endName != null && (!startName.getPrefix().equals(endName.getPrefix()) || !startName.getLocalName().equals(endName.getLocalName()))) { throw new SystemException(ErrorCode.XPST0003, endName.getSourceLocation()); } pushContext(); for (DirectAttributeConstructorNode acNode : decNode.getAttributes()) { QNameNode aName = acNode.getName(); if ("xmlns".equals(aName.getPrefix())) { List<ASTNode> values = acNode.getValue(); if (values.size() != 1 || !ASTTag.CONTENT_CHARS.equals(values.get(0).getTag())) { throw new SystemException(ErrorCode.XQST0022, acNode.getSourceLocation()); } currCtx.registerNamespaceUri(aName.getLocalName(), unquote(((ContentCharsNode) values.get(0)).getContent())); } } List<ILogicalExpression> content = new ArrayList<ILogicalExpression>(); for (DirectAttributeConstructorNode acNode : decNode.getAttributes()) { QNameNode aName = acNode.getName(); if (!"xmlns".equals(aName.getPrefix())) { content.add(vre(translateExpression(acNode, tCtx))); } } ILogicalExpression name = ce(SequenceType.create(BuiltinTypeRegistry.XS_QNAME, Quantifier.QUANT_ONE), createQName(startName, moduleCtx.getDefaultElementNamespaceUri())); for (ASTNode cVal : decNode.getContent()) { switch (cVal.getTag()) { case CONTENT_CHARS: { String contentChars = ((ContentCharsNode) cVal).getContent(); ILogicalExpression cce = ce( SequenceType.create(BuiltinTypeRegistry.XS_UNTYPED_ATOMIC, Quantifier.QUANT_ONE), contentChars); content.add(sfce(BuiltinOperators.TEXT_CONSTRUCTOR, cce)); break; } default: content.add(vre(translateExpression(cVal, tCtx))); } } popContext(); ILogicalExpression contentExpr = content.size() == 1 ? content.get(0) : sfce(BuiltinOperators.CONCATENATE, content.toArray(new ILogicalExpression[content.size()])); LogicalVariable lVar = createAssignment(sfce(BuiltinOperators.ELEMENT_CONSTRUCTOR, name, contentExpr), tCtx); return lVar; } private LogicalVariable translateDirectCommentConstructorNode(TranslationContext tCtx, DirectCommentConstructorNode dccNode) throws SystemException { String content = dccNode.getContent(); LogicalVariable lVar = createAssignment( sfce(BuiltinOperators.COMMENT_CONSTRUCTOR, ce(SequenceType.create(BuiltinTypeRegistry.XS_STRING, Quantifier.QUANT_ONE), content)), tCtx); return lVar; } private LogicalVariable translateDirectPIConstructorNode(TranslationContext tCtx, DirectPIConstructorNode dpicNode) throws SystemException { String target = dpicNode.getTarget(); String content = dpicNode.getContent(); LogicalVariable lVar = createAssignment( sfce(BuiltinOperators.PI_CONSTRUCTOR, ce(SequenceType.create(BuiltinTypeRegistry.XS_STRING, Quantifier.QUANT_ONE), target), ce(SequenceType.create(BuiltinTypeRegistry.XS_STRING, Quantifier.QUANT_ONE), content)), tCtx); return lVar; } private LogicalVariable translateLiteralNode(TranslationContext tCtx, LiteralNode lNode) throws SystemException { String image = lNode.getImage(); LiteralNode.LiteralType lType = lNode.getType(); SequenceType t = null; Object value = null; switch (lType) { case DECIMAL: t = SequenceType.create(BuiltinTypeRegistry.XS_DECIMAL, Quantifier.QUANT_ONE); value = Double.parseDouble(image); break; case DOUBLE: t = SequenceType.create(BuiltinTypeRegistry.XS_DOUBLE, Quantifier.QUANT_ONE); value = Double.parseDouble(image); break; case INTEGER: t = SequenceType.create(BuiltinTypeRegistry.XS_INTEGER, Quantifier.QUANT_ONE); try { value = Long.parseLong(image); } catch (NumberFormatException nfe) { throw new SystemException(ErrorCode.FOAR0002); } break; case STRING: t = SequenceType.create(BuiltinTypeRegistry.XS_STRING, Quantifier.QUANT_ONE); value = unquote(image); break; default: throw new IllegalStateException("Unknown type: " + lType); } LogicalVariable lVar = createAssignment(ce(t, value), tCtx); return lVar; } private LogicalVariable translateParenthisizedExprNode(TranslationContext tCtx, ParenthesizedExprNode peNode) throws SystemException { ASTNode eNode = peNode.getExpr(); if (eNode == null) { return createConcatenation(Collections.<LogicalVariable>emptyList(), tCtx); } return translateExpression(peNode.getExpr(), tCtx); } private LogicalVariable translateExtensionExprNode(TranslationContext tCtx, ExtensionExprNode eNode) throws SystemException { if (eNode.getExpr() == null) { throw new SystemException(ErrorCode.XQST0079, eNode.getSourceLocation()); } return translateExpression(eNode.getExpr(), tCtx); } private LogicalVariable translateTypeExprNode(TranslationContext tCtx, TypeExprNode teNode) throws SystemException { LogicalVariable var = translateExpression(teNode.getExpr(), tCtx); SequenceType type = createSequenceType(teNode.getType()); ILogicalExpression expr = null; switch (teNode.getOperator()) { case CAST: expr = cast(vre(var), type); break; case CASTABLE: expr = castable(vre(var), type); break; case INSTANCEOF: expr = instanceOf(vre(var), type); break; case TREAT: expr = treat(vre(var), type); break; default: throw new IllegalStateException("Unknown type operator: " + teNode.getOperator()); } LogicalVariable lVar = createAssignment(expr, tCtx); return lVar; } private LogicalVariable translateFunctionExprNode(TranslationContext tCtx, FunctionExprNode fnNode) throws SystemException { List<LogicalVariable> args = new ArrayList<LogicalVariable>(); for (ASTNode an : fnNode.getArguments()) { args.add(translateExpression(an, tCtx)); } QName name = createQName(fnNode.getName()); SchemaType type = moduleCtx.lookupSchemaType(name); if (type != null && args.size() < 2) { if (!type.isAtomicType()) { throw new SystemException(ErrorCode.XPST0051, fnNode.getName().getSourceLocation()); } LogicalVariable var = args.isEmpty() ? tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME).getLogicalVariable() : args.get(0); ILogicalExpression expr = cast(vre(var), SequenceType.create((ItemType) type, Quantifier.QUANT_QUESTION)); return createAssignment(expr, tCtx); } QName fName = createQName(fnNode.getName(), moduleCtx.getDefaultFunctionNamespaceUri()); if (BuiltinFunctions.FN_POSITION_QNAME.equals(fName)) { XQueryVariable var = tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.POS_VAR_NAME); return var.getLogicalVariable(); } if (BuiltinFunctions.FN_LAST_QNAME.equals(fName)) { XQueryVariable var = tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.LAST_VAR_NAME); return var.getLogicalVariable(); } int nArgs = fnNode.getArguments().size(); Function fn = moduleCtx.lookupFunction(fName, nArgs); if (fn != null && fn.useContextImplicitly()) { args.add(tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME).getLogicalVariable()); fn = moduleCtx.lookupFunction(fName, nArgs + 1); } if (fn == null) { Function[] fns = moduleCtx.lookupFunctions(fName); if (fns != null) { for (int i = 0; i < fns.length && i <= nArgs; ++i) { if (fns[i] != null && fns[i].getSignature().isVarArgs()) { fn = fns[i]; break; } } } } if (fn == null) { throw new SystemException(ErrorCode.XPST0017, fnNode.getName().getSourceLocation()); } Signature sign = fn.getSignature(); List<Mutable<ILogicalExpression>> argExprs = new ArrayList<Mutable<ILogicalExpression>>(); for (int i = 0; i < args.size(); ++i) { SequenceType argType = sign.getParameterType(i); argExprs.add(mutable(normalize(vre(args.get(i)), argType))); } LogicalVariable lVar = createAssignment(new ScalarFunctionCallExpression(fn, argExprs), tCtx); return lVar; } private LogicalVariable translateEnclosedExprNode(TranslationContext tCtx, EnclosedExprNode ee) throws SystemException { return translateExpression(ee.getExpression(), tCtx); } private LogicalVariable translateInfixExprNode(TranslationContext tCtx, InfixExprNode ie) throws SystemException { Function operator = getOperator(ie.getOperator()); Signature sign = operator.getSignature(); LogicalVariable varLeft = translateExpression(ie.getLeftExpr(), tCtx); LogicalVariable varRight = translateExpression(ie.getRightExpr(), tCtx); ILogicalExpression arg1 = normalize(vre(varLeft), sign.getParameterType(0)); ILogicalExpression arg2 = normalize(vre(varRight), sign.getParameterType(1)); if (BuiltinOperators.EXCEPT.equals(operator) || BuiltinOperators.INTERSECT.equals(operator)) { arg1 = sfce(BuiltinOperators.SORT_DISTINCT_NODES_ASC, arg1); arg2 = sfce(BuiltinOperators.SORT_DISTINCT_NODES_ASC, arg2); } ILogicalExpression result = sfce(operator, arg1, arg2); if (BuiltinOperators.UNION.equals(operator)) { result = sfce(BuiltinOperators.SORT_DISTINCT_NODES_ASC, result); } LogicalVariable lVar = createAssignment(result, tCtx); return lVar; } private LogicalVariable translateUnaryExprNode(TranslationContext tCtx, UnaryExprNode ueNode) throws SystemException { boolean neg = false; for (UnaryExprNode.Sign s : ueNode.getSigns()) { if (UnaryExprNode.Sign.MINUS.equals(s)) { neg = !neg; } } LogicalVariable var = translateExpression(ueNode.getExpr(), tCtx); if (neg) { ILogicalExpression nExpr = normalize(vre(var), BuiltinOperators.NUMERIC_UNARY_MINUS.getSignature().getParameterType(0)); ILogicalExpression negExpr = sfce(BuiltinOperators.NUMERIC_UNARY_MINUS, nExpr); var = createAssignment(negExpr, tCtx); } return var; } private LogicalVariable translateExprNode(TranslationContext tCtx, ExprNode node) throws SystemException { return createConcatenation(translateExpressionList(node.getExpressions(), tCtx), tCtx); } private LogicalVariable translatePathExpr(PathExprNode pe, TranslationContext tCtx) throws SystemException { ILogicalExpression ctxExpr = null; PathType type = pe.getPathType(); if (type != null) { XQueryVariable dotVar = tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME); ILogicalExpression root = sfce(BuiltinFunctions.FN_ROOT_1, vre(dotVar.getLogicalVariable())); if (PathType.SLASH.equals(type)) { ctxExpr = root; } else { ctxExpr = sfce(BuiltinOperators.DESCENDANT_OR_SELF, treat(root, SequenceType.create(AnyNodeType.INSTANCE, Quantifier.QUANT_STAR))); } } if (pe.getPaths() != null) { for (RelativePathExprNode rpen : pe.getPaths()) { boolean asc = true; if (PathType.SLASH_SLASH.equals(rpen.getPathType())) { ctxExpr = sfce(BuiltinOperators.DESCENDANT_OR_SELF, treat(ctxExpr, SequenceType.create(AnyNodeType.INSTANCE, Quantifier.QUANT_STAR))); } boolean popScope = false; if (ctxExpr != null) { popScope = true; tCtx = tCtx.pushContext(); tCtx.pushVariableScope(); iterateOver(ctxExpr, tCtx); ctxExpr = null; } List<ASTNode> predicates = null; ASTNode pathNode = rpen.getPath(); if (ASTTag.AXIS_STEP.equals(pathNode.getTag())) { AxisStepNode axisNode = (AxisStepNode) pathNode; predicates = axisNode.getPredicates(); AxisStepNode.Axis axis = axisNode.getAxis(); if (ctxExpr == null) { ctxExpr = vre(tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME) .getLogicalVariable()); } Function axisFn = translateAxis(axis); NodeType nt = translateNodeTest(axis, axisNode.getNodeTest()); int ntCode = currCtx.encodeSequenceType(SequenceType.create(nt, Quantifier.QUANT_ONE)); ctxExpr = sfce(axisFn, treat(ctxExpr, SequenceType.create(AnyNodeType.INSTANCE, Quantifier.QUANT_STAR)), ce(SequenceType.create(BuiltinTypeRegistry.XS_INT, Quantifier.QUANT_ONE), ntCode)); asc = isForwardAxis(axis); } else if (ASTTag.FILTER_EXPRESSION.equals(pathNode.getTag())) { FilterExprNode filterNode = (FilterExprNode) pathNode; predicates = filterNode.getPredicates(); ctxExpr = vre(translateExpression(filterNode.getExpr(), tCtx)); } else { throw new IllegalStateException("Unknown path node: " + pathNode.getTag()); } if (predicates != null && !predicates.isEmpty()) { ctxExpr = sfce(asc ? BuiltinOperators.SORT_DISTINCT_NODES_ASC_OR_ATOMICS : BuiltinOperators.SORT_DISTINCT_NODES_DESC_OR_ATOMICS, ctxExpr); for (ASTNode pn : predicates) { tCtx = tCtx.pushContext(); tCtx.pushVariableScope(); iterateOver(ctxExpr, tCtx); LogicalVariable pLVar = translateExpression(pn, tCtx); ILogicalExpression tTest = instanceOf(vre(pLVar), SequenceType.create(BuiltinTypeRegistry.XSEXT_NUMERIC, Quantifier.QUANT_ONE)); ILogicalExpression posTest = sfce(BuiltinOperators.VALUE_EQ, vre(pLVar), vre(tCtx.varScope .lookupVariable(XMLQueryCompilerConstants.POS_VAR_NAME).getLogicalVariable())); ILogicalExpression boolTest = sfce(BuiltinFunctions.FN_BOOLEAN_1, vre(pLVar)); SelectOperator select = new SelectOperator( mutable(sfce(BuiltinOperators.IF_THEN_ELSE, tTest, posTest, boolTest)), false, null); select.getInputs().add(mutable(tCtx.op)); tCtx.op = select; ctxExpr = vre(tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME) .getLogicalVariable()); tCtx.popVariableScope(); tCtx = tCtx.popContext(); } } if (popScope) { tCtx.popVariableScope(); List<LogicalVariable> vars = new ArrayList<LogicalVariable>(); List<Mutable<ILogicalExpression>> exprs = new ArrayList<Mutable<ILogicalExpression>>(); LogicalVariable var = newLogicalVariable(); vars.add(var); exprs.add(mutable(afce(BuiltinOperators.SEQUENCE, false, ctxExpr))); AggregateOperator aop = new AggregateOperator(vars, exprs); aop.getInputs().add(mutable(tCtx.op)); tCtx.op = aop; tCtx = tCtx.popContext(); ctxExpr = vre(var); ctxExpr = sfce(asc ? BuiltinOperators.SORT_DISTINCT_NODES_ASC_OR_ATOMICS : BuiltinOperators.SORT_DISTINCT_NODES_DESC_OR_ATOMICS, vre(var)); } } } LogicalVariable lVar = createAssignment(ctxExpr, tCtx); return lVar; } private void iterateOver(ILogicalExpression ctxExpr, TranslationContext tCtx) { LogicalVariable seqLVar = createAssignment(ctxExpr, tCtx); LogicalVariable lastLVar = createAssignment(sfce(BuiltinFunctions.FN_COUNT_1, vre(seqLVar)), tCtx); tCtx.varScope.registerVariable(new XQueryVariable(XMLQueryCompilerConstants.LAST_VAR_NAME, SequenceType.create(BuiltinTypeRegistry.XS_INTEGER, Quantifier.QUANT_ONE), lastLVar)); LogicalVariable forLVar = newLogicalVariable(); LogicalVariable posLVar = newLogicalVariable(); UnnestOperator unnest = new UnnestOperator(forLVar, mutable(ufce(BuiltinOperators.ITERATE, vre(seqLVar))), posLVar, BuiltinTypeRegistry.XS_INTEGER, new VXQueryPositionWriter()); SequenceType forVarType = SequenceType.create(AnyItemType.INSTANCE, Quantifier.QUANT_ONE); XQueryVariable forVar = new XQueryVariable(XMLQueryCompilerConstants.DOT_VAR_NAME, forVarType, forLVar); tCtx.varScope.registerVariable(forVar); SequenceType posVarType = SequenceType.create(BuiltinTypeRegistry.XS_INTEGER, Quantifier.QUANT_ONE); XQueryVariable posVar = new XQueryVariable(XMLQueryCompilerConstants.POS_VAR_NAME, posVarType, posLVar); tCtx.varScope.registerVariable(posVar); unnest.getInputs().add(mutable(tCtx.op)); tCtx.op = unnest; } private boolean isForwardAxis(AxisStepNode.Axis axis) { switch (axis) { case ABBREV: case CHILD: case ABBREV_ATTRIBUTE: case ATTRIBUTE: case DESCENDANT: case DESCENDANT_OR_SELF: case FOLLOWING: case FOLLOWING_SIBLING: case SELF: return true; case ANCESTOR: case ANCESTOR_OR_SELF: case DOT_DOT: case PARENT: case PRECEDING: case PRECEDING_SIBLING: return false; default: throw new IllegalStateException("Unknown axis: " + axis); } } private NodeType translateNodeTest(AxisStepNode.Axis axis, ASTNode nodeTest) throws SystemException { NodeType nt = AnyNodeType.INSTANCE; if (nodeTest != null) { switch (nodeTest.getTag()) { case NAME_TEST: { NameTestNode ntn = (NameTestNode) nodeTest; String uri = null; if (ntn.getPrefix() != null) { if (!"".equals(ntn.getPrefix())) { uri = currCtx.lookupNamespaceUri(ntn.getPrefix()); if (uri == null) { throw new SystemException(ErrorCode.XPST0081, ntn.getSourceLocation()); } } else { uri = ""; } } String localName = ntn.getLocalName(); NameTest nameTest = new NameTest(uri == null ? null : createUTF8String(uri), localName == null ? null : createUTF8String(ntn.getLocalName())); if (axis == AxisStepNode.Axis.ATTRIBUTE || axis == AxisStepNode.Axis.ABBREV_ATTRIBUTE) { nt = new AttributeType(nameTest, BuiltinTypeRegistry.XS_ANY_ATOMIC); } else { nt = new ElementType(nameTest, AnyType.INSTANCE, true); } break; } case ANY_NODE_TEST: case DOCUMENT_TEST: case TEXT_TEST: case COMMENT_TEST: case PI_TEST: case ATTRIBUTE_TEST: case SCHEMA_ATTRIBUTE_TEST: case ELEMENT_TEST: case SCHEMA_ELEMENT_TEST: nt = (NodeType) createItemType(nodeTest); break; default: throw new IllegalStateException("Unknown node: " + nodeTest.getTag()); } } return nt; } private Function translateAxis(AxisStepNode.Axis axis) { switch (axis) { case ABBREV: case CHILD: return BuiltinOperators.CHILD; case ABBREV_ATTRIBUTE: case ATTRIBUTE: return BuiltinOperators.ATTRIBUTE; case ANCESTOR: return BuiltinOperators.ANCESTOR; case ANCESTOR_OR_SELF: return BuiltinOperators.ANCESTOR_OR_SELF; case DESCENDANT: return BuiltinOperators.DESCENDANT; case DESCENDANT_OR_SELF: return BuiltinOperators.DESCENDANT_OR_SELF; case DOT_DOT: case PARENT: return BuiltinOperators.PARENT; case FOLLOWING: return BuiltinOperators.FOLLOWING; case FOLLOWING_SIBLING: return BuiltinOperators.FOLLOWING_SIBLING; case PRECEDING: return BuiltinOperators.PRECEDING; case PRECEDING_SIBLING: return BuiltinOperators.PRECEDING_SIBLING; case SELF: return BuiltinOperators.SELF; default: throw new IllegalStateException("Unknown axis: " + axis); } } private static String unquote(String image) throws SystemException { StringBuilder buffer = new StringBuilder(); char quoteChar = image.charAt(0); image = image.substring(1, image.length() - 1); Matcher m = UNQUOTER.matcher(image); int i = 0; while (m.find()) { int start = m.start(); int end = m.end(); if (i < start) { buffer.append(image, i, start); } if (m.start(1) >= 0) { buffer.append('<'); } else if (m.start(2) >= 0) { buffer.append('>'); } else if (m.start(3) >= 0) { buffer.append('\''); } else if (m.start(4) >= 0) { buffer.append('&'); } else if (m.start(5) >= 0) { buffer.append('"'); } else if (m.start(6) >= 0) { buffer.append(quoteChar == '"' ? '"' : "\"\""); } else if (m.start(7) >= 0) { buffer.append(quoteChar == '\'' ? '\'' : "''"); } else if (m.start(8) >= 0) { try { buffer.appendCodePoint(Integer.parseInt(image.substring(start + 2, end - 1))); } catch (NumberFormatException e) { throw new SystemException(ErrorCode.XQST0090); } } else if (m.start(9) >= 0) { try { buffer.appendCodePoint(Integer.parseInt(image.substring(start + 3, end - 1), 16)); } catch (NumberFormatException e) { throw new SystemException(ErrorCode.XQST0090); } } i = m.end(); } if (i < image.length()) { buffer.append(image, i, image.length()); } return buffer.toString(); } private QName createQName(QNameNode qnNode) throws SystemException { return createQName(qnNode, ""); } private QName createQName(QNameNode qnNode, String defaultUri) throws SystemException { String prefix = qnNode.getPrefix(); String local = qnNode.getLocalName(); String uri; if (!"".equals(prefix)) { uri = currCtx.lookupNamespaceUri(prefix); if (uri == null) { throw new SystemException(ErrorCode.XPST0081, qnNode.getSourceLocation()); } } else { uri = defaultUri; } return new QName(uri, local, prefix); } private static ILogicalExpression afce(Function fn, boolean isTwoStep, ILogicalExpression... argExprs) { List<Mutable<ILogicalExpression>> args = new ArrayList<Mutable<ILogicalExpression>>(); for (ILogicalExpression e : argExprs) { args.add(mutable(e)); } return new AggregateFunctionCallExpression(fn, isTwoStep, args); } private static ILogicalExpression ufce(Function fn, ILogicalExpression... argExprs) { List<Mutable<ILogicalExpression>> args = new ArrayList<Mutable<ILogicalExpression>>(); for (ILogicalExpression e : argExprs) { args.add(mutable(e)); } return new UnnestingFunctionCallExpression(fn, args); } private static ILogicalExpression sfce(Function fn, ILogicalExpression... argExprs) { List<Mutable<ILogicalExpression>> args = new ArrayList<Mutable<ILogicalExpression>>(); for (ILogicalExpression e : argExprs) { args.add(mutable(e)); } return new ScalarFunctionCallExpression(fn, args); } private Function getOperator(InfixOperator operator) { switch (operator) { case AND: return BuiltinOperators.AND; case DIV: return BuiltinOperators.DIVIDE; case EXCEPT: return BuiltinOperators.EXCEPT; case FOLLOWS: return BuiltinOperators.NODE_AFTER; case GENERAL_EQ: return BuiltinOperators.GENERAL_EQ; case GENERAL_GE: return BuiltinOperators.GENERAL_GE; case GENERAL_GT: return BuiltinOperators.GENERAL_GT; case GENERAL_LE: return BuiltinOperators.GENERAL_LE; case GENERAL_LT: return BuiltinOperators.GENERAL_LT; case GENERAL_NE: return BuiltinOperators.GENERAL_NE; case IDIV: return BuiltinOperators.IDIV; case INTERSECT: return BuiltinOperators.INTERSECT; case IS: return BuiltinOperators.IS_SAME_NODE; case MINUS: return BuiltinOperators.SUBTRACT; case MOD: return BuiltinOperators.MOD; case MULTIPLY: return BuiltinOperators.MULTIPLY; case OR: return BuiltinOperators.OR; case PLUS: return BuiltinOperators.ADD; case PRECEDES: return BuiltinOperators.NODE_BEFORE; case RANGE: return BuiltinOperators.TO; case UNION: return BuiltinOperators.UNION; case VALUE_EQ: return BuiltinOperators.VALUE_EQ; case VALUE_GE: return BuiltinOperators.VALUE_GE; case VALUE_GT: return BuiltinOperators.VALUE_GT; case VALUE_LE: return BuiltinOperators.VALUE_LE; case VALUE_LT: return BuiltinOperators.VALUE_LT; case VALUE_NE: return BuiltinOperators.VALUE_NE; } throw new IllegalStateException("Unknown operator: " + operator); } private ILogicalExpression ce(SequenceType type, Object value) throws SystemException { try { ItemType it = type.getItemType(); if (it.isAtomicType()) { AtomicType at = (AtomicType) it; byte[] bytes = null; switch (at.getTypeId()) { case BuiltinTypeConstants.XS_BOOLEAN_TYPE_ID: { baaos.reset(); dOut.write((byte) ValueTag.XS_BOOLEAN_TAG); dOut.writeByte(((Boolean) value).booleanValue() ? 1 : 0); break; } case BuiltinTypeConstants.XS_INT_TYPE_ID: { baaos.reset(); dOut.write((byte) ValueTag.XS_INT_TAG); dOut.writeInt(((Number) value).intValue()); break; } case BuiltinTypeConstants.XS_INTEGER_TYPE_ID: { baaos.reset(); dOut.write((byte) ValueTag.XS_INTEGER_TAG); dOut.writeLong(((Number) value).longValue()); break; } case BuiltinTypeConstants.XS_DOUBLE_TYPE_ID: { baaos.reset(); dOut.write((byte) ValueTag.XS_DOUBLE_TAG); dOut.writeDouble(((Number) value).doubleValue()); break; } case BuiltinTypeConstants.XS_STRING_TYPE_ID: { baaos.reset(); dOut.write((byte) ValueTag.XS_STRING_TAG); stringVB.write((CharSequence) value, dOut); break; } case BuiltinTypeConstants.XS_DECIMAL_TYPE_ID: { baaos.reset(); // TODO Remove the creation of the separate byte array. DoublePointable doublep = (DoublePointable) DoublePointable.FACTORY.createPointable(); doublep.set(new byte[DoublePointable.TYPE_TRAITS.getFixedLength()], 0, DoublePointable.TYPE_TRAITS.getFixedLength()); doublep.setDouble(((Number) value).doubleValue()); CastToDecimalOperation castToDecimal = new CastToDecimalOperation(); castToDecimal.convertDouble(doublep, dOut); break; } case BuiltinTypeConstants.XS_QNAME_TYPE_ID: { QName qname = (QName) value; baaos.reset(); dOut.write((byte) ValueTag.XS_QNAME_TAG); stringVB.write(qname.getNamespaceURI(), dOut); stringVB.write(qname.getPrefix(), dOut); stringVB.write(qname.getLocalPart(), dOut); break; } case BuiltinTypeConstants.XS_UNTYPED_ATOMIC_TYPE_ID: { baaos.reset(); dOut.write((byte) ValueTag.XS_UNTYPED_ATOMIC_TAG); stringVB.write((CharSequence) value, dOut); break; } default: throw new SystemException(ErrorCode.SYSE0001); } bytes = Arrays.copyOf(baaos.getByteArray(), baaos.size()); return new ConstantExpression(new VXQueryConstantValue(type, bytes)); } throw new UnsupportedOperationException(); } catch (IOException e) { throw new SystemException(ErrorCode.SYSE0001, e); } } private static ILogicalExpression vre(LogicalVariable var) { if (var == null) { throw new NullPointerException(); } return new VariableReferenceExpression(var); } private LogicalVariable createConcatenation(List<LogicalVariable> vars, TranslationContext tCtx) { if (vars.size() == 1) { return vars.get(0); } return createFunctionCall(BuiltinOperators.CONCATENATE, vars, tCtx); } private LogicalVariable createFunctionCall(Function fn, List<LogicalVariable> vars, TranslationContext tCtx) { return createAssignment(createFunctionCall(fn, vars), tCtx); } private LogicalVariable createAssignment(ILogicalExpression expr, TranslationContext tCtx) { if (expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) { return ((VariableReferenceExpression) expr).getVariableReference(); } LogicalVariable result = newLogicalVariable(); AssignOperator aOp = new AssignOperator(result, mutable(expr)); aOp.getInputs().add(mutable(tCtx.op)); tCtx.op = aOp; return result; } private static ILogicalExpression createFunctionCall(Function fn, List<LogicalVariable> vars) { List<Mutable<ILogicalExpression>> args = new ArrayList<Mutable<ILogicalExpression>>(); for (LogicalVariable var : vars) { args.add(mutable(new VariableReferenceExpression(var))); } return new ScalarFunctionCallExpression(fn, args); } private ILogicalExpression normalize(ILogicalExpression expr, SequenceType type) throws SystemException { if (type.getItemType().isAtomicType()) { ILogicalExpression atomizedExpr = new ScalarFunctionCallExpression(BuiltinFunctions.FN_DATA_1, Collections.singletonList(mutable(expr))); AtomicType aType = (AtomicType) type.getItemType(); if (TypeUtils.isSubtypeTypeOf(aType, BuiltinTypeRegistry.XS_BOOLEAN)) { return new ScalarFunctionCallExpression(BuiltinFunctions.FN_BOOLEAN_1, Collections.singletonList(mutable(atomizedExpr))); } return promote(atomizedExpr, type); } else { return treat(expr, type); } } private ILogicalExpression promote(ILogicalExpression expr, SequenceType type) throws SystemException { int typeCode = currCtx.lookupSequenceType(type); return sfce(BuiltinOperators.PROMOTE, expr, ce(SequenceType.create(BuiltinTypeRegistry.XS_INT, Quantifier.QUANT_ONE), typeCode)); } private ILogicalExpression treat(ILogicalExpression expr, SequenceType type) throws SystemException { int typeCode = currCtx.lookupSequenceType(type); return sfce(BuiltinOperators.TREAT, expr, ce(SequenceType.create(BuiltinTypeRegistry.XS_INT, Quantifier.QUANT_ONE), typeCode)); } private ILogicalExpression cast(ILogicalExpression expr, SequenceType type) throws SystemException { int typeCode = currCtx.lookupSequenceType(type); return sfce(BuiltinOperators.CAST, expr, ce(SequenceType.create(BuiltinTypeRegistry.XS_INT, Quantifier.QUANT_ONE), typeCode)); } private ILogicalExpression castable(ILogicalExpression expr, SequenceType type) throws SystemException { int typeCode = currCtx.lookupSequenceType(type); return sfce(BuiltinOperators.CASTABLE, expr, ce(SequenceType.create(BuiltinTypeRegistry.XS_INT, Quantifier.QUANT_ONE), typeCode)); } private ILogicalExpression instanceOf(ILogicalExpression expr, SequenceType type) throws SystemException { int typeCode = currCtx.lookupSequenceType(type); return sfce(BuiltinOperators.INSTANCE_OF, expr, ce(SequenceType.create(BuiltinTypeRegistry.XS_INT, Quantifier.QUANT_ONE), typeCode)); } private List<LogicalVariable> translateExpressionList(List<ASTNode> expressions, TranslationContext tCtx) throws SystemException { List<LogicalVariable> result = new ArrayList<LogicalVariable>(); for (ASTNode e : expressions) { result.add(translateExpression(e, tCtx)); } return result; } private static Mutable<ILogicalExpression> mutable(ILogicalExpression expr) { return new MutableObject<ILogicalExpression>(expr); } private static Mutable<ILogicalOperator> mutable(ILogicalOperator op) { return new MutableObject<ILogicalOperator>(op); } private LogicalVariable newLogicalVariable() { return new LogicalVariable(varCounter++); } private class RootVariableScope implements IVariableScope { @Override public IVariableScope getParentScope() { return null; } @Override public XQueryVariable lookupVariable(QName name) { return moduleCtx.lookupVariable(name); } @Override public void registerVariable(XQueryVariable var) { moduleCtx.registerVariable(var); } } private class TranslationContext { private final TranslationContext parent; private ILogicalOperator op; private IVariableScope varScope; public TranslationContext(TranslationContext parent, ILogicalOperator op) { this.parent = parent; this.op = op; varScope = parent == null ? rootVarScope : parent.varScope; } TranslationContext pushContext() { SubplanOperator sOp = new SubplanOperator(); sOp.getInputs().add(mutable(op)); op = sOp; NestedTupleSourceOperator ntsOp = new NestedTupleSourceOperator(mutable(sOp)); TranslationContext childCtx = new TranslationContext(this, ntsOp); return childCtx; } TranslationContext popContext() { SubplanOperator sOp = (SubplanOperator) parent.op; sOp.setRootOp(mutable(op)); return parent; } void pushVariableScope() { varScope = new ExpressionVariableScope(varScope); } void popVariableScope() { varScope = varScope.getParentScope(); } } private interface IVariableScope { public IVariableScope getParentScope(); public XQueryVariable lookupVariable(QName name); public void registerVariable(XQueryVariable var); } private static class ExpressionVariableScope implements IVariableScope { private final IVariableScope parent; private final Map<QName, XQueryVariable> varMap; public ExpressionVariableScope(IVariableScope parent) { this.parent = parent; varMap = new HashMap<QName, XQueryVariable>(); } @Override public IVariableScope getParentScope() { return parent; } @Override public XQueryVariable lookupVariable(QName name) { if (varMap.containsKey(name)) { return varMap.get(name); } return parent.lookupVariable(name); } @Override public void registerVariable(XQueryVariable var) { varMap.put(var.getName(), var); } } }