Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
import java.util.List;

import org.eclipse.rdf4j.query.algebra.Filter;
import org.eclipse.rdf4j.query.algebra.Join;
import org.eclipse.rdf4j.query.algebra.QueryModelNode;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.algebra.helpers.AbstractSimpleQueryModelVisitor;

/**
Expand Down Expand Up @@ -46,6 +48,37 @@ public void meet(Filter node) {
node.getArg().visit(this);
}

@Override
public void meet(Join node) throws RuntimeException {
TupleExpr leftArg = node.getLeftArg();
TupleExpr rightArg = node.getRightArg();

// INSERT clause is often a deeply nested join. Recursive approach may cause stack overflow. Attempt
// non-recursive (or at least less-recursive) approach first.
while (true) {
if (leftArg instanceof Join && !(rightArg instanceof Join)) {
rightArg.visit(this);

Join join = (Join) leftArg;
leftArg = join.getLeftArg();
rightArg = join.getRightArg();

} else if (rightArg instanceof Join && !(leftArg instanceof Join)) {
leftArg.visit(this);

Join join = (Join) rightArg;
leftArg = join.getLeftArg();
rightArg = join.getRightArg();

} else {
leftArg.visit(this);
rightArg.visit(this);
return;
}
}

}

@Override
public void meet(StatementPattern node) {
statementPatterns.add(node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,47 @@
*******************************************************************************/
package org.eclipse.rdf4j.sail.memory;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;

import org.eclipse.rdf4j.common.transaction.IsolationLevels;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.testsuite.repository.RepositoryConnectionTest;
import org.junit.jupiter.api.Test;

