Skip to content

Commit

Permalink
QuaQue is now on Iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
JPugetGil committed Oct 31, 2024
1 parent d3ad657 commit fd96d45
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- '*'
- '!master'
- '!main'

jobs:
test:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package fr.cnrs.liris.jpugetgil.converg;

import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.engine.binding.BindingBuilder;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.*;
import java.util.function.Consumer;

public class BindingIterator implements Iterator<Binding> {
private final ResultSet resultSet;
private final ResultSetMetaData rsmd;
private final List<String> allVariables = new ArrayList<>();
private final List<String> variables = new ArrayList<>();
private final Set<Var> vars = new HashSet<>();

public BindingIterator(ResultSet resultSet) throws SQLException {
this.resultSet = resultSet;
this.rsmd = resultSet.getMetaData();
buildAllVariablesAndVariables();
}

public Set<Var> getVars() {
return vars;
}

@Override
public Binding next() {
try {
resultSet.next();

BindingBuilder bindingBuilder = Binding.builder();

for (String v : variables) {
Var variable = Var.alloc(v);
Node variableValue;

try {
if (hasColumn(resultSet, "name$" + v) && resultSet.getString("name$" + v) != null) {
String value = resultSet.getString("name$" + v);
String valueType;
if (allVariables.contains("type$" + v)) {
valueType = resultSet.getString("type$" + v);
} else {
valueType = getAssociatedRDFType(rsmd.getColumnType(resultSet.findColumn("name$" + v)));
}
variableValue = valueType == null ?
NodeFactory.createURI(value) : NodeFactory.createLiteral(value, NodeFactory.getType(valueType));
} else if (hasColumn(resultSet, v) && resultSet.getString(v) != null) {
String value = resultSet.getString(v);
String valueType = getAssociatedRDFType(rsmd.getColumnType(resultSet.findColumn(v)));
variableValue = NodeFactory.createLiteral(value, NodeFactory.getType(valueType));
} else {
variableValue = null;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}

if (variableValue != null) {
bindingBuilder.add(variable, variableValue);
}
}

return bindingBuilder.build();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}

/**
* @return true if the iteration has more elements
*/
@Override
public boolean hasNext() {
try {
boolean hasNext = !resultSet.isLast();

if (!hasNext) {
resultSet.close();
}
return hasNext;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}

/**
*
*/
@Override
public void remove() {
Iterator.super.remove();
}

/**
* @param action The action to be performed for each element
*/
@Override
public void forEachRemaining(Consumer<? super Binding> action) {
while (hasNext()) {
action.accept(next());
}
}

private void buildAllVariablesAndVariables() throws SQLException {
int nbColumns = rsmd.getColumnCount();
for (int i = 1; i <= nbColumns; i++) {
String columnName = rsmd.getColumnName(i);
allVariables.add(columnName);

if (columnName.startsWith("name$")) {
String variableName = columnName.substring(5);
variables.add(variableName);
Var var = Var.alloc(variableName);
vars.add(var);
} else if (!columnName.startsWith("type$")) {
variables.add(columnName);
Var var = Var.alloc(columnName);
vars.add(var);
}
}
}

private boolean hasColumn(java.sql.ResultSet rs, String columnName) {
try {
rs.findColumn(columnName);
return true;
} catch (SQLException e) {
return false;
}
}

private String getAssociatedRDFType(int sqlType) {
// Implement this method to map SQL types to RDF types
// For example:
switch (sqlType) {
case Types.INTEGER:
return XSDDatatype.XSDinteger.getURI();
case Types.VARCHAR:
return XSDDatatype.XSDstring.getURI();
// Add more cases as needed
default:
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;


public abstract class SPARQLLanguageTranslator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,68 +67,20 @@ public ResultSet translateAndExecSelect(Query query) {
log.info("[Measure] (Query translation duration): {} ns for query: {};", end - start, query);
log.info("Query result: {};", qu.getSql());

Long startExec = System.nanoTime();
try (java.sql.ResultSet rs = jdbcConnection.executeSQL(qu.getSql())) {
try {
Long startExec = System.nanoTime();
java.sql.ResultSet rs = jdbcConnection.executeSQL(qu.getSql());
Long endExec = System.nanoTime();
log.info("[Measure] (Query execution duration): {} ns for query: {};", endExec - startExec, query);

// Change the List implementation to the Iterator one (heap space)
Set<Var> vars = new HashSet<>();
List<Binding> bindings = new ArrayList<>();

while (Objects.requireNonNull(rs).next()) {
ResultSetMetaData rsmd = rs.getMetaData();
List<String> allVariables = new ArrayList<>();
List<String> variables = new ArrayList<>();
int nbColumns = rsmd.getColumnCount();
for (int i = 1; i <= nbColumns; i++) {
String columnName = rsmd.getColumnName(i);
allVariables.add(columnName);
if (columnName.startsWith("name$")) {
variables.add(columnName.substring(5));
} else if (!columnName.startsWith("type$")) {
variables.add(columnName);
}
}

BindingBuilder bindingBuilder = Binding.builder();
for (String v : variables) {
Var variable = Var.alloc(v);
Node variableValue;

if (hasColumn(rs, "name$" + v) && rs.getString("name$" + v) != null) {
String value = rs.getString("name$" + v);
String valueType;
if (allVariables.contains("type$" + v)) {
valueType = rs.getString("type$" + v);
} else {
valueType = getAssociatedRDFType(rsmd.getColumnType(rs.findColumn("name$" + v)));
}
variableValue = valueType == null ?
NodeFactory.createURI(value) : NodeFactory.createLiteral(value, NodeFactory.getType(valueType));
} else if (hasColumn(rs, v) && rs.getString(v) != null) {
String value = rs.getString(v);
String valueType = getAssociatedRDFType(rsmd.getColumnType(rs.findColumn(v)));
variableValue = NodeFactory.createLiteral(value, NodeFactory.getType(valueType));
} else {
variableValue = null;
}

vars.add(variable);

if (variableValue != null) {
bindingBuilder.add(variable, variableValue);
}
}

bindings.add(bindingBuilder.build());
}
BindingIterator bindingIterator = new BindingIterator(rs);

return ResultSetStream.create(new ArrayList<>(vars), bindings.iterator());
Set<Var> vars = bindingIterator
.getVars();

return ResultSetStream.create(new ArrayList<>(vars), bindingIterator);
} catch (SQLException e) {
log.error(e.getMessage());
throw new ARQException(e);
throw new RuntimeException(e);
}
}

Expand Down Expand Up @@ -260,27 +212,4 @@ private SQLContext addURIsToContext(OpBGP opBGP, SQLContext context) {

return context;
}

private boolean hasColumn(java.sql.ResultSet rs, String columnName) throws SQLException {
try {
rs.findColumn(columnName);
return true;
} catch (SQLException e) {
return false;
}
}

private String getAssociatedRDFType(int sqlType) {
// Implement this method to map SQL types to RDF types
// For example:
switch (sqlType) {
case Types.INTEGER:
return XSDDatatype.XSDinteger.getURI();
case Types.VARCHAR:
return XSDDatatype.XSDstring.getURI();
// Add more cases as needed
default:
return null;
}
}
}

0 comments on commit fd96d45

Please sign in to comment.