Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions .github/workflows/run-qt3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@ jobs:
with:
script: |
const workflowId = 'run-qt3.yml';
const branch = context.eventName === 'pull_request'
const isPullRequest = context.eventName === 'pull_request';
const defaultBranch = context.payload.repository.default_branch;
const branch = isPullRequest
? context.payload.pull_request.base.ref
: context.ref.replace('refs/heads/', '');
const event = 'push';
const event = !isPullRequest || branch === defaultBranch
? 'push'
: 'pull_request';
Comment thread
CaiJimmy marked this conversation as resolved.

const runs = await github.paginate(github.rest.actions.listWorkflowRuns, {
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: workflowId,
branch,
event,
status: 'completed',
per_page: 100
});

Expand All @@ -57,6 +60,10 @@ jobs:
);
}

runs.sort(
(a, b) => new Date(b.created_at) - new Date(a.created_at)
);

let baselineRun = null;
for (const run of runs) {
if (run.conclusion !== 'success') {
Expand All @@ -74,8 +81,8 @@ jobs:
const baselineRunId = baselineRun ? String(baselineRun.id) : '';
core.info(
baselineRunId
? `Using baseline run ${baselineRunId} from branch ${branch}.`
: `No successful baseline run with unexpired QT3 artifacts found for branch ${branch}.`
? `Using baseline run ${baselineRunId} from ${event} on branch ${branch}.`
: `No successful ${event} baseline run with unexpired QT3 artifacts found for branch ${branch}.`
);
core.setOutput('baseline_run_id', baselineRunId);

Expand Down Expand Up @@ -104,15 +111,15 @@ jobs:

qt3-jsoniq:
needs: [resolve-baseline, build]
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@master
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@jimmy/xml-schema
Comment thread
CaiJimmy marked this conversation as resolved.
with:
tested_parser: jsoniq
rumble_artifact_name: rumble-build
baseline_run_id: ${{ needs.resolve-baseline.outputs.baseline_run_id }}

qt3-xquery:
needs: [resolve-baseline, build]
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@master
uses: RumbleDB/rumble-test-suite/.github/workflows/qt3-suite.yml@jimmy/xml-schema
with:
tested_parser: xquery
rumble_artifact_name: rumble-build
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/org/rumbledb/compiler/CloneVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.rumbledb.expressions.module.LibraryModule;
import org.rumbledb.expressions.module.MainModule;
import org.rumbledb.expressions.module.Prolog;
import org.rumbledb.expressions.module.SchemaImport;
import org.rumbledb.expressions.module.TypeDeclaration;
import org.rumbledb.expressions.module.VariableDeclaration;
import org.rumbledb.expressions.postfix.ArrayLookupExpression;
Expand Down Expand Up @@ -90,6 +91,7 @@
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.IsStaticallyExpression;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.xml.AttributeNodeContentExpression;
import org.rumbledb.expressions.xml.AttributeNodeExpression;
Expand Down Expand Up @@ -135,18 +137,33 @@ public Node visitLibraryModule(LibraryModule module, Node argument) {

@Override
public Node visitProlog(Prolog expression, Node argument) {
List<SchemaImport> schemaImports = expression.getSchemaImports().stream()
.map(schemaImport -> (SchemaImport) visit(schemaImport, argument))
.collect(Collectors.toList());
List<LibraryModule> libraryModules = expression.getImportedModules().stream()
.map(libraryModule -> (LibraryModule) visit(libraryModule, argument))
.collect(Collectors.toList());
List<Node> declarations = expression.getDeclarations().stream()
.map(expr -> visit(expr, argument))
.collect(Collectors.toList());
expression.setDeclarations(declarations);
expression.getSchemaImports().clear();
expression.getSchemaImports().addAll(schemaImports);
expression.getImportedModules().clear();
expression.getImportedModules().addAll(libraryModules);
return expression;
}

@Override
public Node visitSchemaImport(SchemaImport schemaImport, Node argument) {
return new SchemaImport(
schemaImport.getTargetNamespace(),
schemaImport.getBindingKind(),
schemaImport.getPrefix(),
schemaImport.getLocationHints(),
schemaImport.getMetadata());
}

@Override
public Node visitProgram(Program program, Node argument) {
StatementsAndOptionalExpr statementsAndOptionalExpr =
Expand Down Expand Up @@ -1143,6 +1160,19 @@ public Node visitValidateTypeExpression(ValidateTypeExpression expression, Node
return result;
}

@Override
public Node visitValidateExpression(ValidateExpression expression, Node argument) {
Expression result = new ValidateExpression(
(Expression) visit(expression.getMainExpression(), argument),
expression.getValidationMode(),
expression.getTypeName(),
expression.getMetadata());
result.setStaticContext(expression.getStaticContext());
result.setStaticSequenceType(expression.getStaticSequenceType());
result.setSequential(expression.isSequential());
return result;
}

// region scripting
@Override
public Node visitApplyStatement(ApplyStatement statement, Node argument) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import org.rumbledb.expressions.scripting.statement.StatementsAndExpr;
import org.rumbledb.expressions.scripting.statement.StatementsAndOptionalExpr;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.update.CopyDeclaration;
import org.rumbledb.expressions.update.TransformExpression;
Expand Down Expand Up @@ -691,6 +692,13 @@ public StaticContext visitValidateTypeExpression(ValidateTypeExpression expressi
}
}

@Override
public StaticContext visitValidateExpression(ValidateExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
expression.setHighestExecutionMode(ExecutionMode.LOCAL);
return argument;
}

@Override
public StaticContext visitRangeExpr(RangeExpression rangeExpression, StaticContext argument) {
visitDescendants(rangeExpression, argument);
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/rumbledb/compiler/InferTypeVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.IsStaticallyExpression;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.update.AppendExpression;
import org.rumbledb.expressions.update.CopyDeclaration;
Expand Down Expand Up @@ -2543,6 +2544,13 @@ public StaticContext visitValidateTypeExpression(ValidateTypeExpression expressi
return argument;
}

@Override
public StaticContext visitValidateExpression(ValidateExpression expression, StaticContext argument) {
visitDescendants(expression, expression.getStaticContext());
expression.setStaticSequenceType(expression.getMainExpression().getStaticSequenceType());
return argument;
}

// endregion
//
// // begin scripting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.rumbledb.errorcodes.ErrorCode;
import org.rumbledb.exceptions.ExceptionMetadata;
import org.rumbledb.exceptions.OurBadException;
import org.rumbledb.exceptions.UnsupportedFeatureException;
import org.rumbledb.expressions.AbstractNodeVisitor;
import org.rumbledb.expressions.CommaExpression;
import org.rumbledb.expressions.ExecutionMode;
Expand Down Expand Up @@ -119,6 +120,7 @@
import org.rumbledb.expressions.typing.CastableExpression;
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.update.AppendExpression;
import org.rumbledb.expressions.update.CopyDeclaration;
Expand Down Expand Up @@ -1480,6 +1482,12 @@ public ItemRuntimePlan visitValidateTypeExpression(ValidateTypeExpression expres
return resultIterator;
}

@Override
public ItemRuntimePlan visitValidateExpression(ValidateExpression expression, ItemRuntimePlan argument) {
throw new UnsupportedFeatureException(
"XML Schema validate expressions are not executable yet.", expression.getMetadata());
}

@Override

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be implemented in the upcoming PRs.

public ItemRuntimePlan visitTreatExpression(TreatExpression expression, ItemRuntimePlan argument) {
ItemRuntimePlan childExpression = this.visit(expression.getMainExpression(), argument);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
import org.rumbledb.expressions.typing.CastableExpression;
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.update.CopyDeclaration;
import org.rumbledb.expressions.update.TransformExpression;
Expand Down Expand Up @@ -474,6 +475,12 @@ public StaticContext visitValidateTypeExpression(ValidateTypeExpression expressi
return argument;
}

@Override
public StaticContext visitValidateExpression(ValidateExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
return argument;
}

@Override
public StaticContext visitCastExpression(CastExpression expression, StaticContext argument) {
visitDescendants(expression, argument);
Expand Down
17 changes: 14 additions & 3 deletions src/main/java/org/rumbledb/compiler/TranslationVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.IsStaticallyExpression;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.update.AppendExpression;
import org.rumbledb.expressions.update.CopyDeclaration;
Expand Down Expand Up @@ -1565,9 +1566,19 @@ public Node visitValueExpr(JsoniqParser.ValueExprContext ctx) {

@Override
public Node visitValidateExpr(JsoniqParser.ValidateExprContext ctx) {
Expression mainExpr = (Expression) this.visitExpr(ctx.expr());
SequenceType sequenceType = this.processSequenceType(ctx.sequenceType());
return new ValidateTypeExpression(mainExpr, true, sequenceType, createMetadataFromContext(ctx));
Expression mainExpression = (Expression) this.visitExpr(ctx.expr());
if (ctx.sequenceType() != null) {
// TODO: This is a compatibility hack to support JSONiq validate expression, which has a different semantics
// than XQuery validate expression
SequenceType sequenceType = this.processSequenceType(ctx.sequenceType());
return new ValidateTypeExpression(mainExpression, true, sequenceType, createMetadataFromContext(ctx));
}

ValidateExpression.ValidationMode validationMode = ValidateExpression.ValidationMode.STRICT;
if (ctx.validationMode() != null && ctx.validationMode().KW_LAX() != null) {
validationMode = ValidateExpression.ValidationMode.LAX;
}
return new ValidateExpression(mainExpression, validationMode, null, createMetadataFromContext(ctx));
}
// endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
import org.rumbledb.expressions.module.MainModule;
import org.rumbledb.expressions.module.OptionDeclaration;
import org.rumbledb.expressions.module.Prolog;
import org.rumbledb.expressions.module.SchemaImport;
import org.rumbledb.expressions.module.SchemaImport.BindingKind;
import org.rumbledb.expressions.module.TypeDeclaration;
import org.rumbledb.expressions.module.VariableDeclaration;
import org.rumbledb.expressions.postfix.DynamicFunctionCallExpression;
Expand Down Expand Up @@ -137,7 +139,8 @@
import org.rumbledb.expressions.typing.InstanceOfExpression;
import org.rumbledb.expressions.typing.IsStaticallyExpression;
import org.rumbledb.expressions.typing.TreatExpression;
import org.rumbledb.expressions.typing.ValidateTypeExpression;
import org.rumbledb.expressions.typing.ValidateExpression;
import org.rumbledb.expressions.typing.ValidateExpression.ValidationMode;
import org.rumbledb.expressions.xml.AttributeNodeContentExpression;
import org.rumbledb.expressions.xml.AttributeNodeExpression;
import org.rumbledb.expressions.xml.CommentNodeConstructorExpression;
Expand Down Expand Up @@ -355,8 +358,10 @@ public Node visitLibraryModule(XQueryParser.LibraryModuleContext ctx) {
@Override
public Node visitProlog(XQueryParser.PrologContext ctx) {
List<LibraryModule> libraryModules = new ArrayList<>();
List<SchemaImport> schemaImports = new ArrayList<>();
List<OptionDeclaration> optionDeclarations = new ArrayList<>();
Set<String> namespaces = new HashSet<>();
Set<String> schemaNamespaces = new HashSet<>();
PrologPhase1Flags phase1 = new PrologPhase1Flags();
for (int ci = 0; ci < ctx.getChildCount(); ci++) {
ParseTree child = ctx.getChild(ci);
Expand All @@ -372,8 +377,18 @@ public Node visitProlog(XQueryParser.PrologContext ctx) {
processNamespaceDecl(namespaceDeclContext);
} else if (child instanceof SetterContext setterContext) {
processPrologPhase1Setter(setterContext, phase1);
} else if (child instanceof XQueryParser.SchemaImportContext) {
// Not supported yet; previously skipped as well.
} else if (child instanceof XQueryParser.SchemaImportContext schemaImportContext) {
SchemaImport schemaImport = translateSchemaImport(schemaImportContext);
if (!schemaNamespaces.add(schemaImport.getTargetNamespace())) {
throw new SemanticException(
"The schema namespace "
+ schemaImport.getTargetNamespace()
+ " is imported more than once.",
ErrorCode.DuplicateSchemaImportErrorCode,
createMetadataFromContext(schemaImportContext));
}
bindSchemaImportNamespace(schemaImport);
schemaImports.add(schemaImport);
} else if (child instanceof XQueryParser.ModuleImportContext namespace) {
LibraryModule libraryModule = this.processModuleImport(namespace);
libraryModules.add(libraryModule);
Expand Down Expand Up @@ -445,12 +460,57 @@ public Node visitProlog(XQueryParser.PrologContext ctx) {
for (LibraryModule libraryModule : libraryModules) {
prolog.addImportedModule(libraryModule);
}
for (SchemaImport schemaImport : schemaImports) {
prolog.addSchemaImport(schemaImport);
}
for (OptionDeclaration optionDeclaration : optionDeclarations) {
prolog.addDeclaration(optionDeclaration);
}
return prolog;
}

private SchemaImport translateSchemaImport(XQueryParser.SchemaImportContext ctx) {
String targetNamespace = URILiteralUtils.normalizeAsAnyURI(processURILiteral(ctx.nsURI));
BindingKind bindingKind = BindingKind.NONE;
String prefix = null;
if (ctx.schemaPrefix() != null) {
if (ctx.schemaPrefix().ncName() != null) {
bindingKind = BindingKind.PREFIX;
prefix = ctx.schemaPrefix().ncName().getText();
} else {
bindingKind = BindingKind.DEFAULT_ELEMENT_NAMESPACE;
}
}
List<String> locationHints = ctx.locations.stream()
.map(this::processURILiteral)
.map(URILiteralUtils::normalizeAsAnyURI)
.collect(Collectors.toList());
return new SchemaImport(targetNamespace, bindingKind, prefix, locationHints, createMetadataFromContext(ctx));
}

private void bindSchemaImportNamespace(SchemaImport schemaImport) {
if (schemaImport.getBindingKind() == BindingKind.NONE) {
return;
}
String namespace = schemaImport.getTargetNamespace();
if (schemaImport.getBindingKind() == BindingKind.DEFAULT_ELEMENT_NAMESPACE) {
bindNamespace("", namespace, schemaImport.getMetadata());
return;
}
String prefix = schemaImport.getPrefix();
if (namespace.isEmpty()) {
throw new SemanticException(
"A schema import cannot bind a prefix to a zero-length target namespace.",
ErrorCode.SchemaImportWithoutTargetNamespaceErrorCode,
schemaImport.getMetadata());
}
if (prefix.equals("xml") || prefix.equals("xmlns")) {
throw new PredefinedPrefixInNamespaceDeclarationException(
"Schema import prefix " + prefix + " is reserved.", schemaImport.getMetadata());
}
bindNamespace(prefix, namespace, schemaImport.getMetadata());
}

@Override
public Node visitOptionDecl(XQueryParser.OptionDeclContext ctx) {
Name name = parseEqName(ctx.name, false, false, false, false);
Expand Down Expand Up @@ -1485,10 +1545,16 @@ public Node visitValueExpr(XQueryParser.ValueExprContext ctx) {

@Override
public Node visitValidateExpr(XQueryParser.ValidateExprContext ctx) {
Expression mainExpr = (Expression) this.visitExpr(ctx.expr());
SequenceType sequenceType = this.processSequenceType(ctx.sequenceType());
return new ValidateTypeExpression(mainExpr, true, sequenceType, createMetadataFromContext(ctx));
// TODO: this is not implemented in XQuery. Throw an unsupported feature exception.
Expression mainExpression = (Expression) this.visitExpr(ctx.expr());
ValidationMode validationMode = ValidationMode.STRICT;
Name typeName = null;
if (ctx.validationMode() != null && ctx.validationMode().KW_LAX() != null) {
validationMode = ValidationMode.LAX;
} else if (ctx.KW_TYPE() != null) {
validationMode = ValidationMode.TYPE;
typeName = parseEqName(ctx.typeName().eqName(), false, true, false, false);
}
return new ValidateExpression(mainExpression, validationMode, typeName, createMetadataFromContext(ctx));
}
// endregion

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/rumbledb/errorcodes/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ public String toString() {
public static final ErrorCode NamespaceDoesNotMatchModule = registerBuiltIn("XQST0048");
public static final ErrorCode VariableAlreadyExists = registerBuiltIn("XQST0049");
public static final ErrorCode UnknownCastTypeErrorCode = registerBuiltIn("XQST0052");
public static final ErrorCode SchemaImportWithoutTargetNamespaceErrorCode = registerBuiltIn("XQST0057");
public static final ErrorCode DuplicateSchemaImportErrorCode = registerBuiltIn("XQST0058");
public static final ErrorCode MoreThanOneCopyNamespacesDeclarationErrorCode = registerBuiltIn("XQST0055");
public static final ErrorCode ModuleNotFoundErrorCode = registerBuiltIn("XQST0059");
public static final ErrorCode MoreThanOneBoundarySpaceDeclarationErrorCode = registerBuiltIn("XQST0068");
Expand Down
Loading