public class MemoryStoreConnectionTest extends RepositoryConnectionTest {
@Override
protected Repository createRepository(File dataDir) {
return new SailRepository(new MemoryStore());
}

@Test
public void reallyBigUpdateToTriggerPotentialStackOverflowTest() {
setupTest(IsolationLevels.NONE);

IRI g1 = vf.createIRI("urn:test:g1");
testCon.begin();
testCon.add(vf.createBNode(), RDF.TYPE, g1);
testCon.commit();

testCon.begin();

StringBuilder bigUpdate = new StringBuilder();
bigUpdate.append("DELETE { ?s ?p ?o } INSERT{\n");

for (int i = 0; i < 20000; i++) {
bigUpdate.append(" [] <urn:test:prop> \"").append(i).append("\".\n");
}
bigUpdate.append("\n} WHERE { ?s ?p ?o }");

testCon.prepareUpdate(bigUpdate.toString()).execute();

long size = testCon.size();
assertThat(size).isEqualTo(20000);
testCon.commit();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand All @@ -40,6 +41,7 @@
import org.eclipse.rdf4j.model.impl.LinkedHashModel;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.util.Models;
import org.eclipse.rdf4j.model.vocabulary.CONFIG;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.repository.RepositoryReadOnlyException;
import org.eclipse.rdf4j.repository.config.ConfigTemplate;
Expand Down Expand Up @@ -143,12 +145,12 @@ private String getUserTemplates() {
*/
private String getBuiltinTemplates() {
// assume the templates are all located in the same jar "directory" as the RepositoryConfig class
Class cl = RepositoryConfig.class;
Class<RepositoryConfig> cl = RepositoryConfig.class;

try {
URI dir = cl.getResource(cl.getSimpleName() + ".class").toURI();
if (dir.getScheme().equals("jar")) {
try (FileSystem fs = FileSystems.newFileSystem(dir, Collections.EMPTY_MAP, null)) {
try (FileSystem fs = FileSystems.newFileSystem(dir, Collections.emptyMap(), null)) {
// turn package structure into directory structure
String pkg = cl.getPackage().getName().replaceAll("\\.", "/");
return getOrderedTemplates(fs.getPath(pkg));
Expand Down Expand Up @@ -187,15 +189,9 @@ private void createRepository(final String templateName) {
boolean eof = inputParameters(valueMap, variableMap, configTemplate.getMultilineMap());
if (!eof) {
final String configString = configTemplate.render(valueMap);
final Model graph = new LinkedHashModel();
final Model graph = parseConfigIntoModel(configString);

final RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE, SimpleValueFactory.getInstance());
rdfParser.setRDFHandler(new StatementCollector(graph));
rdfParser.parse(new StringReader(configString), RepositoryConfigSchema.NAMESPACE);

final Resource repositoryNode = Models
.subject(graph.getStatements(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY))
.orElseThrow(() -> new RepositoryConfigException("missing repository node"));
final Resource repositoryNode = findRepositoryNode(graph);

final RepositoryConfig repConfig = RepositoryConfig.create(graph, repositoryNode);
repConfig.validate();
Expand Down Expand Up @@ -232,6 +228,25 @@ private void createRepository(final String templateName) {
}
}

private Resource findRepositoryNode(final Model graph) {
Optional<Resource> modern = Models
.subject(graph.getStatements(null, RDF.TYPE, CONFIG.Rep.Repository));
Resource repositoryNode = modern
.orElseGet(() -> Models
.subject(graph.getStatements(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY))
.orElseThrow(() -> new RepositoryConfigException("missing repository node")));
return repositoryNode;
}

private Model parseConfigIntoModel(final String configString) throws IOException {
final Model graph = new LinkedHashModel();

final RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE, SimpleValueFactory.getInstance());
rdfParser.setRDFHandler(new StatementCollector(graph));
rdfParser.parse(new StringReader(configString), CONFIG.NAMESPACE);
return graph;
}

/**
* Ask user to specify values for the template variables
*
Expand All @@ -251,23 +266,7 @@ private boolean inputParameters(final Map<String, String> valueMap, final Map<St
final String var = entry.getKey();
final List<String> values = entry.getValue();

StringBuilder sb = new StringBuilder();
sb.append(var);

if (values.size() > 1) {
sb.append(" (");
for (int i = 0; i < values.size(); i++) {
if (i > 0) {
sb.append("|");
}
sb.append(values.get(i));
}
sb.append(")");
}
if (!values.isEmpty()) {
sb.append(" [" + values.get(0) + "]");
}
String prompt = sb.append(": ").toString();
String prompt = buildPromptString(values, var);
String value = multilineInput.containsKey(var) ? consoleIO.readMultiLineInput(prompt)
: consoleIO.readln(prompt);
eof = (value == null);
Expand All @@ -284,6 +283,25 @@ private boolean inputParameters(final Map<String, String> valueMap, final Map<St
return eof;
}

private String buildPromptString(final List<String> values, String var) {
StringBuilder sb = new StringBuilder();
sb.append(var);
if (values.size() > 1) {
sb.append(" (");
for (int i = 0; i < values.size(); i++) {
if (i > 0) {
sb.append("|");
}
sb.append(values.get(i));
}
sb.append(")");
}
if (!values.isEmpty()) {
sb.append(" [" + values.get(0) + "]");
}
return sb.append(": ").toString();
}

/**
* Create input stream from a template file in the specified file directory. If the file cannot be found, try to
* read it from the embedded java resources instead.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2018 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.console.command;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.eclipse.rdf4j.common.exception.RDF4JException;
import org.eclipse.rdf4j.console.ConsoleIO;
import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
* Test verify command
*
* @author Bart Hanssens
*/
public class CreateTest extends AbstractCommandTest {
private Create cmd;
private ConsoleIO io;

@BeforeEach
public void setUp() throws IOException, RDF4JException {
InputStream input = mock(InputStream.class);
OutputStream out = mock(OutputStream.class);
when(mockConsoleState.getDataDirectory()).thenReturn(locationFile);
when(mockConsoleState.getManager()).thenReturn(new LocalRepositoryManager(locationFile));

io = new ConsoleIO(input, out, mockConsoleState) {

@Override
public String readMultiLineInput(String promt) {
switch (promt) {
default:
return null;
}
}

@Override
public String readMultiLineInput() {
return null;
}

@Override
public String readln(String... message) {
switch (message[0]) {
case "Repository ID [memory]: ":
return "Y";
case "Repository title [Memory store]: ":
return "Create-Test-Memory-Store";
case "Query Iteration Cache sync threshold [10000]: ":
return "10";
case "Persist (true|false) [true]: ":
return "false";
case "Sync delay [0]: ":
return "0";
case "Query Evaluation Mode (STRICT|STANDARD) [STRICT]: ":
return "STANDARD";
}
return null;
}

@Override
public boolean askProceed(String msg, boolean defaultValue) {
return true;
}

};

cmd = new Create(io, mockConsoleState);
}

@Test
public final void startCreate() {
cmd.execute("create", "memory");
assertFalse(io.wasErrorWritten());
}

}
Loading