All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jena.tdb.store.GraphTDB Maven / Gradle / Ivy

Go to download

TDB is a storage subsystem for Jena and ARQ, it is a native triple store providing persistent storage of triples/quads.

There is a newer version: 4.10.0
Show newest version
/*
 * 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.tdb.store ;

import java.util.Iterator ;
import java.util.function.Function;

import org.apache.jena.atlas.iterator.Iter ;
import org.apache.jena.atlas.lib.Closeable ;
import org.apache.jena.atlas.lib.Sync ;
import org.apache.jena.atlas.lib.tuple.Tuple ;
import org.apache.jena.atlas.lib.tuple.TupleFactory ;
import org.apache.jena.graph.GraphEvents ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.Triple ;
import org.apache.jena.riot.other.GLib ;
import org.apache.jena.riot.system.RiotLib;
import org.apache.jena.shared.PrefixMapping ;
import org.apache.jena.sparql.core.DatasetGraph ;
import org.apache.jena.sparql.core.DatasetPrefixStorage ;
import org.apache.jena.sparql.core.GraphView ;
import org.apache.jena.sparql.core.Quad ;
import org.apache.jena.system.Txn;
import org.apache.jena.tdb.TDBException ;
import org.apache.jena.tdb.store.nodetupletable.NodeTupleTable ;
import org.apache.jena.tdb.transaction.DatasetGraphTransaction;
import org.apache.jena.util.iterator.ExtendedIterator ;
import org.apache.jena.util.iterator.WrappedIterator ;

/**
 * General operations for TDB graphs
 * (free-standing graph, default graph and named graphs)
 */
public abstract class GraphTDB extends GraphView implements Closeable, Sync {
    public GraphTDB(DatasetGraph dataset, Node graphName) {
        super(dataset, graphName) ;
    }

    private String graphNameStr() {
        if ( getGraphName() == null )   return DatasetPrefixesTDB.unnamedGraphURI;
        if ( getGraphName().isURI() )   return getGraphName().getURI();
        if ( getGraphName().isBlank() ) return RiotLib.blankNodeToIri(getGraphName()).getURI();
        throw new TDBException("Bad node for graph name: "+getGraphName());
    }
    
    /** Return the associated DatasetGraphTDB.
     * For non-transactional, that's the base storage.
     * For transactional, it is the current transaction wrapper {@link DatasetGraphTDB}.
     * 

* Immediate validity only. * Not valid across transaction boundaries, nor non-transactional to transactional. */ public abstract DatasetGraphTDB getDatasetGraphTDB() ; /** Return the {@link DatasetGraphTransaction}. * If this wrapping a base {@link DatasetGraphTDB}, return null. */ public abstract DatasetGraphTransaction getDatasetGraphTransaction() ; /** Return the associated base DatasetGraphTDB storage, not the transactional level. * Internal use only. Use with great care. *

* Immediate validity only. */ protected abstract DatasetGraphTDB getBaseDatasetGraphTDB() ; protected DatasetPrefixStorage getPrefixStorage() { return getDatasetGraphTDB().getPrefixes() ; } /** The NodeTupleTable for this graph - valid only inside the transaction or non-transactional. */ public NodeTupleTable getNodeTupleTable() { return getDatasetGraphTDB().chooseNodeTupleTable(getGraphName()) ; } // JENA-1527. Don't let GraphBase cache. // Normally, GraphBase calls createPrefixMapping once and reuses that object. // This causes it to be passed across transaction boundaries. // in the case of fetching, then not using for update in a W transaction, // errors occur. // // In TDB1, prefix mapping are limited in usage scope to the transaction. // The issue of the DatasetPrefixStorage. // (Could improve with PrefixMapping that gets the underlying PrefixeMapping each time). @Override public PrefixMapping getPrefixMapping() { return createPrefixMapping(); } @Override protected PrefixMapping createPrefixMapping() { boolean txnMode = getDatasetGraphTransaction() != null && getDatasetGraphTransaction().getStoreConnection().haveUsedInTransaction() ; if ( ! txnMode ) return createPrefixMapping$(); return Txn.calculateRead(getDataset(),()-> createPrefixMapping$()); } private PrefixMapping createPrefixMapping$() { DatasetPrefixStorage dsgPrefixes = getDatasetGraphTDB().getPrefixes() ; if ( isDefaultGraph() ) return dsgPrefixes.getPrefixMapping() ; if ( isUnionGraph() ) return dsgPrefixes.getPrefixMapping() ; return dsgPrefixes.getPrefixMapping(getGraphName().getURI()) ; } @Override public final void sync() { getDatasetGraphTDB().sync(); } @Override final public void close() { sync() ; // Don't close the dataset. super.close() ; } @Override protected ExtendedIterator graphUnionFind(Node s, Node p, Node o) { Iterator iterQuads = getDatasetGraphTDB().find(Quad.unionGraph, s, p, o) ; Iterator iter = GLib.quads2triples(iterQuads) ; // Suppress duplicates after projecting to triples. // TDB guarantees that duplicates are adjacent. // See SolverLib. iter = Iter.distinctAdjacent(iter) ; return WrappedIterator.createNoRemove(iter) ; } @Override protected final int graphBaseSize() { if ( isDefaultGraph() ) return (int)getNodeTupleTable().size() ; Node gn = getGraphName() ; boolean unionGraph = isUnionGraph(gn) ; gn = unionGraph ? Node.ANY : gn ; QuadTable quadTable = getDatasetGraphTDB().getQuadTable() ; Iterator> iter = quadTable.getNodeTupleTable().findAsNodeIds(gn, null, null, null) ; if ( unionGraph ) { iter = Iter.map(iter, project4TupleTo3Tuple) ; iter = Iter.distinctAdjacent(iter) ; } return (int)Iter.count(iter) ; } private static Function, Tuple> project4TupleTo3Tuple = item -> { if (item.len() != 4) throw new TDBException("Expected a Tuple of 4, got: " + item); return TupleFactory.tuple(item.get(1), item.get(2), item.get(3)); }; @Override public void clear() { // Logically, this is "super.clear()" except the default implementation // is a loop that materializes nodes. We want to call the dataset directly // so that nodes don't get materialized, just deleted from indexes. getDataset().deleteAny(getGraphName(), Node.ANY, Node.ANY, Node.ANY) ; getEventManager().notifyEvent(this, GraphEvents.removeAll) ; } @Override public void remove(Node s, Node p, Node o) { if ( getEventManager().listening() ) { // Have to do it the hard way so that triple events happen. super.remove(s, p, o) ; return ; } getDatasetGraphTDB().deleteAny(getGraphName(), s, p, o) ; // We know no one is listening ... // getEventManager().notifyEvent(this, GraphEvents.remove(s, p, o) ) ; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy