@Override public LimitHandler getLimitHandler() { return new AbstractLimitHandler() { @Override public boolean supportsLimit() { return true; } @Override public String processSql(String sql, RowSelection selection) { if (LimitHelper.useLimit(this, selection)) { final boolean hasMaxRows = LimitHelper.hasMaxRows(selection); final boolean hasOffset = LimitHelper.hasFirstRow(selection); return sql + (hasMaxRows ? " limit ?" : "") + (hasOffset ? " offset ?" : ""); } return sql; } }; }
protected SqlStatementWrapper executeQueryStatement( String sqlStatement, QueryParameters queryParameters, boolean scroll, List<AfterLoadAction> afterLoadActions, SessionImplementor session) throws SQLException { // Processing query filters. queryParameters.processFilters( sqlStatement, session ); // Applying LIMIT clause. final LimitHandler limitHandler = getLimitHandler( queryParameters.getFilteredSQL(), queryParameters.getRowSelection() ); String sql = limitHandler.getProcessedSql(); // Adding locks and comments. sql = preprocessSQL( sql, queryParameters, getFactory().getDialect(), afterLoadActions ); final PreparedStatement st = prepareQueryStatement( sql, queryParameters, limitHandler, scroll, session ); return new SqlStatementWrapper( st, getResultSet( st, queryParameters.getRowSelection(), limitHandler, queryParameters.hasAutoDiscoverScalarTypes(), session ) ); }
/** * Execute given <tt>PreparedStatement</tt>, advance to the first result and return SQL <tt>ResultSet</tt>. */ protected final ResultSet getResultSet( final PreparedStatement st, final RowSelection selection, final LimitHandler limitHandler, final boolean autodiscovertypes, final SessionImplementor session) throws SQLException, HibernateException { try { ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st ); rs = wrapResultSetIfEnabled( rs , session ); if ( !limitHandler.supportsLimitOffset() || !LimitHelper.useLimit( limitHandler, selection ) ) { advance( rs, selection ); } if ( autodiscovertypes ) { autoDiscoverTypes( rs ); } return rs; } catch ( SQLException sqle ) { session.getTransactionCoordinator().getJdbcCoordinator().release( st ); throw sqle; } }
private int selectRecordsByMaxAge(Session session, String tempTable, Date minValue, Dialect dialect) { // fill temporary table, we don't need to join task on object on // container, oid and id is already in task table StringBuilder selectSB = new StringBuilder(); selectSB.append("select a.id as id from ").append(RAuditEventRecord.TABLE_NAME).append(" a"); selectSB.append(" where a.").append(RAuditEventRecord.COLUMN_TIMESTAMP).append(" < ###TIME###"); String selectString = selectSB.toString(); // batch size RowSelection rowSelection = new RowSelection(); rowSelection.setMaxRows(CLEANUP_AUDIT_BATCH_SIZE); LimitHandler limitHandler = dialect.buildLimitHandler(selectString, rowSelection); selectString = limitHandler.getProcessedSql(); // replace ? -> batch size, $ -> ? // Sorry for that .... I just don't know how to write this query in HQL, // nor I'm not sure if limiting max size in // compound insert into ... select ... query via query.setMaxSize() // would work - TODO write more nicely if anybody knows how) selectString = selectString.replace("?", String.valueOf(CLEANUP_AUDIT_BATCH_SIZE)); selectString = selectString.replace("###TIME###", "?"); String queryString = "insert into " + tempTable + " " + selectString; LOGGER.trace("Query string = {}", queryString); SQLQuery query = session.createSQLQuery(queryString); query.setParameter(0, new Timestamp(minValue.getTime())); return query.executeUpdate(); }
private int selectRecordsByNumberToKeep(Session session, String tempTable, Integer recordsToKeep, Dialect dialect) { Number totalAuditRecords = (Number) session.createCriteria(RAuditEventRecord.class) .setProjection(Projections.rowCount()) .uniqueResult(); int recordsToDelete = totalAuditRecords.intValue() - recordsToKeep; if (recordsToDelete <= 0) { recordsToDelete = 0; } else if (recordsToDelete > CLEANUP_AUDIT_BATCH_SIZE) { recordsToDelete = CLEANUP_AUDIT_BATCH_SIZE; } LOGGER.debug("Total audit records: {}, records to keep: {} => records to delete in this batch: {}", totalAuditRecords, recordsToKeep, recordsToDelete); if (recordsToDelete == 0) { return 0; } StringBuilder selectSB = new StringBuilder(); selectSB.append("select a.id as id from ").append(RAuditEventRecord.TABLE_NAME).append(" a"); selectSB.append(" order by a.").append(RAuditEventRecord.COLUMN_TIMESTAMP).append(" asc"); String selectString = selectSB.toString(); // batch size RowSelection rowSelection = new RowSelection(); rowSelection.setMaxRows(recordsToDelete); LimitHandler limitHandler = dialect.buildLimitHandler(selectString, rowSelection); selectString = limitHandler.getProcessedSql(); selectString = selectString.replace("?", String.valueOf(recordsToDelete)); String queryString = "insert into " + tempTable + " " + selectString; LOGGER.trace("Query string = {}", queryString); SQLQuery query = session.createSQLQuery(queryString); return query.executeUpdate(); }
@Test public void testLimit() { final RowSelection rowSelection = new RowSelection(); rowSelection.setMaxRows(getMaxRows()); LimitHandler limitHandler = ((SessionFactoryImpl) sessionFactory()).getDialect().getLimitHandler(); String limitStatement = limitHandler.processSql(SELECT_POST_COMMENT, rowSelection); long startNanos = System.nanoTime(); doInJDBC(connection -> { try (PreparedStatement statement = connection.prepareStatement(limitStatement)) { limitHandler.bindLimitParametersAtEndOfQuery(rowSelection, statement, 1); statement.setInt(1, getMaxRows()); statement.execute(); int count = 0; ResultSet resultSet = statement.getResultSet(); while (resultSet.next()) { resultSet.getLong(1); count++; } assertEquals(getMaxRows(), count); } catch (SQLException e) { fail(e.getMessage()); } }); LOGGER.info("{} Result Set with limit took {} millis", dataSourceProvider().database(), TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos)); }
private int selectRecordsByMaxAge(Session session, String tempTable, Date minValue, Dialect dialect) { // fill temporary table, we don't need to join task on object on // container, oid and id is already in task table StringBuilder selectSB = new StringBuilder(); selectSB.append("select a.id as id from ").append(RAuditEventRecord.TABLE_NAME).append(" a"); selectSB.append(" where a.").append(RAuditEventRecord.COLUMN_TIMESTAMP).append(" < ###TIME###"); String selectString = selectSB.toString(); // batch size RowSelection rowSelection = new RowSelection(); rowSelection.setMaxRows(CLEANUP_AUDIT_BATCH_SIZE); LimitHandler limitHandler = dialect.getLimitHandler(); selectString = limitHandler.processSql(selectString, rowSelection); // replace ? -> batch size, $ -> ? // Sorry for that .... I just don't know how to write this query in HQL, // nor I'm not sure if limiting max size in // compound insert into ... select ... query via query.setMaxSize() // would work - TODO write more nicely if anybody knows how) selectString = selectString.replace("?", String.valueOf(CLEANUP_AUDIT_BATCH_SIZE)); selectString = selectString.replace("###TIME###", "?"); String queryString = "insert into " + tempTable + " " + selectString; LOGGER.trace("Query string = {}", queryString); NativeQuery query = session.createNativeQuery(queryString); query.setParameter(1, new Timestamp(minValue.getTime())); return query.executeUpdate(); }
private int selectRecordsByNumberToKeep(Session session, String tempTable, Integer recordsToKeep, Dialect dialect) { Number totalAuditRecords = (Number) session.createCriteria(RAuditEventRecord.class) .setProjection(Projections.rowCount()) .uniqueResult(); int recordsToDelete = totalAuditRecords.intValue() - recordsToKeep; if (recordsToDelete <= 0) { recordsToDelete = 0; } else if (recordsToDelete > CLEANUP_AUDIT_BATCH_SIZE) { recordsToDelete = CLEANUP_AUDIT_BATCH_SIZE; } LOGGER.debug("Total audit records: {}, records to keep: {} => records to delete in this batch: {}", totalAuditRecords, recordsToKeep, recordsToDelete); if (recordsToDelete == 0) { return 0; } StringBuilder selectSB = new StringBuilder(); selectSB.append("select a.id as id from ").append(RAuditEventRecord.TABLE_NAME).append(" a"); selectSB.append(" order by a.").append(RAuditEventRecord.COLUMN_TIMESTAMP).append(" asc"); String selectString = selectSB.toString(); // batch size RowSelection rowSelection = new RowSelection(); rowSelection.setMaxRows(recordsToDelete); LimitHandler limitHandler = dialect.getLimitHandler(); selectString = limitHandler.processSql(selectString, rowSelection); selectString = selectString.replace("?", String.valueOf(recordsToDelete)); String queryString = "insert into " + tempTable + " " + selectString; LOGGER.trace("Query string = {}", queryString); NativeQuery query = session.createNativeQuery(queryString); return query.executeUpdate(); }
@Override public LimitHandler getLimitHandler() { return LIMIT_HANDLER; }
/** * Obtain a <tt>PreparedStatement</tt> with all parameters pre-bound. * Bind JDBC-style <tt>?</tt> parameters, named parameters, and * limit parameters. */ protected final PreparedStatement prepareQueryStatement( final String sql, final QueryParameters queryParameters, final LimitHandler limitHandler, final boolean scroll, final SessionImplementor session) throws SQLException, HibernateException { final Dialect dialect = getFactory().getDialect(); final RowSelection selection = queryParameters.getRowSelection(); final boolean useLimit = LimitHelper.useLimit( limitHandler, selection ); final boolean hasFirstRow = LimitHelper.hasFirstRow( selection ); final boolean useLimitOffset = hasFirstRow && useLimit && limitHandler.supportsLimitOffset(); final boolean callable = queryParameters.isCallable(); final ScrollMode scrollMode = getScrollMode( scroll, hasFirstRow, useLimitOffset, queryParameters ); final PreparedStatement st = session.getTransactionCoordinator().getJdbcCoordinator() .getStatementPreparer().prepareQueryStatement( sql, callable, scrollMode ); try { int col = 1; //TODO: can we limit stored procedures ?! col += limitHandler.bindLimitParametersAtStartOfQuery( st, col ); if (callable) { col = dialect.registerResultSetOutParameter( (CallableStatement)st, col ); } col += bindParameterValues( st, queryParameters, col, session ); col += limitHandler.bindLimitParametersAtEndOfQuery( st, col ); limitHandler.setMaxRows( st ); if ( selection != null ) { if ( selection.getTimeout() != null ) { st.setQueryTimeout( selection.getTimeout() ); } if ( selection.getFetchSize() != null ) { st.setFetchSize( selection.getFetchSize() ); } } // handle lock timeout... final LockOptions lockOptions = queryParameters.getLockOptions(); if ( lockOptions != null ) { if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) { if ( !dialect.supportsLockTimeouts() ) { if ( log.isDebugEnabled() ) { log.debugf( "Lock timeout [%s] requested but dialect reported to not support lock timeouts", lockOptions.getTimeOut() ); } } else if ( dialect.isLockTimeoutParameterized() ) { st.setInt( col++, lockOptions.getTimeOut() ); } } } if ( log.isTraceEnabled() ) { log.tracev( "Bound [{0}] parameters total", col ); } } catch ( SQLException sqle ) { session.getTransactionCoordinator().getJdbcCoordinator().release( st ); throw sqle; } catch ( HibernateException he ) { session.getTransactionCoordinator().getJdbcCoordinator().release( st ); throw he; } return st; }
@Override public LimitHandler buildLimitHandler(String sql, RowSelection selection) { return new CUBRIDLimitHandler( this, sql, selection ); }
@Override public LimitHandler buildLimitHandler(String sql, RowSelection selection) { return new SQLServer2005LimitHandler( sql, selection ); }
@Override public LimitHandler getLimitHandler() { return this.wrapped.getLimitHandler(); }
/** * Build LIMIT clause handler applicable for given selection criteria. Returns {@link NoopLimitHandler} delegate * if dialect does not support LIMIT expression or processed query does not use pagination. * * @param sql Query string. * @param selection Selection criteria. * @return LIMIT clause delegate. */ protected LimitHandler getLimitHandler(String sql, RowSelection selection) { final LimitHandler limitHandler = getFactory().getDialect().buildLimitHandler( sql, selection ); return LimitHelper.useLimit( limitHandler, selection ) ? limitHandler : new NoopLimitHandler( sql, selection ); }
/** * Build LIMIT clause handler applicable for given selection criteria. Returns {@link org.hibernate.dialect.pagination.NoopLimitHandler} delegate * if dialect does not support LIMIT expression or processed query does not use pagination. * * @param sql Query string. * @param selection Selection criteria. * @return LIMIT clause delegate. */ protected LimitHandler getLimitHandler(String sql, RowSelection selection) { final LimitHandler limitHandler = getFactory().getDialect().buildLimitHandler( sql, selection ); return LimitHelper.useLimit( limitHandler, selection ) ? limitHandler : new NoopLimitHandler( sql, selection ); }
/** * Build delegate managing LIMIT clause. * * @param sql SQL query. * @param selection Selection criteria. {@code null} in case of unlimited number of rows. * @return LIMIT clause delegate. */ public LimitHandler buildLimitHandler(String sql, RowSelection selection) { return new LegacyLimitHandler( this, sql, selection ); }
/** * Build delegate managing LIMIT clause. * * @param sql SQL query. * @param selection Selection criteria. {@code null} in case of unlimited number of rows. * @return LIMIT clause delegate. */ public LimitHandler buildLimitHandler(String sql, RowSelection selection) { return new SQLiteLimitHandler( sql, selection ); }