/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: LimitOffsetCompensator.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.database.capabilities; import com.uwyn.rife.database.DbPreparedStatement; import com.uwyn.rife.database.DbResultSet; import com.uwyn.rife.database.VirtualParameters; import com.uwyn.rife.database.VirtualParametersHandler; import com.uwyn.rife.database.exceptions.DatabaseException; import com.uwyn.rife.database.queries.Query; import com.uwyn.rife.database.queries.QueryParameterType; import com.uwyn.rife.database.queries.QueryParameters; import java.sql.SQLException; public class LimitOffsetCompensator implements VirtualParametersHandler { private boolean mUseRelativeForScrolling = false; public void setUseRelativeForScrolling(boolean useRelativeForCursors) { mUseRelativeForScrolling = useRelativeForCursors; } public void handleCapablePreparedStatement(DbPreparedStatement statement) throws DatabaseException { Query query = statement.getQuery(); if (query != null) { // obtain capabilities Capabilities capabilities = query.getCapabilities(); if (capabilities != null) { // handle limit and offset capabilities if (capabilities.containsKey(Capability.LIMIT)) { // limit the fetch size of the resultset int max_rows = 0; int limit = (Integer)capabilities.get(Capability.LIMIT); statement.setFetchSize(limit); max_rows += limit; // limit the maximum number of rows if (capabilities.containsKey(Capability.OFFSET)) { max_rows += (Integer)capabilities.get(Capability.OFFSET); } if (max_rows != 0) { statement.setMaxRows(max_rows); } } // handle limit and offset parameter capabilities else if (capabilities.containsKey(Capability.LIMIT_PARAMETER)) { QueryParameters parameters = query.getParameters(); if (parameters != null) { QueryParameters virtual_query_parameters = parameters.getNewInstance(); virtual_query_parameters.addTypedParameter(QueryParameterType.LIMIT, (String)capabilities.get(Capability.LIMIT_PARAMETER)); if (capabilities.containsKey(Capability.OFFSET_PARAMETER)) { virtual_query_parameters.addTypedParameter(QueryParameterType.OFFSET, (String)capabilities.get(Capability.OFFSET_PARAMETER)); } VirtualParameters virtual_parameters = new VirtualParameters(virtual_query_parameters, this); statement.setVirtualParameters(virtual_parameters); } } } } } public void handleValues(DbPreparedStatement statement) throws DatabaseException { Query query = statement.getQuery(); if (query != null) { // obtain capabilities Capabilities capabilities = query.getCapabilities(); if (capabilities != null) { // handle limit and offset capabilities if (capabilities.containsKey(Capability.LIMIT_PARAMETER)) { // limit the fetch size of the resultset int max_rows = 0; String limit_parameter_name = (String)capabilities.get(Capability.LIMIT_PARAMETER); int limit = Integer.parseInt(String.valueOf(statement.getVirtualParameterValue(limit_parameter_name))); statement.setFetchSize(limit); max_rows += limit; // limit the maximum number of rows if (capabilities.containsKey(Capability.OFFSET_PARAMETER)) { String offset_parameter_name = (String)capabilities.get(Capability.OFFSET_PARAMETER); int offset = Integer.parseInt(String.valueOf(statement.getVirtualParameterValue(offset_parameter_name))); max_rows += offset; } if (max_rows != 0) { statement.setMaxRows(max_rows); } } } } } public void handleCapableResultSet(DbPreparedStatement statement) throws DatabaseException { DbResultSet resultset = statement.getResultSet(); // obtain capabilities Capabilities capabilities = statement.getQuery().getCapabilities(); if (capabilities != null && (capabilities.containsKey(Capability.LIMIT) || capabilities.containsKey(Capability.LIMIT_PARAMETER))) { int offset = -1; // handle limit and offset capabilities if (capabilities.containsKey(Capability.OFFSET)) { offset = (Integer)capabilities.get(Capability.OFFSET); } else if (capabilities.containsKey(Capability.OFFSET_PARAMETER)) { String parameter_name = (String)capabilities.get(Capability.OFFSET_PARAMETER); offset = Integer.parseInt(String.valueOf(statement.getVirtualParameterValue(parameter_name))); } // apply the offset if (offset > 0) { try { if (mUseRelativeForScrolling) { resultset.relative(offset); } else { while (offset > 0) { resultset.next(); offset--; } } } catch (SQLException e) { throw new DatabaseException(e); } } } } }