org.apache.jena.sdb.layout2.SQLBridge2 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-sdb Show documentation
Show all versions of jena-sdb Show documentation
SDB is a persistence layer for use with Apache Jena that uses an SQL database to store triples/quads.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.sdb.layout2;
import java.sql.ResultSet ;
import java.sql.SQLException ;
import java.util.Collection ;
import org.apache.jena.datatypes.RDFDatatype ;
import org.apache.jena.datatypes.TypeMapper ;
import org.apache.jena.datatypes.xsd.XSDDatatype ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.NodeFactory ;
import org.apache.jena.sdb.compiler.SqlBuilder ;
import org.apache.jena.sdb.core.AliasesSql ;
import org.apache.jena.sdb.core.SDBRequest ;
import org.apache.jena.sdb.core.Scope ;
import org.apache.jena.sdb.core.ScopeEntry ;
import org.apache.jena.sdb.core.sqlexpr.S_Equal ;
import org.apache.jena.sdb.core.sqlexpr.SqlColumn ;
import org.apache.jena.sdb.core.sqlexpr.SqlExpr ;
import org.apache.jena.sdb.core.sqlnode.SqlNode ;
import org.apache.jena.sdb.core.sqlnode.SqlTable ;
import org.apache.jena.sdb.sql.ResultSetJDBC ;
import org.apache.jena.sdb.sql.SQLUtils ;
import org.apache.jena.sdb.store.SQLBridgeBase ;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.engine.binding.BindingFactory ;
import org.apache.jena.sparql.engine.binding.BindingMap ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
public class SQLBridge2 extends SQLBridgeBase
{
private static Logger log = LoggerFactory.getLogger(SQLBridge2.class) ;
// Result nodes tables
private static final String NodeBase = AliasesSql.NodesResultAliasBase ;
//private Generator genNodeResultAlias = null ;
public SQLBridge2(SDBRequest request, SqlNode sqlNode, Collection projectVars)
{
super(request, sqlNode, projectVars) ;
}
@Override
protected void buildValues()
{
SqlNode sqlNode = getSqlNode() ;
for ( Var v : getProject() )
sqlNode = insertValueGetter(request, sqlNode, v) ;
setSqlNode(sqlNode) ;
}
@Override
protected void buildProject()
{
for ( Var v : getProject() )
{
if ( ! v.isNamedVar() )
continue ;
ScopeEntry e = getSqlNode().getNodeScope().findScopeForVar(v) ;
if ( e == null )
{
// Should be a column mentioned in the SELECT which is not mentioned in this block
continue ;
}
SqlColumn vCol = e.getColumn() ;
SqlTable table = vCol.getTable() ;
String sqlVarName = allocSqlName(v) ;
// Need to allocate aliases because otherwise we need to access
// "table.column" as a label and "." is illegal in a label
String vLex = SQLUtils.gen(sqlVarName,"lex") ;
// Call overrideable helper method for lex column (Oracle)
SqlColumn cLex = getLexSqlColumn(table);
String vLexNChar = SQLUtils.gen(sqlVarName,"lexNChar") ;
// Call overrideable helper method for lex column (Oracle)
SqlColumn cLexNChar = getLexNCharSqlColumn(table);
String vDatatype = SQLUtils.gen(sqlVarName,"datatype") ;
SqlColumn cDatatype = new SqlColumn(table, "datatype") ;
String vLang = SQLUtils.gen(sqlVarName,"lang") ;
SqlColumn cLang = new SqlColumn(table, "lang") ;
String vType = SQLUtils.gen(sqlVarName,"type") ;
SqlColumn cType = new SqlColumn(table, "type") ;
addProject(cLex, vLex) ;
// Oracle NCLOB support
if (cLexNChar != null) {
addProject(cLexNChar, vLexNChar);
}
addProject(cDatatype, vDatatype) ;
addProject(cLang, vLang) ;
addProject(cType, vType) ;
addAnnotation(sqlVarName+"="+v.toString()) ;
}
setAnnotation() ;
}
/**
* Intended to be overridden by an Oracle-specific impl to handle nclob selection.
* @see SQLBridge2Oracle
* @param table
*
*/
protected SqlColumn getLexSqlColumn(SqlTable table) {
return new SqlColumn(table, "lex") ;
}
/**
* Intended to be overridden by an Oracle-specific impl to handle nclob
* alternate selection
* @see SQLBridge2Oracle
* @param table
* @return SqlColumn
*/
protected SqlColumn getLexNCharSqlColumn(SqlTable table) {
return null;
}
private SqlNode insertValueGetter(SDBRequest request, SqlNode sqlNode, Var var)
{
ScopeEntry e1 = sqlNode.getIdScope().findScopeForVar(var) ;
if ( e1 == null )
{
// Debug.
Scope scope = sqlNode.getIdScope() ;
// Variable not actually in results.
return sqlNode ;
}
// Already in scope (from a condition)?
ScopeEntry e2 = sqlNode.getNodeScope().findScopeForVar(var) ;
if ( e2 != null )
// Already there
return sqlNode ;
SqlColumn c1 = e1.getColumn() ;
// Not in scope -- add a table to get it
TableDescNodes nodeTableDesc = request.getStore().getNodeTableDesc() ;
String tableAlias = request.genId(NodeBase) ;
SqlTable nTable = new SqlTable(tableAlias, nodeTableDesc.getTableName()) ;
String nodeKeyColName = nodeTableDesc.getNodeRefColName() ;
SqlColumn c2 = new SqlColumn(nTable, nodeKeyColName) ;
nTable.setValueColumnForVar(var, c2) ;
// Condition for value: triple table column = node table id/hash
nTable.addNote("Var: "+var) ;
SqlExpr cond = new S_Equal(c1, c2) ;
SqlNode n = SqlBuilder.leftJoin(request, sqlNode, nTable, cond) ;
return n ;
}
@Override
protected Binding assembleBinding(ResultSetJDBC rsHolder, Binding parent)
{
BindingMap b = BindingFactory.create(parent) ;
ResultSet rs = rsHolder.get() ;
for ( Var v : super.getProject() )
{
if ( ! v.isNamedVar() )
// Skip bNodes and system variables
continue ;
String codename = super.getSqlName(v) ;
if ( codename == null )
// Not mentioned in query.
continue ;
try {
int type = rs.getInt(SQLUtils.gen(codename,"type")) ;
// returns 0 on null : type 0 is not allocated
// Test with "wasNull()" for safety
if ( rs.wasNull() )
continue ;
String lexColName = SQLUtils.gen(codename,"lex") ;
// Get lexical - overriden by Oracle-specific code.
String lex = getLexFromResultSet(rs, codename);
// String lex = rs.getString(lexColName) ;
if ( lex == null )
lex = "" ;
String datatype = rs.getString(SQLUtils.gen(codename,"datatype")) ;
String lang = rs.getString(SQLUtils.gen(codename,"lang")) ;
ValueType vType = ValueType.lookup(type) ;
Node r = makeNode(lex, datatype, lang, vType) ;
b.add(v, r) ;
} catch (SQLException ex)
{ // Unknown variable?
//log.warn("Not reconstructed: "+n) ;
}
}
return b ;
}
protected String getLexFromResultSet(ResultSet rs, String codename)
throws SQLException
{
String lex = rs.getString(SQLUtils.gen(codename,"lex")) ;
if ( lex == null )
lex = "" ;
return lex;
}
private static Node makeNode(String lex, String datatype, String lang, ValueType vType)
{
switch (vType)
{
case BNODE:
return NodeFactory.createBlankNode(lex) ;
case URI:
return NodeFactory.createURI(lex) ;
case STRING:
return NodeFactory.createLiteral(lex, lang) ;
case XSDSTRING:
return NodeFactory.createLiteral(lex, XSDDatatype.XSDstring) ;
case INTEGER:
return NodeFactory.createLiteral(lex, XSDDatatype.XSDinteger) ;
case DOUBLE:
return NodeFactory.createLiteral(lex, XSDDatatype.XSDdouble) ;
case DATETIME:
return NodeFactory.createLiteral(lex, XSDDatatype.XSDdateTime) ;
case OTHER:
RDFDatatype dt = TypeMapper.getInstance().getSafeTypeByName(datatype);
return NodeFactory.createLiteral(lex, dt) ;
default:
log.warn("Unrecognized: ("+lex+", "+lang+", "+vType+")") ;
return NodeFactory.createLiteral("UNRECOGNIZED") ;
}
}
}