zoukankan      html  css  js  c++  java
  • sqlserver2012 offset

    /*
     * Hibernate, Relational Persistence for Idiomatic Java
     *
     * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
     * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
     */
    package org.hibernate.dialect.pagination;
    
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    import org.hibernate.engine.spi.RowSelection;
    
    /**
     * LIMIT clause handler compatible with SQL Server 2012 and later.
     *
     * @author Chris Cranford
     */
    public class SQLServer2012LimitHandler extends SQLServer2005LimitHandler {
    	// determines whether the limit handler used offset/fetch or 2005 behavior.
    	private boolean usedOffsetFetch;
    
    	public SQLServer2012LimitHandler() {
    
    	}
    
    	@Override
    	public boolean supportsLimit() {
    		return true;
    	}
    
    	@Override
    	public boolean supportsVariableLimit() {
    		return true;
    	}
    
    	@Override
    	public String processSql(String sql, RowSelection selection) {
    		// SQLServer mandates the following rules to use OFFSET/LIMIT
    		//  * An 'ORDER BY' is required
    		//  * The 'OFFSET ...' clause is mandatory, cannot use 'FETCH ...' by itself.
    		//  * The 'TOP' clause isn't permitted with LIMIT/OFFSET.
    		if ( hasOrderBy( sql ) ) {
    			if ( !LimitHelper.useLimit( this, selection ) ) {
    				return sql;
    			}
    			return applyOffsetFetch( selection, sql, getInsertPosition( sql ) );
    		}
    		return super.processSql( sql, selection );
    	}
    
    	@Override
    	public boolean useMaxForLimit() {
    		// when using the offset fetch clause, the max value is passed as-is.
    		// SQLServer2005LimitHandler uses start + max values.
    		return usedOffsetFetch ? false : super.useMaxForLimit();
    	}
    
    	@Override
    	public int convertToFirstRowValue(int zeroBasedFirstResult) {
    		// When using the offset/fetch clause, the first row is passed as-is
    		// SQLServer2005LimitHandler uses zeroBasedFirstResult + 1
    		if ( usedOffsetFetch ) {
    			return zeroBasedFirstResult;
    		}
    		return super.convertToFirstRowValue( zeroBasedFirstResult );
    	}
    
    	@Override
    	public int bindLimitParametersAtEndOfQuery(RowSelection selection, PreparedStatement statement, int index)
    	throws SQLException {
    		if ( usedOffsetFetch && !LimitHelper.hasFirstRow( selection ) ) {
    			// apply just the max value when offset fetch applied
    			statement.setInt( index, getMaxOrLimit( selection ) );
    			return 1;
    		}
    		return super.bindLimitParametersAtEndOfQuery( selection, statement, index );
    	}
    
    	private String getOffsetFetch(RowSelection selection) {
    		if ( !LimitHelper.hasFirstRow( selection ) ) {
    			return " offset 0 rows fetch next ? rows only";
    		}
    		return " offset ? rows fetch next ? rows only";
    	}
    
    	private int getInsertPosition(String sql) {
    		int position = sql.length() - 1;
    		for ( ; position > 0; --position ) {
    			char ch = sql.charAt( position );
    			if ( ch != ';' && ch != ' ' && ch != '
    ' && ch != '
    ' ) {
    				break;
    			}
    		}
    		return position + 1;
    	}
    
    	private String applyOffsetFetch(RowSelection selection, String sql, int position) {
    		usedOffsetFetch = true;
    
    		StringBuilder sb = new StringBuilder();
    		sb.append( sql.substring( 0, position ) );
    		sb.append( getOffsetFetch( selection ) );
    		if ( position > sql.length() ) {
    			sb.append( sql.substring( position - 1 ) );
    		}
    
    		return sb.toString();
    	}
    
    	private boolean hasOrderBy(String sql) {
    		int depth = 0;
    
    		String lowerCaseSQL = sql.toLowerCase();
    
    		for ( int i = lowerCaseSQL.length() - 1; i >= 0; --i ) {
    			char ch = lowerCaseSQL.charAt( i );
    			if ( ch == '(' ) {
    				depth++;
    			}
    			else if ( ch == ')' ) {
    				depth--;
    			}
    			if ( depth == 0 ) {
    				if ( lowerCaseSQL.startsWith( "order by ", i ) ) {
    					return true;
    				}
    			}
    		}
    		return false;
    	}
    }
    

      

  • 相关阅读:
    Mysql 创建联合主键
    Shell中的while循环
    shell 日期加减运算
    PHP日期格式转时间戳
    Uber 叫车时,弹出以下代码导致无法打车(An email confirmation has been sent to...),解决办法
    如何让Table显示滚动条
    mySQL中replace的用法
    打豪车应用:uber详细攻略(附100元优惠码)
    svn 命令行创建和删除 分支和tags
    php ob_start()、ob_end_flush和ob_end_clean()多级缓冲
  • 原文地址:https://www.cnblogs.com/firstdream/p/7829417.html
Copyright © 2011-2022 走看看