This helper class takes care of contstructing queries
and cursor positioning (paging) for all different kinds
of databases
based on the orginal esql.xsl
| Method from org.apache.cocoon.components.language.markup.xsp.EsqlQuery Detail: |
protected void adjustCounts() throws SQLException {
this.updateCount=this.statement.getUpdateCount();
if (this.hasResultSet) {
this.resultCount++;
} else {
this.updateCountCount++;
}
}
update counters for result sets and update counts |
public Statement createStatement() throws SQLException {
switch(limitMethod) {
case EsqlConnection.LIMIT_METHOD_JDBC:
statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
break;
default:
statement = connection.createStatement();
};
return(statement);
}
|
public boolean execute() throws SQLException {
return this.execute(false);
}
|
public boolean execute(int resultSetFromObject) throws SQLException {
hasResultSet = this.execute(false);
resultSet = (ResultSet) ((CallableStatement) preparedStatement).getObject(resultSetFromObject);
resultSetValid = true;
return hasResultSet;
}
|
public boolean execute(boolean needsQuery) throws SQLException {
if ( needsQuery ) {
if (preparedStatement != null) {
resultSet = preparedStatement.executeQuery();
}
else {
resultSet = statement.executeQuery( getQueryString() );
}
hasResultSet = (resultSet != null);
resultSetValid = true;
} else {
if (preparedStatement != null) {
hasResultSet = preparedStatement.execute();
}
else {
hasResultSet = statement.execute( getQueryString() );
}
resultSetValid = false;
}
this.adjustCounts();
return(hasResultSet);
}
some brain dead DBMSs (Informix) don't like their callable
statements to be 'execute'd but require 'executeQuery' instead. |
public CallableStatement getCallableStatement() {
return((CallableStatement) preparedStatement);
}
|
public int getCurrentRow() {
return(position);
}
|
public int getMaxRows() {
return(maxRows);
}
|
public boolean getMoreResults() throws SQLException {
if (this.statement==null)
return false;
this.hasResultSet = this.statement.getMoreResults();
this.resultSetValid=false;
this.adjustCounts();
return (this.hasResultSet || (this.updateCount >-1));
}
retrieve next result, check whether it is an result set or an
update count. Set instance vars accordingly and update
counters. |
public PreparedStatement getPreparedStatement() {
return(preparedStatement);
}
|
public String getQueryString() {
switch(limitMethod) {
case EsqlConnection.LIMIT_METHOD_POSTGRESQL:
if (skipRows > 0) {
if (maxRows > -1) {
return(new StringBuffer(query).append(" LIMIT ").append(maxRows).append(",").append(skipRows).toString());
}
else {
return(new StringBuffer(query).append(" OFFSET ").append(skipRows).toString());
}
}
else {
if (maxRows > -1) {
return(new StringBuffer(query).append(" LIMIT ").append(maxRows).toString());
}
else {
return(query);
}
}
case EsqlConnection.LIMIT_METHOD_MYSQL:
if (skipRows > 0) {
if (maxRows > -1) {
return(new StringBuffer(query).append(" LIMIT ").append(skipRows).append(",").append(maxRows).toString());
}
else {
throw new RuntimeException("MySQL does not support a skip of rows only");
}
}
else {
if (maxRows > -1) {
return(new StringBuffer(query).append(" LIMIT ").append(maxRows).toString());
}
else {
return(query);
}
}
default:
return(query);
}
}
|
public int getResultCount() {
return this.resultCount;
}
|
public void getResultRows() throws SQLException {
if ( !resultSetValid ) {
resultSet = statement.getResultSet();
}
resultSetMetaData = resultSet.getMetaData();
position = 0;
if (skipRows > 0) {
switch(limitMethod) {
case EsqlConnection.LIMIT_METHOD_POSTGRESQL:
// in clause
position = skipRows;
break;
case EsqlConnection.LIMIT_METHOD_MYSQL:
// in clause
position = skipRows;
break;
case EsqlConnection.LIMIT_METHOD_JDBC:
resultSet.absolute(skipRows);
position = skipRows;
break;
default:
while (resultSet.next()) {
position++;
if (position == skipRows) {
break;
}
}
};
}
}
|
public ResultSet getResultSet() {
return(resultSet);
}
|
public ResultSetMetaData getResultSetMetaData() {
return(resultSetMetaData);
}
|
public int getSkipRows() {
return(skipRows);
}
|
public Statement getStatement() {
return(statement);
}
|
public int getUpdateCount() throws SQLException {
return this.updateCount;
}
|
public int getUpdateCountCount() {
return this.updateCountCount;
}
|
public boolean groupLevelExists() {
return (this.groups != null && this.groups.size() >= this.groupLevel+1 && this.groups.get(this.groupLevel) != null);
}
|
public void groupLevelMinusMinus() {
this.groupLevel--;
}
|
public void groupLevelPlusPlus() {
this.groupLevel++;
}
|
public boolean hasGroupingVarChanged() throws SQLException {
if (this.changeLevel != -1) {
if (this.changeLevel < this.groupLevel) {
return true;
} else {
this.changeLevel = -1;
return true;
}
} else {
boolean result = false;
// need to check the complete hierarchy of nested groups for changes
for (int i = 0; i < = this.groupLevel; i++) {
Object tmp = this.getResultSet().getObject(((EsqlGroup)this.groups.get(i)).var);
if (!tmp.equals(((EsqlGroup)this.groups.get(i)).value)) {
((EsqlGroup)this.groups.get(i)).value = tmp;
result = true;
if (this.changeLevel == -1 && this.groupLevel != i)
this.changeLevel = i;
}
}
return result;
}
}
|
public boolean hasResultSet() {
return(this.hasResultSet);
}
|
public boolean keepGoing() {
return(keepgoing);
}
|
public boolean nextRow() throws SQLException {
position++;
return(resultSet.next());
}
|
public CallableStatement prepareCall() throws SQLException {
switch(limitMethod) {
case EsqlConnection.LIMIT_METHOD_POSTGRESQL:
case EsqlConnection.LIMIT_METHOD_MYSQL:
preparedStatement = connection.prepareCall( getQueryString() );
break;
case EsqlConnection.LIMIT_METHOD_JDBC:
preparedStatement = connection.prepareCall( getQueryString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
break;
case EsqlConnection.LIMIT_METHOD_NOLIMIT:
default:
preparedStatement = connection.prepareCall( getQueryString() );
};
statement = preparedStatement;
return((CallableStatement)preparedStatement);
}
|
public PreparedStatement prepareStatement() throws SQLException {
switch(limitMethod) {
case EsqlConnection.LIMIT_METHOD_POSTGRESQL:
case EsqlConnection.LIMIT_METHOD_MYSQL:
preparedStatement = connection.prepareStatement(getQueryString() );
break;
case EsqlConnection.LIMIT_METHOD_JDBC:
// Produce scrollable ResultSet and skip rows with ResultSet.absolute(skipRows).
// With SQL Server, statement.getResultSet() throws
// java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Error setting up static cursor cache.
// Same error with TYPE_SCROLL_SENSITIVE.
preparedStatement = connection.prepareStatement( getQueryString(),
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
break;
case EsqlConnection.LIMIT_METHOD_NOLIMIT:
default:
// maxRows can be set without the limit method being set - it defaults to LIMIT_METHOD_NOLIMIT
// which is not such a good name as its really another way of limiting using JDBC.
// Produce non-scrollable ResultSet and skip rows with multiple ResultSet.next().
preparedStatement = connection.prepareStatement(getQueryString() );
break;
}
statement = preparedStatement;
return(preparedStatement);
}
|
public int rowCount() throws SQLException {
switch(limitMethod) {
case EsqlConnection.LIMIT_METHOD_JDBC:
// TC: I'm not quite sure if synchronized is really necessary since
// the XSP page will be poolable
synchronized (resultSet) {
int currentRow = resultSet.getRow();
resultSet.last();
int count = resultSet.getRow();
if (currentRow > 0) {
resultSet.absolute(currentRow);
}
else {
resultSet.first();
resultSet.relative(-1);
}
return(count);
}
default:
// select count(*)
throw new RuntimeException("not yet implemented");
}
}
|
public void setGroupingVar(String key) throws SQLException {
if (this.groups == null)
this.groups = new ArrayList(1);
this.groups.ensureCapacity(this.groupLevel);
this.groups.add(this.groupLevel, new EsqlGroup(key, this.getResultSet().getObject(key)));
}
|
public void setKeepGoing(boolean still) {
keepgoing = still;
}
|
public void setMaxRows(int i) {
this.maxRows = i;
}
|
public void setSkipRows(int i) {
this.skipRows = i;
}
|