org.modeshape.jdbc.JcrStatement Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of modeshape-jdbc-local
Show all versions of modeshape-jdbc-local
JDBC driver to allow clients to use JCR-SQL2 to query a ModeShape JCR repository within the same JVM process.
/*
* ModeShape (http://www.modeshape.org)
*
* Licensed 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.modeshape.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.Statement;
import javax.jcr.RepositoryException;
import javax.jcr.query.QueryResult;
import org.modeshape.jdbc.delegate.RepositoryDelegate;
class JcrStatement implements Statement {
private final JcrConnection connection;
private ResultSet results;
private boolean closed;
private SQLWarning warning;
private int rowLimit = -1;
private int fetchDirection = ResultSet.FETCH_FORWARD;
private boolean poolable;
private int moreResults = 0;
private String sqlLanguage = JcrConnection.JCR_SQL2;
JcrStatement( JcrConnection connection ) {
this.connection = connection;
assert this.connection != null;
}
JcrConnection connection() {
return this.connection;
}
public void setJcrSqlLanguage( String jcrSQL ) {
this.sqlLanguage = (jcrSQL != null ? jcrSQL : JcrConnection.JCR_SQL2);
}
/**
* {@inheritDoc}
*
* This driver doesn't have a way to set the fetch size, so this method always returns 0.
*
*
* @see java.sql.Statement#getFetchSize()
*/
@Override
public int getFetchSize() throws SQLException {
notClosed();
return 0;
}
/**
* {@inheritDoc}
*
* This driver doesn't have a way to set the fetch size, so this method is ignored and does nothing.
*
*
* @see java.sql.Statement#setFetchSize(int)
*/
@Override
public void setFetchSize( int rows ) throws SQLException {
notClosed();
}
@Override
public int getFetchDirection() throws SQLException {
notClosed();
return fetchDirection;
}
@Override
public void setFetchDirection( int direction ) throws SQLException {
notClosed();
if (direction != ResultSet.FETCH_FORWARD && direction != ResultSet.FETCH_REVERSE && direction != ResultSet.FETCH_UNKNOWN) {
throw new SQLException(JdbcLocalI18n.invalidArgument.text(direction, "" + ResultSet.FETCH_FORWARD + ", "
+ ResultSet.FETCH_REVERSE + ", "
+ ResultSet.FETCH_UNKNOWN));
}
fetchDirection = direction;
}
/**
* {@inheritDoc}
*
* This driver does not support limiting the field size, and always returns 0.
*
*
* @see java.sql.Statement#getMaxFieldSize()
*/
@Override
public int getMaxFieldSize() throws SQLException {
notClosed();
return 0;
}
@Override
public void setMaxFieldSize( int max ) throws SQLException {
notClosed();
if (max < 0) {
throw new SQLException(JdbcLocalI18n.argumentMayNotBeNegative.text("max", max));
}
// ignored otherwise
}
@Override
public int getMaxRows() throws SQLException {
notClosed();
// need to map ModeShapes -1 rowLimit to 0
// because the jdbc spec indicate maxRows must be >= 0
// or an exception should be thrown.
return (rowLimit == -1 ? 0 : rowLimit);
}
@Override
public void setMaxRows( int max ) throws SQLException {
notClosed();
if (max < 0) {
throw new SQLException(JdbcLocalI18n.argumentMayNotBeNegative.text("max", max));
}
rowLimit = max;
}
/**
* {@inheritDoc}
*
* This method returns 0 since there is currently no timeout with JCR 1.0 or JCR 2.0.
*
*
* @see java.sql.Statement#getQueryTimeout()
*/
@Override
public int getQueryTimeout() throws SQLException {
notClosed();
return 0;
}
@Override
public void setQueryTimeout( int seconds ) throws SQLException {
notClosed();
if (seconds < 0) {
throw new SQLException(JdbcLocalI18n.argumentMayNotBeNegative.text("seconds", seconds));
}
// Otherwise ignore
}
@Override
public boolean isPoolable() throws SQLException {
notClosed();
return poolable;
}
@Override
public void setPoolable( boolean poolable ) throws SQLException {
notClosed();
this.poolable = poolable;
}
@Override
public Connection getConnection() throws SQLException {
notClosed();
return connection;
}
@Override
public void cancel() throws SQLException {
notClosed();
close();
// Unable to cancel a JCR query ...
}
@Override
public void clearWarnings() throws SQLException {
notClosed();
warning = null;
}
@Override
public SQLWarning getWarnings() throws SQLException {
notClosed();
return warning;
}
@Override
public boolean isClosed() {
return closed || connection.isClosed();
}
@Override
public void close() {
if (!closed) {
closed = true;
connection.getRepositoryDelegate().closeStatement();
}
}
protected final void notClosed() throws SQLException {
if (isClosed()) throw new SQLException(JdbcLocalI18n.statementIsClosed.text());
}
protected final void noUpdates() throws SQLException {
throw new SQLException(JdbcLocalI18n.updatesNotSupported.text());
}
// ----------------------------------------------------------------------------------------------------------------
// Updates
// ----------------------------------------------------------------------------------------------------------------
@Override
public int executeUpdate( String sql ) throws SQLException {
notClosed();
noUpdates();
return 0;
}
@Override
public int executeUpdate( String sql,
int autoGeneratedKeys ) throws SQLException {
notClosed();
noUpdates();
return 0;
}
@Override
public int executeUpdate( String sql,
int[] columnIndexes ) throws SQLException {
notClosed();
noUpdates();
return 0;
}
@Override
public int executeUpdate( String sql,
String[] columnNames ) throws SQLException {
notClosed();
noUpdates();
return 0;
}
@Override
public void setCursorName( String name ) throws SQLException {
notClosed();
noUpdates();
}
@Override
public int getUpdateCount() throws SQLException {
notClosed();
return -1;
}
@Override
public void addBatch( String sql ) throws SQLException {
notClosed();
noUpdates();
}
@Override
public void clearBatch() throws SQLException {
notClosed();
noUpdates();
}
@Override
public int[] executeBatch() throws SQLException {
notClosed();
noUpdates();
return null;
}
// ----------------------------------------------------------------------------------------------------------------
// Queries
// ----------------------------------------------------------------------------------------------------------------
@Override
public boolean execute( String sql ) throws SQLException {
notClosed();
warning = null;
moreResults = 0;
try {
// Convert the supplied SQL into JCR-SQL2 ...
String jcrSql2 = connection.nativeSQL(sql);
// Create the query ...
final QueryResult jcrResults = getJcrRepositoryDelegate().execute(jcrSql2, this.sqlLanguage);
results = new JcrResultSet(this, jcrResults, null);
moreResults = 1;
} catch (RepositoryException e) {
throw new SQLException(e.getLocalizedMessage(), e);
}
return true; // always a ResultSet
}
protected RepositoryDelegate getJcrRepositoryDelegate() {
return this.connection.getRepositoryDelegate();
}
@Override
public boolean execute( String sql,
int autoGeneratedKeys ) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public boolean execute( String sql,
int[] columnIndexes ) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public boolean execute( String sql,
String[] columnNames ) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public ResultSet executeQuery( String sql ) throws SQLException {
execute(sql);
return getResultSet();
}
@Override
public ResultSet getGeneratedKeys() /*throws SQLException*/{
// TODO: if and when ModeShape supports providing key information
// then a result set containing the metadata will need to be created.
return new JcrResultSet();
}
@Override
public boolean getMoreResults() throws SQLException {
notClosed();
return moreResults > 0;
}
@Override
public boolean getMoreResults( int current ) throws SQLException {
notClosed();
if (current != CLOSE_ALL_RESULTS && current != CLOSE_CURRENT_RESULT && current != KEEP_CURRENT_RESULT) {
throw new SQLException(JdbcLocalI18n.invalidArgument.text(current, "" + CLOSE_ALL_RESULTS + ", "
+ CLOSE_CURRENT_RESULT + ", "
+ KEEP_CURRENT_RESULT));
}
if (KEEP_CURRENT_RESULT != current) {
// Close (by nulling) the results ...
// jcrResults = null;
results = null;
}
if (moreResults > 0) --moreResults;
return moreResults > 0;
}
@Override
public ResultSet getResultSet() throws SQLException {
notClosed();
return results; // may be null
}
@Override
public int getResultSetConcurrency() throws SQLException {
notClosed();
return ResultSet.CONCUR_READ_ONLY;
}
@Override
public int getResultSetHoldability() throws SQLException {
notClosed();
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
}
@Override
public int getResultSetType() throws SQLException {
notClosed();
return ResultSet.TYPE_SCROLL_INSENSITIVE;
}
@Override
public void setEscapeProcessing( boolean enable ) throws SQLException {
notClosed();
// Ignore for now
}
@Override
public boolean isWrapperFor( Class> iface ) /*throws SQLException*/{
return iface.isInstance(this);
}
@Override
public T unwrap( Class iface ) throws SQLException {
if (!isWrapperFor(iface)) {
throw new SQLException(JdbcLocalI18n.classDoesNotImplementInterface.text(Statement.class.getSimpleName(),
iface.getName()));
}
return iface.cast(this);
}
@Override
public void closeOnCompletion() {
}
@Override
public boolean isCloseOnCompletion() {
return true;
}
}