📄 rdfsource.java
字号:
/* Sesame - Storage and Querying architecture for RDF and RDF Schema * Copyright (C) 2001-2005 Aduna * * Contact: * Aduna * Prinses Julianaplein 14 b * 3817 CS Amersfoort * The Netherlands * tel. +33 (0)33 465 99 87 * fax. +33 (0)33 465 99 87 * * http://aduna.biz/ * http://www.openrdf.org/ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package org.openrdf.sesame.sailimpl.rdbms;import java.io.UnsupportedEncodingException;import java.math.BigInteger;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import org.openrdf.util.log.ThreadLog;import org.openrdf.model.BNode;import org.openrdf.model.Literal;import org.openrdf.model.Resource;import org.openrdf.model.Statement;import org.openrdf.model.URI;import org.openrdf.model.Value;import org.openrdf.model.ValueFactory;import org.openrdf.model.impl.StatementImpl;import org.openrdf.sesame.sail.NamespaceIterator;import org.openrdf.sesame.sail.SailInitializationException;import org.openrdf.sesame.sail.SailInternalException;import org.openrdf.sesame.sail.StatementIterator;import org.openrdf.sesame.sail.query.And;import org.openrdf.sesame.sail.query.BooleanExpr;import org.openrdf.sesame.sail.query.ConstructQuery;import org.openrdf.sesame.sail.query.LiteralExpr;import org.openrdf.sesame.sail.query.Not;import org.openrdf.sesame.sail.query.Null;import org.openrdf.sesame.sail.query.Or;import org.openrdf.sesame.sail.query.PathExpression;import org.openrdf.sesame.sail.query.GraphPattern;import org.openrdf.sesame.sail.query.GraphPatternQuery;import org.openrdf.sesame.sail.query.ProjectionElem;import org.openrdf.sesame.sail.query.Query;import org.openrdf.sesame.sail.query.QueryOptimizer;import org.openrdf.sesame.sail.query.ResourceExpr;import org.openrdf.sesame.sail.query.SetOperator;import org.openrdf.sesame.sail.query.SelectQuery;import org.openrdf.sesame.sail.query.TriplePattern;import org.openrdf.sesame.sail.query.ValueCompare;import org.openrdf.sesame.sail.query.ValueExpr;import org.openrdf.sesame.sail.query.Var;import org.openrdf.sesame.sail.util.EmptyStatementIterator;import org.openrdf.sesame.sailimpl.rdbms.iterators.RdbmsNamespaceIterator;import org.openrdf.sesame.sailimpl.rdbms.iterators.RdbmsStatementIterator;import org.openrdf.sesame.sailimpl.rdbms.model.IdBNode;import org.openrdf.sesame.sailimpl.rdbms.model.IdLiteral;import org.openrdf.sesame.sailimpl.rdbms.model.IdResource;import org.openrdf.sesame.sailimpl.rdbms.model.IdURI;import org.openrdf.sesame.sailimpl.rdbms.model.IdValue;/** * A portable implementation of the RdfSource interface for relational * databases, based on (a subset of) the SQL2/SQL92 standard. This class defines * the read-only methods, the subclass RdfRepository defines the update methods. * * @author Arjohn Kampman * @author Adam Skutt * @version $Revision: 1.46.2.2 $ */public class RdfSource implements org.openrdf.sesame.sail.RdfSource, TableNames, ValueFactory{/*----------+| Constants |+----------*/ /** Key used to store the schema version in the metadata table. **/ public static final String KEY_SCHEMAVERSION = "schemaversion"; /** Key used to store the schema creator in the metadata table. **/ public static final String KEY_SCHEMACREATOR = "schemacreator"; /** Key used to store the status of the export flags in the metadata table. **/ public static final String KEY_EXPORT_FLAGS = "exportflags"; /** Value used to indiate an "up-to-date" status in the metadata table. **/ public static final String VALUE_UP_TO_DATE = "up-to-date"; /** Value used to indiate an "dirty" status in the metadata table. **/ public static final String VALUE_DIRTY = "dirty"; /** Key used to specify a JDBC driver in the initialization parameters. **/ public static final String JDBC_DRIVER_KEY = "jdbcDriver"; /** Key used to specify a JDBC URL in the initialization parameters. **/ public static final String JDBC_URL_KEY = "jdbcUrl"; /** Key used to specify a username in the initialization parameters. **/ public static final String USER_KEY = "user"; /** Key used to specify a password in the initialization parameters. **/ public static final String PASSWORD_KEY = "password"; /** * Version of the database schema implemented by this RdfSource. 0 = * reserved number, indicating schemas before this versioning system was * implemented. The value of this 'constant' can be changed by subclasses of * this class. */ // 1: first schema version // 2: 'labelKey' column in literals table replaced with 'labelHash' column based on MD5 hash. // 3: new table 'expiredvalues' used to removed potentially expired values // 4: Renamed column of triples tables: subject --> subj, predicate --> pred, object --> obj // 5: Replaced 'expiredValues' table with 'expiredResources' and 'expiredLiterals' table protected int CURRENT_SCHEMA_VERSION; /** * Creator of the database schema. The value of this 'constant' can be * changed by subclasses of this class. */ protected String SCHEMA_CREATOR; /** * Equal to the string " NOT NULL" if the database leaves empty string as * they are, or equal to an empty string if the database converts empty * strings to NULL. This constant can be used for creating tables containing * text values that can be empty strings. */ protected String NN_ON_TEXT;/*----------+| Variables |+----------*/ /** * The version of the schema currently in the database. The version will be * equal after the schema has possibly been updated with a call to * _initDatabase(). The value '-1' indicates that the database doesn't have * a schema yet. */ protected int _schemaVersion; /** An object offering a collection of dbms-specific methods. **/ protected RDBMS _rdbms; /** MD5 digest object for calculating literal label keys. **/ protected MessageDigest _md5Digest; /** The prefix for any new bnode IDs. **/ private String _bnodePrefix; /** The ID for the next bnode that is created. **/ private int _nextBNodeID; /** The ID for the next namespace that is created. **/ protected int _nextNamespaceId; /* local cache of used namespaces. */ protected Map _namespaceTable; protected List _namespaceList; /** * Array storing namespace names using their id as the index for position in * the array. This array is for rapid retrieval of a namespace name using a * namespace id. */ protected String[] _namespaceNames; /** * Flag indicating whether the 'export' status of namespaces needs to be * updated before reporting them. An update of the export status normally * takes place the first time getNamespaces() is called after a transaction * has been committed. **/ private boolean _exportStatusUpToDate;/*-------------+| Constructors |+-------------*/ /** * Creates a new RdfSource object that will be able to read triples from an * RDF database. */ public RdfSource() { CURRENT_SCHEMA_VERSION = 5; SCHEMA_CREATOR = "org.openrdf.sesame.sailimpl.rdbms.RdfSource"; _updateBNodePrefix(); _nextNamespaceId = 1; _namespaceTable = new HashMap(); _namespaceList = new ArrayList(); try { _md5Digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { // Should never happen as MD5 should be available on every Java platform throw new RuntimeException( "MD5 digest algorithm not available on this platform", e); } } /** * Generates a new bnode prefix based on <tt>currentTimeMillis()</tt> and * resets <tt>_nextBNodeID</tt> to <tt>1</tt>. **/ protected void _updateBNodePrefix() { // BNode prefix is based on currentTimeMillis(). Combined with a // sequential number per session, this gives a unique identifier. _bnodePrefix = "node" + Long.toString(System.currentTimeMillis(), 32) + "x"; _nextBNodeID = 1; }/*------------------+| Methods from Sail |+------------------*/ /** * Initializes the RdfSource. * * @param jdbcDriver The String representing the JDBC-driver class, e.g. * <tt>org.gjt.mm.mysql.Driver</tt>. * @param jdbcUrl The String representing the JDBC-url of the database to * connect to, e.g. <tt>jdbc:mysql://localhost/sesame</tt>. * * @exception SailInitializationException If the initialization failed. */ public void initialize(String jdbcDriver, String jdbcUrl) throws SailInitializationException { Map configParams = new HashMap(2); configParams.put(JDBC_DRIVER_KEY, jdbcDriver); configParams.put(JDBC_URL_KEY, jdbcUrl); this.initialize(configParams); } /** * Initializes the RdfSource. * * @param jdbcDriver The String representing the JDBC-driver class, e.g. * <tt>org.gjt.mm.mysql.Driver</tt>. * @param jdbcUrl The String representing the JDBC-url of the database to * connect to, e.g. <tt>jdbc:mysql://localhost/sesame</tt>. * @param user The username that can be used to connect to the RDBMS. * @param password The password of the user in the RDBMS. * * @exception SailInitializationException If the initialization failed. */ public void initialize(String jdbcDriver, String jdbcUrl, String user, String password) throws SailInitializationException { Map configParams = new HashMap(4); configParams.put(JDBC_DRIVER_KEY, jdbcDriver); configParams.put(JDBC_URL_KEY, jdbcUrl); configParams.put(USER_KEY, user); configParams.put(PASSWORD_KEY, password); this.initialize(configParams); } /** * Initializes the RdfSource. Parameters can be specified using the keys * defined by constants in this class: <tt>JDBC_DRIVER_KEY</tt>, * <tt>JDBC_URL_KEY</tt>,<tt>USER_KEY</tt> and <tt>PASSWORD_KEY</tt>. * See the other <tt>initialize()</tt> methods of this class for a * description of the parameters and their values. * * @param configParams configuration parameters * @exception SailInitializationException If the RdfSource could not be * initialized using the supplied parameters. * @see #JDBC_DRIVER_KEY * @see #JDBC_URL_KEY * @see #USER_KEY * @see #PASSWORD_KEY * @see #initialize(java.lang.String,java.lang.String,java.lang.String,java.lang.String) */ public void initialize(Map configParams) throws SailInitializationException { // Get initialization parameters String jdbcDriver = (String)configParams.get(JDBC_DRIVER_KEY); String jdbcUrl = (String)configParams.get(JDBC_URL_KEY); String user = (String)configParams.get(USER_KEY); String password = (String)configParams.get(PASSWORD_KEY); if (jdbcDriver == null) { throw new SailInitializationException("parameter 'jdbcDriver' missing"); } if (jdbcUrl == null) { throw new SailInitializationException("parameter 'jdbcUrl' missing"); } // Load jdbc driver try { Class.forName(jdbcDriver); } catch (ClassNotFoundException e) { throw new SailInitializationException( "Unable to load JDBC-driver '" + jdbcDriver + "'", e); } try { _rdbms = RDBMS.createInstance(jdbcUrl, user, password); NN_ON_TEXT = _rdbms.emptyStringIsNull() ? "" : " NOT NULL"; } catch (SQLException e) { throw new SailInitializationException(e); } // Initialize database schema, if necessary _initDatabase(); } /** * Disconnects from the database. */ public void shutDown() { _rdbms.disconnect(); }/*------------------------+| Database initialization |+------------------------*/ /** * Initializes the database. _initDatabase() creates tables, indexes and * inserts default values into the database. */ protected void _initDatabase() throws SailInitializationException { try { _schemaVersion = _checkDbSchema(); if (_schemaVersion > CURRENT_SCHEMA_VERSION) { throw new SailInitializationException( "The database schema was created by a newer version of this Sail!"); } else if (_schemaVersion < CURRENT_SCHEMA_VERSION) { // There's no schema yet, or it is out-of-date. if (_schemaVersion == -1) { ThreadLog.trace("No DB schema yet, creating it..."); } else if (_schemaVersion < CURRENT_SCHEMA_VERSION) { ThreadLog.trace("Old DB schema, updating it..."); } _createDbSchema(); _schemaVersion = CURRENT_SCHEMA_VERSION; _exportStatusUpToDate = true; } else { // Restore value of _exportStatusUpToDate flag _exportStatusUpToDate = !VALUE_DIRTY.equals( _getRepInfo(KEY_EXPORT_FLAGS) ); ThreadLog.trace("DB schema is up to date"); } // Initialize local caches _initNamespaceCache(); } catch (SQLException e) { throw new SailInitializationException(e); } } /** * Checks and returns the DB schema version that is recorded in the * REP_INFO_TABLE. If this table does not yet exist, -1 will be returned. */ protected int _checkDbSchema() throws SQLException, SailInitializationException { ThreadLog.trace("Checking DB schema..."); int result; if (_rdbms.tableExists(REP_INFO_TABLE)) { String creator = _getRepInfo(KEY_SCHEMACREATOR); String version = _getRepInfo(KEY_SCHEMAVERSION); if (!SCHEMA_CREATOR.equals(creator)) { // FIXME temporary check to allow backward compatibility // with 0.9 class names if (!creator.startsWith("nl.aidministrator.rdf.sail.rdbms.")) { throw new SailInitializationException( "Database schema was not created by this Sail"); } else { _setRepInfo(KEY_SCHEMACREATOR, SCHEMA_CREATOR); } } try { result = Integer.parseInt(version); } catch (NumberFormatException nfe) { throw new SailInitializationException( "schema version is not an integer"); } } else { // No schema found. result = -1; } return result; }/*---------------+| Table creation |+---------------*/ /** * Creates the database schema (the tables and indexes). */ protected void _createDbSchema() throws SQLException { // First create the repository info table. _createRepInfoTable(); // Namespaces table _createNamespacesTable(); // Resources table _createResourcesTable(); // Literals table _createLiteralsTable(); // Triples table _createTriplesTable(); } /** * Creates the REP_INFO_TABLE for storing repository meta info. */ protected void _createRepInfoTable() throws SQLException { if (_schemaVersion == -1) { // No schema yet _rdbms.executeUpdate( "CREATE TABLE " + REP_INFO_TABLE + " (infokey " + _rdbms.INFOFIELD + " NOT NULL PRIMARY KEY," + " infovalue " + _rdbms.INFOFIELD + " NOT NULL)"); _setRepInfo(KEY_SCHEMAVERSION, String.valueOf(CURRENT_SCHEMA_VERSION)); _setRepInfo(KEY_SCHEMACREATOR, SCHEMA_CREATOR); } else if (_schemaVersion < CURRENT_SCHEMA_VERSION) { // Update the version number _setRepInfo(KEY_SCHEMAVERSION, String.valueOf(CURRENT_SCHEMA_VERSION)); } } /** * Creates the NAMESPACES_TABLE. */ protected void _createNamespacesTable() throws SQLException { if (_schemaVersion == -1) { // No schema yet _rdbms.executeUpdate( "CREATE TABLE " + NAMESPACES_TABLE + " (id " + _rdbms.ID_INT + " NOT NULL PRIMARY KEY," + " prefix " + _rdbms.PREFIX + NN_ON_TEXT + "," + " name " + _rdbms.NAME + "," + " userDefined " + _rdbms.BOOLEAN + " NOT NULL," + " export " + _rdbms.BOOLEAN + " NOT NULL," + " UNIQUE(prefix))");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -