📄 driverrdb.java
字号:
*/
private void notSupported(String opName)
{ throw new UnsupportedOperationException(opName); }
protected static final int xactBegin = 0;
protected static final int xactCommit = 1;
protected static final int xactAbort = 2;
protected static final int xactIsActive = 3;
protected static final int xactAutoOff = 4;
protected static final int xactAutoOn = 5;
protected static final int xactBeginIfNone = 6;
/**
* Perform a transaction operation. For begin/commit/abort,
* return true if success, false if fail. for xactIsActive,
* return true if this driver has an active transaction,
* else return false.
* for beginIfNone, if there is a transaction running, return false, otherwise
*
*/
protected synchronized boolean xactOp(int op) throws RDFRDBException {
try { return xaxtOpRaw( op ); }
catch (SQLException e) { throw new JenaException( "Transaction support failed: ", e );
}
}
private boolean xaxtOpRaw( int op ) throws SQLException
{
boolean ret = true;
if (op == xactBegin) {
// start a transaction
// always return true
if (!inTransaction) {
xactBegin();
inTransaction = true;
}
} else if (op == xactBeginIfNone) {
if (inTransaction)
ret = false;
else {
xactBegin();
inTransaction = true; }
} else if (op == xactCommit) {
// commit a transaction
// always return true
if (inTransaction) {
xactCommit();
inTransaction = false;
}
} else if (op == xactAbort) {
// rollback a transaction
// always return true
if (inTransaction) {
xactAbort();
inTransaction = false;
}
} else if (op == xactIsActive) {
// return true if xact is active, else false
ret = inTransaction;
} else if (op == xactAutoOff) {
// disable autocommit
// return true if autocommit is on, else false
// begins a new transaction
Connection c = m_sql.getConnection();
ret = c.getAutoCommit();
if ( ret )
xactBegin();
inTransaction = true;
} else if (op == xactAutoOn) {
// enable autocommit
// always return true
if ( inTransaction )
throw new JenaException("Can't enable AutoCommit in middle of existing transaction");
Connection c = m_sql.getConnection();
c.setAutoCommit(true);
ret = true;
} else
throw new JenaException("Unknown transaction operation: " + op);
return ret;
}
private void xactBegin() throws RDFRDBException {
try {
Connection c = m_sql.getConnection();
try {
if (c.getTransactionIsolation() != Connection.TRANSACTION_READ_COMMITTED) {
c.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
}
if (c.getAutoCommit()) {
c.setAutoCommit(false);
}
} catch (Exception e) {
e.printStackTrace();
}
// Starting a transaction could require us to lose any
// cached prepared statements
// for some jdbc drivers, currently I think all the drivers
// we use are safe and
// is a major performance hit so commented out for now.
//m_sql.flushPreparedStatementCache();
} catch (SQLException e) {
throw new JenaException("Transaction begin failed: ", e);
}
}
private void xactAbort() throws RDFRDBException {
try {
Connection c = m_sql.getConnection();
c.rollback();
c.commit();
c.setAutoCommit(true);
} catch (SQLException e) {
throw new JenaException("Transaction rollback failed: ", e);
}
}
private void xactCommit() throws RDFRDBException {
try {
Connection c = m_sql.getConnection();
c.commit();
try {
c.setAutoCommit(true);
} catch (Exception e) {
e.printStackTrace();
}
// not sure why read_uncommitted is set, below. commented
// out by kw.
// c.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
} catch (SQLException e) {
throw new JenaException("Transaction commit failed: ", e);
}
}
/**
* If the underlying database connection supports transactions, turn
* autocommit off, then begin a new transaction. Note that transactions are
* associated with connections, not with Models. This
*/
public synchronized void begin() throws RDFRDBException {
if (transactionsSupported()) {
xactOp(xactBegin);
} else {
notSupported("begin transaction");
}
}
/**
* If the underlying database connection supports transactions, call
* commit(), then turn autocommit on.
*/
public void commit() throws RDFRDBException {
if (transactionsSupported()) {
xactOp(xactCommit);
} else {
notSupported("commit transaction");
}
}
/**
* If underlying database connection supports transactions, call abort() on
* the connection, then turn autocommit on.
*/
public synchronized void abort() throws RDFRDBException {
if (transactionsSupported()) {
xactOp(xactAbort);
} else {
notSupported("abort transaction");
}
}
/**
* Return a string identifying underlying database type.
*
*/
public String getDatabaseType() {
return(DATABASE_TYPE);
}
/**
* Returns true if the underlying database supports transactions.
*/
public boolean transactionsSupported() {
if (m_transactionsSupported != null) {
return(m_transactionsSupported.booleanValue());
}
if (m_dbcon != null) {
try {
Connection c = m_sql.getConnection();
if ( c != null) {
m_transactionsSupported = new Boolean(c.getMetaData().supportsMultipleTransactions());
return(m_transactionsSupported.booleanValue());
}
} catch (SQLException e) {
logger.error("SQL Exception caught ", e);
}
}
return (false);
}
//--------------------------------------------------jena 1 backward compatability
/**
* Close the driver
*
* Nothing to do for now.
*
* @throws RDFDBException if there is an access problem
* @deprecated Since Jena 2.0 this call is no longer required - just
* close the DBConnection - there should be no need for an application
* to interact directly with the driver.
*
*/
public void close() throws RDFRDBException {
}
/**
* Returns true if the database layout supports multiple RDF models
* in the same database.
* @deprecated Since Jena 2.0 all databases support multiple models.
*/
public boolean supportsMultipleModels() {
return true;
}
/**
* Returns true if the database layout supports implicit reification
* of statements (i.e. statements can be treated as resources).
* @deprecated Since Jena 2.0 the reification API has changed. The
* new API is supported in all models, but the old Jena 1 API is no
* longer supported. This call will return false to indicate
* to old code that the old style of jena reification is not supported.
*/
public boolean supportsJenaReification() {
return false;
}
/*
* The following routines are responsible for encoding nodes
* as database structures. For each node type stored (currently,
* literals, URI, blank), there are two possible encodings
* depending on the node size. Small nodes may be stored
* within a statement table. If the node is long (will not
* fit within the statement table), it is be stored in a
* separate table for that node type.
*
* In addition, for resources (URI, blank nodes), the URI
* may be optionally compressed. Below, the possibilites
* are enumerated.
*
* Literal Encoding in Statement Tables
* Short Literal: Lv:[langLen]:[datatypeLen]:[langString][datatypeString]value[:]
* Long Literal: Lr:dbid
* Literal Encoding in Long Literal Table
* Literal: Lv:[langLen]:[datatypeLen]:[langString][datatypeString]head[:] hash tail
*
* Comments:
* L indicates a literal
* v indicates a value
* r indicates a reference to another table
* : is used as a delimiter. note that MySQL trims trailing white space for
* certain VARCHAR columns so an extra delimiter is appended when necessary
* for those columns. it is not required for dbid, however.
* dbid references the long literal table
* langLen is the length of the language identifier for the literal
* langString is the language identifier
* datatypeLen is the length of the datatype for the literal
* datatypeString is the datatype for the literal
* value is the lexical form of the string
* head is a prefix of value that can be indexed
* hash is the CRC32 hash value for the tail
* tail is the remainder of the value that cannot be indexed
*
*
*
* URI Encoding in Statement Tables
* Short URI: Uv:[pfx_dbid]:URI[:]
* Long URI: Ur:[pfx_dbid]:dbid
* URI Encoding in Long URI Table
* URI: Uv:head[:] hash tail
*
* Comments:
* U indicates a URI
* pfx_dbid references the prefix table. if the prefix is too
* short (i.e., the length of the prefix is less than
* URI_COMPRESS_LENGTH), the URI is not compressed and
* pfx_dbid is null.
* URI is the complete URI
* other notation same as for literal encoding
*
* Blank Node Encoding in Statement Tables
* Short URI: Bv:[pfx_dbid]:bnid[:]
* Long URI: Br:[pfx_dbid]:dbid
* Blank Encoding in Long URI Table
* URI: Bv:head[:] hash tail
*
* Comments:
* B indicates a blank node
* bnid is the blank node identifier
* other notation same as above
* Note: currently, blank nodes are always stored uncompressed (pfix_dbid is null).
*
* Variable Node Encoding in Statement Tables
* Variable Node: Vv:name
*
* Comments:
* V indicates a variable node
* v indicates a value
* name is the variable name
* Note: the length must be less than LONG_OBJECT_LENGTH
*
* ANY Node Encoding in Statement Tables
* Variable Node: Av:
*
* Prefix Encoding in Prefix Table
* Prefix: Pv:val[:] [hash] [tail]
*
* Comments:
* P indicates a prefix
* other notation same as above
* hash and tail are only required for long prefixes.
*
*/
protected static String RDBCodeURI = "U";
protected static String RDBCodeBlank = "B";
protected static String RDBCodeLiteral = "L";
protected static String RDBCodeVariable = "V";
protected static String RDBCodeANY = "A";
protected static String RDBCodePrefix = "P";
protected static String RDBCodeValue = "v";
protected static String RDBCodeRef = "r";
protected static String RDBCodeDelim = ":";
protected static char RDBCodeDelimChar = ':';
protected static String RDBCodeInvalid = "X";
/**
* Convert a node to a string to be stored in a statement table.
* @param Node The node to convert to a string. Must be a concrete node.
* @param addIfLong If the node is a long object and is not in the database, add it.
* @return the string or null if failure.
*/
public String nodeToRDBString ( Node node, boolean addIfLong ) throws RDFRDBException {
String res = null;
if ( node.isURI() ) {
String uri = new String(((Node_URI) node).getURI());
if ( uri.startsWith(RDBCodeURI) ) {
throw new RDFRDBException ("URI Node looks like a blank node: " + uri );
}
// TODO: need to write special version of splitNamespace for rdb.
// or else, need a guarantee that splitNamespace never changes.
// the problem is that if the splitNamespace algorithm changes,
// then URI's may be encoded differently. so, URI's in existing
// databases may become inaccessible.
int pos = 0;
boolean noCompress;
String pfx;
String qname;
if ( URI_COMPRESS == true ) {
pos = dbSplitNamespace(uri);
if ( uri.startsWith(DB.uri) )
noCompress = true;
else
noCompress = (pos == uri.length()) || (pos <= URI_COMPRESS_LENGTH);
} else
noCompress = true;
if ( noCompress ) {
pfx = RDBCodeDelim + RDBCodeDelim;
qname = uri;
} else {
// see if it's cached
DBIDInt pfxid = URItoPrefix(uri, pos, addIfLong);
if ( pfxid == null ) return res;
pfx = RDBCodeDelim + ((DBIDInt)pfxid).getIntID() + RDBCodeDelim;
qname = uri.substring(pos);
}
int encodeLen = RDBCodeURI.length() + 1 + pfx.length() + EOS_LEN;
boolean URIisLong = objectIsLong(encodeLen,qname);
if ( URIisLong ) {
int dbid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -