diff --git a/exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g b/exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g index f5f3cb0209a..188804f1e33 100644 --- a/exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g +++ b/exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g @@ -180,6 +180,7 @@ imaginaryTokenDefinitions PRAGMA GTEQ SEQUENCE + INSERT_TARGET ; // === XPointer === @@ -238,7 +239,7 @@ moduleDecl throws XPathException // === Prolog === prolog throws XPathException -{ boolean inSetters = true; } +{ boolean inSetters = true; boolean redeclaration = false; } : ( ( @@ -263,8 +264,17 @@ prolog throws XPathException ( "declare" "context" "item" ) => contextItemDeclUp { inSetters = false; } | - ( "declare" MOD ) + // bare keyword updating is valid because of rule CompatibilityAnnotation in the XQUF standard + ( "declare" (MOD | "updating") ) => annotateDecl { inSetters = false; } + | + ( "declare" "revalidation" ) + => revalidationDecl { + inSetters = false; + if(redeclaration) + throw new XPathException((XQueryAST) returnAST, ErrorCodes.XUST0003, "It is a static error if a Prolog contains more than one revalidation declaration."); + redeclaration = true; + } ) SEMICOLON! )* @@ -454,6 +464,17 @@ annotation : MOD! name=eqName! (LPAREN! literal (COMMA! literal)* RPAREN!)? { #annotation= #(#[ANNOT_DECL, name], #annotation); } + + | "updating"! + { + name = "updating"; + #annotation= #(#[ANNOT_DECL, name], #annotation); + } + ; + +revalidationDecl throws XPathException +: + "declare"! "revalidation"^ ("strict" | "lax" | "skip") ; eqName returns [String name] @@ -574,7 +595,7 @@ itemType throws XPathException : ( "item" LPAREN ) => "item"^ LPAREN! RPAREN! | - ( "function" LPAREN ) => functionTest + ( ("function" LPAREN) | ( MOD ) ) => functionTest | ( "map" LPAREN ) => mapType | @@ -609,20 +630,23 @@ atomicType throws XPathException functionTest throws XPathException : - ( "function" LPAREN STAR RPAREN) => anyFunctionTest - | - typedFunctionTest + annotations + ( + ( "function" LPAREN STAR RPAREN ) => anyFunctionTest + | + typedFunctionTest + ) ; anyFunctionTest throws XPathException : - "function"! LPAREN! s:STAR RPAREN! + annotations "function"! LPAREN! s:STAR RPAREN! { #anyFunctionTest = #(#[FUNCTION_TEST, "anyFunction"], #s); } ; typedFunctionTest throws XPathException : - "function"! LPAREN! (sequenceType (COMMA! sequenceType)*)? RPAREN! "as" sequenceType + annotations "function"! LPAREN! (sequenceType (COMMA! sequenceType)*)? RPAREN! "as" sequenceType { #typedFunctionTest = #(#[FUNCTION_TEST, "anyFunction"], #typedFunctionTest); } ; @@ -697,6 +721,12 @@ exprSingle throws XPathException | ( "switch" LPAREN ) => switchExpr | ( "typeswitch" LPAREN ) => typeswitchExpr | ( "update" ( "replace" | "value" | "insert" | "delete" | "rename" )) => updateExpr + | ( "insert" ( "node" | "nodes" ) ) => xqufInsertExpr + | ( "delete" ( "node" | "nodes" ) ) => xqufDeleteExpr + | ( "replace" ( "value" | "node" ) ) => xqufReplaceExpr + | ( "rename" "node" ) => xqufRenameExpr + | ( "copy" DOLLAR ) => copyModifyExpr + | ( "invoke" "updating" ) => dynamicUpdFunCall | orExpr ; @@ -740,6 +770,50 @@ renameExpr throws XPathException "rename" exprSingle "as"! exprSingle ; +xqufInsertExpr throws XPathException +: + "insert"^ ( "node"! | "nodes"! ) exprSingle + insertExprTargetChoice exprSingle + ; + +insertExprTargetChoice throws XPathException +{ String target = null; } +: + ( + ( ( "as"! ( "first"! { target = "first"; } | "last"! { target = "last"; } ) )? "into"! { + if (target == null) + target = "into"; + } ) + | "after"! { target = "after"; } + | "before"! { target = "before"; } + ) + { #insertExprTargetChoice= #(#[INSERT_TARGET, target]); } + +; + +xqufDeleteExpr throws XPathException +: + "delete"^ ( "node"! | "nodes"! ) exprSingle + ; + +xqufReplaceExpr throws XPathException +: + "replace"^ ("value" "of"!)? "node"! exprSingle "with"! exprSingle + ; + +xqufRenameExpr throws XPathException +: + "rename"^ "node"! exprSingle "as"! exprSingle + ; + +copyModifyExpr throws XPathException +: + "copy"^ letVarBinding ( COMMA! letVarBinding )* + "modify"! exprSingle + "return"! exprSingle + ; + + // === try/catch === tryCatchExpr throws XPathException : @@ -1005,7 +1079,7 @@ castableExpr throws XPathException castExpr throws XPathException : - arrowExpr ( "cast"^ "as"! singleType )? + transformWithExpr ( "cast"^ "as"! singleType )? ; comparisonExpr throws XPathException @@ -1274,11 +1348,27 @@ postfixExpr throws XPathException )* ; +dynamicUpdFunCall throws XPathException +: + "invoke"! "updating"^ primaryExpr ( argumentList )* + ; + arrowExpr throws XPathException : unaryExpr ( ARROW_OP^ arrowFunctionSpecifier argumentList )* ; + +// This is not perfectly adherent to the standard grammar +// at https://www.w3.org/TR/xquery-31/#prod-xquery31-ArrowExpr +// but the standard XQuery 3.1 grammar conflicts with the XQuery Update Facility 3.0 grammar +// https://www.w3.org/TR/xquery-update-30/#prod-xquery30-TransformWithExpr +// However, the end behavior should be identical +transformWithExpr throws XPathException +: + arrowExpr ( "transform"^ "with"! LCURLY! ( expr )? RCURLY! )? + ; + arrowFunctionSpecifier throws XPathException { String name= null; } : @@ -2228,6 +2318,32 @@ reservedKeywords returns [String name] "empty-sequence" { name = "empty-sequence"; } | "schema-element" { name = "schema-element"; } + | + "updating" { name = "updating"; } + | + "revalidation" { name = "revalidation"; } + | + "strict" { name = "strict"; } + | + "lax" { name = "lax"; } + | + "skip" { name = "skip"; } + | + "transform" { name = "transform"; } + | + "invoke" { name = "invoke"; } + | + "nodes" { name = "nodes"; } + | + "first" { name = "first"; } + | + "last" { name = "last"; } + | + "after" { name = "after"; } + | + "before" { name = "before"; } + | + "copy" { name = "copy"; } ; /** diff --git a/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g b/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g index e965f13c295..22e78774c35 100644 --- a/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g +++ b/exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g @@ -53,6 +53,7 @@ header { import org.exist.xquery.value.*; import org.exist.xquery.functions.fn.*; import org.exist.xquery.update.*; + import org.exist.xquery.update.legacy.*; import org.exist.storage.ElementValue; import org.exist.xquery.functions.map.MapExpr; import org.exist.xquery.functions.array.ArrayConstructor; @@ -146,7 +147,7 @@ options { String ns = qname.getNamespaceURI(); if (ns.equals(Namespaces.XPATH_FUNCTIONS_NS)) { String ln = qname.getLocalPart(); - return ("private".equals(ln) || "public".equals(ln)); + return ("private".equals(ln) || "public".equals(ln) || "updating".equals(ln) || "simple".equals(ln)); } else { return !(ns.equals(Namespaces.XML_NS) || ns.equals(Namespaces.SCHEMA_NS) @@ -156,7 +157,7 @@ options { } } - private static void processAnnotations(List annots, FunctionSignature signature) { + private static Annotation[] processAnnotations(List annots, FunctionSignature signature) { Annotation[] anns = new Annotation[annots.size()]; //iterate the declare Annotations @@ -182,7 +183,11 @@ options { } //set the Annotations on the Function Signature - signature.setAnnotations(anns); + if (signature != null) { + signature.setAnnotations(anns); + } + + return anns; } private static void processParams(List varList, UserDefinedFunction func, FunctionSignature signature) @@ -499,6 +504,24 @@ throws PermissionDeniedException, EXistException, XPathException { List annots = new ArrayList(); } (annotations [annots] )? + { + for(int i = 0; i < annots.size(); i++) + { + List la = (List) annots.get(i); + if(la.size() > 0) + { + for(int a = 0; a < la.size(); a++) + { + if(la.get(a).toString().equals("simple") || la.get(a).toString().equals("updating")) + { + throw new XPathException(qname, ErrorCodes.XUST0032, + "It is a static error if an %updating or %simple annotation is used on a VarDecl."); + } + } + } + } + + } ( #( "as" @@ -621,6 +644,26 @@ throws PermissionDeniedException, EXistException, XPathException functionDecl [path] | importDecl [path] + | + #( + "revalidation" + ( + "strict" + { + staticContext.setRevalidationMode(XQueryContext.RevalidationMode.STRICT); + } + | + "lax" + { + staticContext.setRevalidationMode(XQueryContext.RevalidationMode.LAX); + } + | + "skip" + { + staticContext.setRevalidationMode(XQueryContext.RevalidationMode.SKIP); + } + ) + ) )* ; @@ -1062,6 +1105,12 @@ throws XPathException } ) | + { List annots = new ArrayList(); } + (annotations [annots])? + { + Annotation[] anns = processAnnotations(annots, null); + type.setAnnotations(anns); + } #( FUNCTION_TEST { type.setPrimaryType(Type.FUNCTION_REFERENCE); } ( @@ -2146,6 +2195,20 @@ throws PermissionDeniedException, EXistException, XPathException step=numericExpr [path] | step=updateExpr [path] + | + step=xqufInsertExpr [path] + | + step=xqufDeleteExpr [path] + | + step=xqufReplaceExpr [path] + | + step=xqufRenameExpr [path] + | + step=transformWithExpr [path] + | + step=copyModifyExpr [path] + | + step=dynamicUpdFunCall [path] ; /** @@ -2966,6 +3029,37 @@ throws PermissionDeniedException, EXistException, XPathException ) ; +dynamicUpdFunCall [PathExpr path] +returns [Expression step] +throws PermissionDeniedException, EXistException, XPathException +{ + step = null; + PathExpr primary = new PathExpr(context); +} +: + #( + "updating" + { + List params = new ArrayList(5); + boolean isPartial = false; + } + step=primaryExpr [primary] + ( + ( + { PathExpr pathExpr = new PathExpr(context); } + expr [pathExpr] { params.add(pathExpr); } + ) + )* + { + DynamicFunctionCall dynCall = new DynamicFunctionCall(context, step, params, isPartial); + dynCall.setCategory(Expression.Category.UPDATING); + step = dynCall; + path.add(step); + } + ) +; + + functionCall [PathExpr path] returns [Expression step] throws PermissionDeniedException, EXistException, XPathException @@ -3553,6 +3647,92 @@ throws PermissionDeniedException, EXistException, XPathException ) ; + +transformWithExpr [PathExpr path] +returns [Expression step] +throws PermissionDeniedException, EXistException, XPathException +{ + step= null; + CopyModifyExpression cpme = new CopyModifyExpression(context); + QName virtualVariable = null; +}: + #( + tr:"transform" + { + PathExpr transformExpr = new PathExpr(context); + } + t:expr [transformExpr] + { + try { + virtualVariable = QName.parse(staticContext, "virtualCopyModifyName", null); + } + catch (final IllegalQNameException e) { + // this should never happen, since it is a virtual QName + } + + final VariableDeclaration decl = new VariableDeclaration(context, virtualVariable, transformExpr); + decl.setASTNode(t); + + cpme.addCopySource("virtualCopyModifyName", decl); + } + { + PathExpr withExpr = new PathExpr(context); + } + ( + expr [withExpr] + )? + { + // see https://www.w3.org/TR/xquery-update-30/#id-transform-with for explanation + // in short TransformWith is a shorthand notation for a common Copy Modify Expression + + PathExpr refExpr = new PathExpr(context); + refExpr.add(new VariableReference(context, virtualVariable)); + cpme.setModifyExpr(new OpSimpleMap(context, refExpr, withExpr)); + cpme.setReturnExpr(refExpr); + + cpme.setASTNode(tr); + path.add(cpme); + step = cpme; + } + ) + ; + +copyModifyExpr [PathExpr path] +returns [Expression step] +throws PermissionDeniedException, EXistException, XPathException +{ + step= null; + CopyModifyExpression cpme = new CopyModifyExpression(context); + PathExpr modify = new PathExpr(context); + PathExpr retExpr = new PathExpr(context); +}: + #( + cp:"copy" + ( + #( + copyVarName:VARIABLE_BINDING + { + PathExpr inputSequence= new PathExpr(context); + } + step=expr [inputSequence] + { + cpme.addCopySource(copyVarName.getText(), inputSequence); + } + ) + )+ + step=expr [modify] + step=expr [retExpr] + { + cpme.setModifyExpr(modify); + cpme.setReturnExpr(retExpr); + + cpme.setASTNode(cp); + path.add(cpme); + step = cpme; + } + ) + ; + typeCastExpr [PathExpr path] returns [Expression step] throws PermissionDeniedException, EXistException, XPathException @@ -3711,6 +3891,122 @@ throws XPathException, PermissionDeniedException, EXistException ) ; +xqufInsertExpr [PathExpr path] +returns [Expression step] +throws XPathException, PermissionDeniedException, EXistException +{ +}: + #( + insertAST:"insert" + { + PathExpr source = new PathExpr(context); + PathExpr target = new PathExpr(context); + InsertExpr.Choice choice = null; + } + step=expr [source] + #( + it:INSERT_TARGET + { + switch (it.getText()) { + case "first": + choice = InsertExpr.Choice.FIRST; + break; + case "last": + choice = InsertExpr.Choice.LAST; + break; + case "into": + choice = InsertExpr.Choice.INTO; + break; + case "before": + choice = InsertExpr.Choice.BEFORE; + break; + case "after": + choice = InsertExpr.Choice.AFTER; + break; + } + } + ) + step=expr [target] + { + InsertExpr insertExpr = new InsertExpr(context, source, target, choice); + insertExpr.setASTNode(insertAST); + path.add(insertExpr); + step = insertExpr; + } + ) + ; + +xqufDeleteExpr [PathExpr path] +returns [Expression step] +throws XPathException, PermissionDeniedException, EXistException +{ +}: + #( + deleteAST:"delete" + { + PathExpr target = new PathExpr(context); + } + step=expr [target] + { + DeleteExpr deleteExpr = new DeleteExpr(context, target); + deleteExpr.setASTNode(deleteAST); + path.add(deleteExpr); + step = deleteExpr; + } + ) + ; + +xqufReplaceExpr [PathExpr path] +returns [Expression step] +throws XPathException, PermissionDeniedException, EXistException +{ +}: + #( + replaceAST:"replace" + { + PathExpr target = new PathExpr(context); + PathExpr with = new PathExpr(context); + ReplaceExpr.ReplacementType replacementType = ReplaceExpr.ReplacementType.NODE; + } + ( + "value" + { + replacementType = ReplaceExpr.ReplacementType.VALUE; + } + )? + step=expr [target] + step=expr [with] + { + ReplaceExpr replaceExpr = new ReplaceExpr(context, target, with, replacementType); + replaceExpr.setASTNode(replaceAST); + path.add(replaceExpr); + step = replaceExpr; + } + ) + ; + +xqufRenameExpr [PathExpr path] +returns [Expression step] +throws XPathException, PermissionDeniedException, EXistException +{ +}: + #( + renameAST:"rename" + { + PathExpr target = new PathExpr(context); + PathExpr newName = new PathExpr(context); + } + step=expr [target] + step=expr [newName] + { + RenameExpr renameExpr = new RenameExpr(context, target, newName); + renameExpr.setASTNode(renameAST); + path.add(renameExpr); + step = renameExpr; + } + ) + ; + mapConstr [PathExpr path] returns [Expression step] throws XPathException, PermissionDeniedException, EXistException diff --git a/exist-core/src/main/java/org/exist/xquery/DynamicFunctionCall.java b/exist-core/src/main/java/org/exist/xquery/DynamicFunctionCall.java index 8478417cf5e..94ff7009fdb 100644 --- a/exist-core/src/main/java/org/exist/xquery/DynamicFunctionCall.java +++ b/exist-core/src/main/java/org/exist/xquery/DynamicFunctionCall.java @@ -35,9 +35,10 @@ public class DynamicFunctionCall extends AbstractExpression { private final Expression functionExpr; private final List arguments; private final boolean isPartial; - private AnalyzeContextInfo cachedContextInfo; + private Category category = Category.SIMPLE; + public DynamicFunctionCall(final XQueryContext context, final Expression fun, final List args, final boolean partial) { super(context); setLocation(fun.getLine(), fun.getColumn()); @@ -163,4 +164,14 @@ public String toString() { return builder.toString(); } + + + @Override + public Category getCategory() { + return this.category; + } + + public void setCategory(Category category) { + this.category = category; + } } diff --git a/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java b/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java index d916c2d6434..47c7c9c1c30 100644 --- a/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java +++ b/exist-core/src/main/java/org/exist/xquery/ErrorCodes.java @@ -239,6 +239,10 @@ public class ErrorCodes { public static final ErrorCode XTSE0165 = new W3CErrorCode("XTSE0165","It is a static error if the processor is not able to retrieve the resource identified by the URI reference [ in the href attribute of xsl:include or xsl:import] , or if the resource that is retrieved does not contain a stylesheet module conforming to this specification."); + /* XQuery 3.0 Update Facility https://www.w3.org/TR/xquery-update-30/#id-new-error-codes */ + public static final ErrorCode XUST0032 = new W3CErrorCode("XUST0032", "It is a static error if an %updating or %simple annotation is used on a VarDecl."); + public static final ErrorCode XUST0003 = new W3CErrorCode("XUST0003", "It is a static error if a Prolog contains more than one revalidation declaration."); + /* eXist specific XQuery and XPath errors * * Codes have the format [EX][XQ|XP][DY|SE|ST][nnnn] diff --git a/exist-core/src/main/java/org/exist/xquery/Expression.java b/exist-core/src/main/java/org/exist/xquery/Expression.java index 78404d39309..bfa091053b7 100644 --- a/exist-core/src/main/java/org/exist/xquery/Expression.java +++ b/exist-core/src/main/java/org/exist/xquery/Expression.java @@ -36,6 +36,16 @@ */ public interface Expression { + /** + * Updating expressions are a new category of expression introduced by XQuery Update Facility 3.0 + * An updating expression is an expression that can return a non-empty pending update list + * Simple expressions are all expressions that are not updating expressions + */ + enum Category { + UPDATING, + SIMPLE + } + // Flags to be passed to analyze: /** * Indicates that the query engine will call the expression once for every @@ -264,4 +274,6 @@ public interface Expression { * @return true if the next expression should be evaluated, false otherwise. */ boolean evalNextExpressionOnEmptyContextSequence(); -} \ No newline at end of file + + public default Category getCategory() { return Category.SIMPLE; }; +} diff --git a/exist-core/src/main/java/org/exist/xquery/XQueryContext.java b/exist-core/src/main/java/org/exist/xquery/XQueryContext.java index 6953d748945..0daabb14edb 100644 --- a/exist-core/src/main/java/org/exist/xquery/XQueryContext.java +++ b/exist-core/src/main/java/org/exist/xquery/XQueryContext.java @@ -91,7 +91,7 @@ import org.exist.xmldb.XmldbURI; import org.exist.xquery.parser.*; import org.exist.xquery.pragmas.*; -import org.exist.xquery.update.Modification; +import org.exist.xquery.update.legacy.Modification; import org.exist.xquery.util.SerializerUtils; import org.exist.xquery.value.*; import org.w3c.dom.Node; @@ -111,6 +111,7 @@ * * @author Wolfgang Meier */ + public class XQueryContext implements BinaryValueManager, Context { private static final Logger LOG = LogManager.getLogger(XQueryContext.class); @@ -412,6 +413,8 @@ public class XQueryContext implements BinaryValueManager, Context { private final Map staticDecimalFormats = hashMap(Tuple(UNNAMED_DECIMAL_FORMAT, DecimalFormat.UNNAMED)); + private RevalidationMode revalidationMode = RevalidationMode.LAX; + // Only used for testing, e.g. {@link org.exist.test.runner.XQueryTestRunner}. private Optional testRepository = Optional.empty(); @@ -3283,6 +3286,22 @@ public void registerBinaryValueInstance(final BinaryValue binaryValue) { binaryValueInstances.push(binaryValue); } + public enum RevalidationMode { + STRICT, + LAX, + SKIP + } + + /** + * Revalidation mode controls the process by which type information + * is recovered for an updated document + */ + public void setRevalidationMode(final RevalidationMode rev) { + this.revalidationMode = rev; + } + + public RevalidationMode getRevalidationMode() { return this.revalidationMode; } + /** * Cleanup Task which is responsible for relasing the streams * of any {@link BinaryValue} which have been used during diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBDefragment.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBDefragment.java index 0408777f828..7180b31b6ab 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBDefragment.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBDefragment.java @@ -33,7 +33,7 @@ import org.exist.xquery.FunctionSignature; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; -import org.exist.xquery.update.Modification; +import org.exist.xquery.update.legacy.Modification; import org.exist.xquery.value.FunctionParameterSequenceType; import org.exist.xquery.value.IntegerValue; import org.exist.xquery.value.Sequence; diff --git a/exist-core/src/main/java/org/exist/xquery/update/CopyModifyExpression.java b/exist-core/src/main/java/org/exist/xquery/update/CopyModifyExpression.java new file mode 100644 index 00000000000..05f088d12b2 --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/update/CopyModifyExpression.java @@ -0,0 +1,156 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import org.exist.xquery.*; +import org.exist.xquery.util.ExpressionDumper; +import org.exist.xquery.value.Item; +import org.exist.xquery.value.Sequence; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public class CopyModifyExpression extends PathExpr { + + public static class CopySource { + private String varName; + private Expression inputSequence; + + public String getVariable() { + return this.varName; + } + + public Expression getInputSequence() { + return this.inputSequence; + } + + public void setVariable(final String varName) { + this.varName = varName; + } + + public void setInputSequence(final Expression inputSequence) { + this.inputSequence = inputSequence; + } + + public CopySource(final String name, final Expression value) { + this.varName = name; + this.inputSequence = value; + } + + public CopySource() { + } + } + + + private List sources; + private Expression modifyExpr; + private Expression returnExpr; + + // see https://www.w3.org/TR/xquery-update-30/#id-copy-modify for details + public Category getCategory() { + // placeholder implementation + return Category.SIMPLE; + } + + public CopyModifyExpression(final XQueryContext context) { + super(context); + this.sources = new ArrayList<>(); + } + + public void addCopySource(final String varName, final Expression value) { + this.sources.add(new CopySource(varName, value)); + } + + public void setModifyExpr(final Expression expr) { + this.modifyExpr = expr; + } + + public Expression getModifyExpr() { + return this.modifyExpr; + } + + public void setReturnExpr(final Expression expr) { + this.returnExpr = expr; + } + + public Expression getReturnExpr() { + return this.returnExpr; + } + + @Override + public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException { + } + + @Override + public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { + return Sequence.EMPTY_SEQUENCE; + } + + @Override + public Cardinality getCardinality() { + return Cardinality.ONE_OR_MORE; + } + + @Override + public void dump(final ExpressionDumper dumper) { + dumper.display("copy").nl(); + dumper.startIndent(); + for (int i = 0; i < sources.size(); i++) { + dumper.display("$").display(sources.get(i).varName); + dumper.display(" := "); + sources.get(i).inputSequence.dump(dumper); + } + dumper.endIndent(); + dumper.display("modify").nl(); + modifyExpr.dump(dumper); + dumper.nl().display("return "); + dumper.startIndent(); + returnExpr.dump(dumper); + dumper.endIndent(); + } + + @Override + public String toString() { + final StringBuilder result = new StringBuilder(); + result.append("copy "); + for (int i = 0; i < sources.size(); i++) { + result.append("$").append(sources.get(i).varName); + result.append(sources.get(i).inputSequence.toString()); + if (sources.size() > 1 && i < sources.size() - 1) { + result.append(", "); + } else { + result.append(" "); + } + } + result.append(" "); + result.append("modify "); + result.append(modifyExpr.toString()); + result.append(" "); + result.append("return "); + result.append(returnExpr.toString()); + return result.toString(); + } +} diff --git a/exist-core/src/main/java/org/exist/xquery/update/DeleteExpr.java b/exist-core/src/main/java/org/exist/xquery/update/DeleteExpr.java new file mode 100644 index 00000000000..a7b948625cd --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/update/DeleteExpr.java @@ -0,0 +1,67 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import org.exist.xquery.AnalyzeContextInfo; +import org.exist.xquery.Expression; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.util.ExpressionDumper; +import org.exist.xquery.value.Item; +import org.exist.xquery.value.Sequence; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public class DeleteExpr extends ModifyingExpression { + + public DeleteExpr(final XQueryContext context, final Expression target) { + super(context, target); + } + + @Override + public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException { + + } + + @Override + public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { + return Sequence.EMPTY_SEQUENCE; + } + + public void dump(final ExpressionDumper dumper) { + dumper.display("delete").nl(); + dumper.startIndent(); + targetExpr.dump(dumper); + dumper.endIndent(); + } + + @Override + public String toString() { + final StringBuilder result = new StringBuilder(); + result.append("delete "); + result.append(" "); + result.append(targetExpr.toString()); + return result.toString(); + } +} diff --git a/exist-core/src/main/java/org/exist/xquery/update/InsertExpr.java b/exist-core/src/main/java/org/exist/xquery/update/InsertExpr.java new file mode 100644 index 00000000000..3ed1d4ccf36 --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/update/InsertExpr.java @@ -0,0 +1,96 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import org.exist.xquery.*; +import org.exist.xquery.util.ExpressionDumper; +import org.exist.xquery.value.Item; +import org.exist.xquery.value.Sequence; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public class InsertExpr extends ModifyingExpression { + public enum Choice { + FIRST, + LAST, + INTO, + AFTER, + BEFORE + } + + private final Expression sourceExpr; + private final Choice choice; + + public InsertExpr(final XQueryContext context, final Expression source, final Expression target, final Choice choice) { + super(context, target); + this.sourceExpr = source; + this.choice = choice; + } + + @Override + public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException { + } + + @Override + public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { + return Sequence.EMPTY_SEQUENCE; + } + + @Override + public Cardinality getCardinality() { + return Cardinality.ONE_OR_MORE; + } + + @Override + public void dump(final ExpressionDumper dumper) { + dumper.display("insert").nl(); + dumper.startIndent(); + sourceExpr.dump(dumper); + dumper.endIndent(); + dumper.display(choice).nl(); + dumper.startIndent(); + targetExpr.dump(dumper); + dumper.endIndent(); + } + + @Override + public String toString() { + final StringBuilder result = new StringBuilder(); + result.append("insert "); + result.append(sourceExpr.toString()); + result.append(" "); + result.append(choice.toString()); + result.append(" "); + result.append(targetExpr.toString()); + return result.toString(); + } + + public Choice getChoice() { + return choice; + } + + public Expression getSourceExpr() { + return sourceExpr; + } +} diff --git a/exist-core/src/main/java/org/exist/xquery/update/ModifyingExpression.java b/exist-core/src/main/java/org/exist/xquery/update/ModifyingExpression.java new file mode 100644 index 00000000000..9bb7f7ed49d --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/update/ModifyingExpression.java @@ -0,0 +1,55 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import org.exist.xquery.AbstractExpression; +import org.exist.xquery.Expression; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.value.Type; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public abstract class ModifyingExpression extends AbstractExpression { + + protected final Expression targetExpr; + + public ModifyingExpression(final XQueryContext context, final Expression target) { + super(context); + this.targetExpr = target; + } + + @Override + public int returnsType() { + // placeholder implementation + return Type.EMPTY; + } + + public Category getCategory() { + return Category.UPDATING; + } + + public Expression getTargetExpr() { + return targetExpr; + } +} diff --git a/exist-core/src/main/java/org/exist/xquery/update/RenameExpr.java b/exist-core/src/main/java/org/exist/xquery/update/RenameExpr.java new file mode 100644 index 00000000000..6d372d57b39 --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/update/RenameExpr.java @@ -0,0 +1,83 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import org.exist.xquery.AnalyzeContextInfo; +import org.exist.xquery.Cardinality; +import org.exist.xquery.Expression; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.util.ExpressionDumper; +import org.exist.xquery.value.Item; +import org.exist.xquery.value.Sequence; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public class RenameExpr extends ModifyingExpression { + private final Expression newNameExpr; + + public RenameExpr(final XQueryContext context, final Expression target, final Expression newName) { + super(context, target); + this.newNameExpr = newName; + } + + @Override + public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException { + } + + @Override + public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { + return Sequence.EMPTY_SEQUENCE; + } + + @Override + public Cardinality getCardinality() { + return Cardinality.ONE_OR_MORE; + } + + @Override + public void dump(final ExpressionDumper dumper) { + dumper.display("replace").nl(); + dumper.startIndent(); + targetExpr.dump(dumper); + dumper.endIndent(); + dumper.startIndent(); + newNameExpr.dump(dumper); + dumper.endIndent(); + } + + @Override + public String toString() { + final StringBuilder result = new StringBuilder(); + result.append("replace "); + result.append(targetExpr.toString()); + result.append(" "); + result.append(newNameExpr.toString()); + return result.toString(); + } + + public Expression getNewNameExpr() { + return newNameExpr; + } +} diff --git a/exist-core/src/main/java/org/exist/xquery/update/ReplaceExpr.java b/exist-core/src/main/java/org/exist/xquery/update/ReplaceExpr.java new file mode 100644 index 00000000000..621e039cf1a --- /dev/null +++ b/exist-core/src/main/java/org/exist/xquery/update/ReplaceExpr.java @@ -0,0 +1,97 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import org.exist.xquery.AnalyzeContextInfo; +import org.exist.xquery.Cardinality; +import org.exist.xquery.Expression; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.util.ExpressionDumper; +import org.exist.xquery.value.Item; +import org.exist.xquery.value.Sequence; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public class ReplaceExpr extends ModifyingExpression { + public enum ReplacementType { + NODE, + VALUE + } + + private final Expression withExpr; + private final ReplaceExpr.ReplacementType replacementType; + + public ReplaceExpr(final XQueryContext context, final Expression target, final Expression with, final ReplaceExpr.ReplacementType replacementType) { + super(context, target); + this.withExpr = with; + this.replacementType = replacementType; + } + + @Override + public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException { + } + + @Override + public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException { + return Sequence.EMPTY_SEQUENCE; + } + + @Override + public Cardinality getCardinality() { + return Cardinality.ONE_OR_MORE; + } + + @Override + public void dump(final ExpressionDumper dumper) { + dumper.display("replace").nl(); + dumper.startIndent(); + targetExpr.dump(dumper); + dumper.endIndent(); + dumper.display(replacementType).nl(); + dumper.startIndent(); + withExpr.dump(dumper); + dumper.endIndent(); + } + + @Override + public String toString() { + final StringBuilder result = new StringBuilder(); + result.append("replace "); + result.append(targetExpr.toString()); + result.append(" "); + result.append(replacementType.toString()); + result.append(" "); + result.append(withExpr.toString()); + return result.toString(); + } + + public ReplaceExpr.ReplacementType getReplacementType() { + return replacementType; + } + + public Expression getWithExpr() { + return withExpr; + } +} diff --git a/exist-core/src/main/java/org/exist/xquery/update/Delete.java b/exist-core/src/main/java/org/exist/xquery/update/legacy/Delete.java similarity index 99% rename from exist-core/src/main/java/org/exist/xquery/update/Delete.java rename to exist-core/src/main/java/org/exist/xquery/update/legacy/Delete.java index b6d19596785..923ee13a0b6 100644 --- a/exist-core/src/main/java/org/exist/xquery/update/Delete.java +++ b/exist-core/src/main/java/org/exist/xquery/update/legacy/Delete.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.exist.EXistException; import org.exist.collections.triggers.TriggerException; @@ -46,7 +46,6 @@ import org.exist.xquery.value.StringValue; import org.exist.xquery.value.Type; import org.exist.xquery.value.ValueSequence; -import org.w3c.dom.Attr; import org.w3c.dom.Node; /** diff --git a/exist-core/src/main/java/org/exist/xquery/update/Insert.java b/exist-core/src/main/java/org/exist/xquery/update/legacy/Insert.java similarity index 99% rename from exist-core/src/main/java/org/exist/xquery/update/Insert.java rename to exist-core/src/main/java/org/exist/xquery/update/legacy/Insert.java index 9d5f4e04e61..d96da1e2fbc 100644 --- a/exist-core/src/main/java/org/exist/xquery/update/Insert.java +++ b/exist-core/src/main/java/org/exist/xquery/update/legacy/Insert.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.exist.EXistException; import org.exist.Namespaces; diff --git a/exist-core/src/main/java/org/exist/xquery/update/Modification.java b/exist-core/src/main/java/org/exist/xquery/update/legacy/Modification.java similarity index 99% rename from exist-core/src/main/java/org/exist/xquery/update/Modification.java rename to exist-core/src/main/java/org/exist/xquery/update/legacy/Modification.java index b4d201e8b67..f13a147c7e0 100644 --- a/exist-core/src/main/java/org/exist/xquery/update/Modification.java +++ b/exist-core/src/main/java/org/exist/xquery/update/legacy/Modification.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import java.util.Iterator; @@ -351,4 +351,7 @@ protected Txn getTransaction() { return node.getParentNode(); } } + + @Override + public Category getCategory() { return Category.UPDATING; } } diff --git a/exist-core/src/main/java/org/exist/xquery/update/Rename.java b/exist-core/src/main/java/org/exist/xquery/update/legacy/Rename.java similarity index 99% rename from exist-core/src/main/java/org/exist/xquery/update/Rename.java rename to exist-core/src/main/java/org/exist/xquery/update/legacy/Rename.java index d5c7a77744a..e3cabf37457 100644 --- a/exist-core/src/main/java/org/exist/xquery/update/Rename.java +++ b/exist-core/src/main/java/org/exist/xquery/update/legacy/Rename.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.exist.EXistException; import org.exist.collections.triggers.TriggerException; diff --git a/exist-core/src/main/java/org/exist/xquery/update/Replace.java b/exist-core/src/main/java/org/exist/xquery/update/legacy/Replace.java similarity index 99% rename from exist-core/src/main/java/org/exist/xquery/update/Replace.java rename to exist-core/src/main/java/org/exist/xquery/update/legacy/Replace.java index 755b400af96..6d4ab0f715b 100644 --- a/exist-core/src/main/java/org/exist/xquery/update/Replace.java +++ b/exist-core/src/main/java/org/exist/xquery/update/legacy/Replace.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.exist.EXistException; import org.exist.collections.triggers.TriggerException; diff --git a/exist-core/src/main/java/org/exist/xquery/update/Update.java b/exist-core/src/main/java/org/exist/xquery/update/legacy/Update.java similarity index 99% rename from exist-core/src/main/java/org/exist/xquery/update/Update.java rename to exist-core/src/main/java/org/exist/xquery/update/legacy/Update.java index cc44a0a5b24..ba4638be3bd 100644 --- a/exist-core/src/main/java/org/exist/xquery/update/Update.java +++ b/exist-core/src/main/java/org/exist/xquery/update/legacy/Update.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,7 +32,6 @@ import org.exist.dom.persistent.StoredNode; import org.exist.dom.persistent.TextImpl; import org.exist.security.Permission; -import org.exist.security.PermissionDeniedException; import org.exist.storage.NotificationService; import org.exist.storage.UpdateListener; import org.exist.storage.txn.Txn; diff --git a/exist-core/src/main/java/org/exist/xquery/value/SequenceType.java b/exist-core/src/main/java/org/exist/xquery/value/SequenceType.java index 0ad7175f5bd..bac8c2964c2 100644 --- a/exist-core/src/main/java/org/exist/xquery/value/SequenceType.java +++ b/exist-core/src/main/java/org/exist/xquery/value/SequenceType.java @@ -22,6 +22,7 @@ package org.exist.xquery.value; import org.exist.dom.QName; +import org.exist.xquery.Annotation; import org.exist.xquery.Cardinality; import org.exist.xquery.Expression; import org.exist.xquery.XPathException; @@ -41,6 +42,8 @@ public class SequenceType { private Cardinality cardinality = Cardinality.EXACTLY_ONE; private QName nodeName = null; + private Annotation[] annotations; + public SequenceType() { } @@ -230,6 +233,13 @@ public void checkCardinality(Sequence seq) throws XPathException { } } + public void setAnnotations(final Annotation[] annotations) { + this.annotations = annotations; + } + public Annotation[] getAnnotations() { + return annotations; + } + @Override public String toString() { if (cardinality == Cardinality.EMPTY_SEQUENCE) { diff --git a/exist-core/src/test/java/org/exist/xquery/update/XQueryUpdate3Test.java b/exist-core/src/test/java/org/exist/xquery/update/XQueryUpdate3Test.java new file mode 100644 index 00000000000..ac44c8c89ca --- /dev/null +++ b/exist-core/src/test/java/org/exist/xquery/update/XQueryUpdate3Test.java @@ -0,0 +1,641 @@ +/* + * eXist-db Open Source Native XML Database + * Copyright (C) 2001 The eXist-db Authors + * + * info@exist-db.org + * http://www.exist-db.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.exist.xquery.update; + +import antlr.RecognitionException; +import antlr.TokenStreamException; +import org.exist.EXistException; +import org.exist.security.PermissionDeniedException; +import org.exist.storage.BrokerPool; +import org.exist.storage.DBBroker; +import org.exist.test.ExistEmbeddedServer; +import org.exist.xquery.*; +import org.exist.xquery.parser.XQueryAST; +import org.exist.xquery.parser.XQueryLexer; +import org.exist.xquery.parser.XQueryParser; +import org.exist.xquery.parser.XQueryTreeParser; +import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.SequenceType; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.StringReader; + +import static org.junit.Assert.*; + +/** + * @author Adam Retter + * @author Gabriele Tomassetti + */ +public class XQueryUpdate3Test { + + @ClassRule + public static final ExistEmbeddedServer existEmbeddedServer = new ExistEmbeddedServer(true, true); + + @Test + public void updatingCompatibilityAnnotation() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException { + final String query = + "xquery version \"3.0\"\n;" + + "module namespace t=\"http://exist-db.org/xquery/test/examples\";\n" + + "declare updating function" + + " t:upsert($e as element(), \n" + + " $an as xs:QName, \n" + + " $av as xs:anyAtomicType) \n" + + " {\n" + + " let $ea := $e/attribute()[fn:node-name(.) = $an]\n" + + " return\n" + + " $ea\n" + + " };"; + + final BrokerPool pool = BrokerPool.getInstance(); + try (final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + final XQueryContext context = new XQueryContext(broker.getBrokerPool()); + final XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + final XQueryParser xparser = new XQueryParser(lexer); + xparser.xpath(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + } + + final XQueryAST ast = (XQueryAST) xparser.getAST(); + final XQueryTreeParser treeParser = new XQueryTreeParser(context); + final PathExpr expr = new PathExpr(context); + treeParser.xpath(ast, expr); + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + } + } + } + + @Test + public void simpleAnnotation() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException { + final String query = + "xquery version \"3.0\"\n;" + + "module namespace t=\"http://exist-db.org/xquery/test/examples\";\n" + + "declare %simple function" + + " t:upsert($e as element(), \n" + + " $an as xs:QName, \n" + + " $av as xs:anyAtomicType) \n" + + " {\n" + + " let $ea := $e/attribute()[fn:node-name(.) = $an]\n" + + " return\n" + + " $ea\n" + + " };"; + + final BrokerPool pool = BrokerPool.getInstance(); + try (final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + final XQueryContext context = new XQueryContext(broker.getBrokerPool()); + final XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + final XQueryParser xparser = new XQueryParser(lexer); + xparser.xpath(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + final XQueryAST ast = (XQueryAST) xparser.getAST(); + final XQueryTreeParser treeParser = new XQueryTreeParser(context); + final PathExpr expr = new PathExpr(context); + treeParser.xpath(ast, expr); + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + } + } + } + + @Test + public void simpleAnnotationIsInvalidForVariableDeclaration() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "declare %simple variable $ab := 1;"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.prolog(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.prolog(ast, expr); + } + catch(XPathException ex) { + assertEquals(ErrorCodes.XUST0032, ex.getErrorCode()); + } + } + + @Test + public void testingForUpdatingFunction() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "%simple function ( * )"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.sequenceType(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + SequenceType type = new SequenceType(); + treeParser.sequenceType(ast, type); + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + } + } + + @Test + public void revalidationDeclaration() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "declare revalidation strict;"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.prolog(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.prolog(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + } + } + + @Test + public void transformWith() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "$e transform with { $e + 1 }\n"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + Expression ret = treeParser.expr(ast, expr); + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(ret instanceof CopyModifyExpression); + } + } + + @Test + public void copyModifyExprTest() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "copy $je := $e\n" + + " modify delete node $je/salary\n" + + " return $je"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + Expression ret = treeParser.expr(ast, expr); + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(ret instanceof CopyModifyExpression); + assertEquals("$je",((CopyModifyExpression) ret).getReturnExpr().toString()); + } + } + + @Test + public void copyModifyExprTestComplexModify() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "copy $newx := $oldx\n" + + " modify (rename node $newx as \"newx\", \n" + + " replace value of node $newx with $newx * 2)\n" + + " return ($oldx, $newx)"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + Expression ret = treeParser.expr(ast, expr); + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(ret instanceof CopyModifyExpression); + assertEquals("( replace $newx \"newx\", replace $newx VALUE $newx * 2 )",((CopyModifyExpression) ret).getModifyExpr().toString()); + assertEquals("( $oldx, $newx )",((CopyModifyExpression) ret).getReturnExpr().toString()); + } + } + + @Test + public void dynamicUpdatingFunctionCall() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = "let $f := fn:put#2\n" + + "return invoke updating $f(,\"newnode.xml\")"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.xpath(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.xpath(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(((DebuggableExpression) ((LetExpr)expr.getFirst()).getReturnExpression()).getFirst() instanceof DynamicFunctionCall); + DynamicFunctionCall dfc = (DynamicFunctionCall) ((DebuggableExpression) ((LetExpr)expr.getFirst()).getReturnExpression()).getFirst(); + assertEquals(Expression.Category.UPDATING, dfc.getCategory()); + } + } + + @Test + public void insertExpr() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "insert node 2005\n" + + " after book/publisher"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof InsertExpr); + assertEquals(Expression.Category.UPDATING, expr.getFirst().getCategory()); + assertEquals(InsertExpr.Choice.AFTER, ((InsertExpr) expr.getFirst()).getChoice()); + } + } + + @Test + public void insertExprAsLast() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "insert node $new-police-report\n" + + " as last into fn:doc(\"insurance.xml\")/policies\n" + + " /policy[id = $pid]\n" + + " /driver[license = $license]\n" + + " /accident[date = $accdate]\n" + + " /police-reports"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof InsertExpr); + assertEquals(Expression.Category.UPDATING, expr.getFirst().getCategory()); + assertEquals("$new-police-report", ((InsertExpr) expr.getFirst()).getSourceExpr().toString()); + assertEquals(InsertExpr.Choice.LAST, ((InsertExpr) expr.getFirst()).getChoice()); + } + } + + @Test + public void deleteExpr() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "delete node fn:doc(\"bib.xml\")/books/book[1]/author[last()]"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof DeleteExpr); + assertEquals(Expression.Category.UPDATING, expr.getFirst().getCategory()); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[1]/child::{}author[last()]", ((DeleteExpr) expr.getFirst()).getTargetExpr().toString()); + } + } + + @Test + public void deleteExprComplex() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "delete nodes /email/message\n" + + " [date > xs:dayTimeDuration(\"P365D\")]"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof DeleteExpr); + assertEquals(Expression.Category.UPDATING, expr.getFirst().getCategory()); + } + } + + @Test + public void replaceNodeExpr() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "replace node fn:doc(\"bib.xml\")/books/book[1]/publisher\n" + + "with fn:doc(\"bib.xml\")/books/book[2]/publisher"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof ReplaceExpr); + assertEquals(ReplaceExpr.ReplacementType.NODE,((ReplaceExpr) expr.getFirst()).getReplacementType()); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[1]/child::{}publisher",((ReplaceExpr) expr.getFirst()).getTargetExpr().toString()); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[2]/child::{}publisher",((ReplaceExpr) expr.getFirst()).getWithExpr().toString()); + } + } + + @Test + public void replaceValueExpr() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "replace value of node fn:doc(\"bib.xml\")/books/book[1]/price\n" + + "with fn:doc(\"bib.xml\")/books/book[1]/price * 1.1"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof ReplaceExpr); + assertEquals(ReplaceExpr.ReplacementType.VALUE,((ReplaceExpr) expr.getFirst()).getReplacementType()); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[1]/child::{}price",((ReplaceExpr) expr.getFirst()).getTargetExpr().toString()); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[1]/child::{}price * 1.1",((ReplaceExpr) expr.getFirst()).getWithExpr().toString()); + } + } + + @Test + public void renameExpr() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "rename node fn:doc(\"bib.xml\")/books/book[1]/author[1]\n" + + "as \"principal-author\""; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof RenameExpr); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[1]/child::{}author[1]",((RenameExpr) expr.getFirst()).getTargetExpr().toString()); + assertEquals("\"principal-author\"",((RenameExpr) expr.getFirst()).getNewNameExpr().toString()); + } + } + + @Test + public void renameExprWithExpr() throws EXistException, RecognitionException, XPathException, TokenStreamException, PermissionDeniedException + { + String query = + "rename node fn:doc(\"bib.xml\")/books/book[1]/author[1]\n" + + "as $newname"; + + BrokerPool pool = BrokerPool.getInstance(); + try(final DBBroker broker = pool.getBroker()) { + // parse the query into the internal syntax tree + XQueryContext context = new XQueryContext(broker.getBrokerPool()); + XQueryLexer lexer = new XQueryLexer(context, new StringReader(query)); + XQueryParser xparser = new XQueryParser(lexer); + xparser.expr(); + if (xparser.foundErrors()) { + fail(xparser.getErrorMessage()); + return; + } + + XQueryAST ast = (XQueryAST) xparser.getAST(); + + XQueryTreeParser treeParser = new XQueryTreeParser(context); + PathExpr expr = new PathExpr(context); + treeParser.expr(ast, expr); + + if (treeParser.foundErrors()) { + fail(treeParser.getErrorMessage()); + return; + } + + assertTrue(expr.getFirst() instanceof RenameExpr); + assertEquals("doc(\"bib.xml\")/child::{}books/child::{}book[1]/child::{}author[1]",((RenameExpr) expr.getFirst()).getTargetExpr().toString()); + assertEquals("$newname",((RenameExpr) expr.getFirst()).getNewNameExpr().toString()); + } + } +} diff --git a/exist-core/src/test/java/org/exist/xquery/update/AbstractTestUpdate.java b/exist-core/src/test/java/org/exist/xquery/update/legacy/AbstractTestUpdate.java similarity index 99% rename from exist-core/src/test/java/org/exist/xquery/update/AbstractTestUpdate.java rename to exist-core/src/test/java/org/exist/xquery/update/legacy/AbstractTestUpdate.java index a7886583684..674b8942212 100644 --- a/exist-core/src/test/java/org/exist/xquery/update/AbstractTestUpdate.java +++ b/exist-core/src/test/java/org/exist/xquery/update/legacy/AbstractTestUpdate.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.exist.TestUtils; import org.exist.test.ExistXmldbEmbeddedServer; diff --git a/exist-core/src/test/java/org/exist/xquery/update/IndexIntegrationTest.java b/exist-core/src/test/java/org/exist/xquery/update/legacy/IndexIntegrationTest.java similarity index 99% rename from exist-core/src/test/java/org/exist/xquery/update/IndexIntegrationTest.java rename to exist-core/src/test/java/org/exist/xquery/update/legacy/IndexIntegrationTest.java index fc1d0f1f716..a887b939887 100644 --- a/exist-core/src/test/java/org/exist/xquery/update/IndexIntegrationTest.java +++ b/exist-core/src/test/java/org/exist/xquery/update/legacy/IndexIntegrationTest.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.easymock.IArgumentMatcher; import org.easymock.IMocksControl; diff --git a/exist-core/src/test/java/org/exist/xquery/update/UpdateInsertTest.java b/exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateInsertTest.java similarity index 99% rename from exist-core/src/test/java/org/exist/xquery/update/UpdateInsertTest.java rename to exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateInsertTest.java index ac097ded063..80fe46387c8 100644 --- a/exist-core/src/test/java/org/exist/xquery/update/UpdateInsertTest.java +++ b/exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateInsertTest.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.junit.Test; import org.xmldb.api.base.XMLDBException; diff --git a/exist-core/src/test/java/org/exist/xquery/update/UpdateReplaceTest.java b/exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateReplaceTest.java similarity index 99% rename from exist-core/src/test/java/org/exist/xquery/update/UpdateReplaceTest.java rename to exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateReplaceTest.java index 2f390a68afa..30980e446a4 100644 --- a/exist-core/src/test/java/org/exist/xquery/update/UpdateReplaceTest.java +++ b/exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateReplaceTest.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.junit.Test; import org.w3c.dom.Document; diff --git a/exist-core/src/test/java/org/exist/xquery/update/UpdateValueTest.java b/exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateValueTest.java similarity index 98% rename from exist-core/src/test/java/org/exist/xquery/update/UpdateValueTest.java rename to exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateValueTest.java index e2894380d70..26f575c05ba 100644 --- a/exist-core/src/test/java/org/exist/xquery/update/UpdateValueTest.java +++ b/exist-core/src/test/java/org/exist/xquery/update/legacy/UpdateValueTest.java @@ -19,7 +19,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.exist.xquery.update; +package org.exist.xquery.update.legacy; import org.junit.Test; import org.xmldb.api.base.XMLDBException;