/** * Limits the given query to the given number of maximum rows. This method * does not alter the query directly, it simply wraps it in sub-selects. * <p> * Note: you cannot alter the query or varbinds after calling this method. * * @param query - query to limit * @param maxRows - maximum number of results to provide * @param varbinds - the variable bindings for the given query */ public static String limitQuery(String query, int maxRows, List<Object> varbinds, DBType dbType) { return limitQuery(query, maxRows, 0, varbinds, dbType); }
/** * Alters the varbinds to work with limitQuery. To use this, you must have created your * query with a limitQueryNoOffset call. This decoupling of the query creating and the varbinds * allows for the registration of limit queries. * * @see SQL#formatLimitQuery(String) */ public static void addVarbindsForLimitQuery(int maxRows, List<Object> varbinds, DBType dbType) { addVarbindsForLimitQuery(maxRows, 0, varbinds, dbType); }
/** * Alters the varbinds to work with limitQuery. To use this, you must have created your * query with a limitQueryNoOffset call. This decoupling of the query creating and the varbinds * allows for the registration of limit queries. * * @see SQL#formatLimitQuery(String) */ public static void addVarbindsForLimitQuery(int maxRows, long offset, List<Object> varbinds, DBType dbType) { internalLimitQuery("", maxRows, offset, varbinds, dbType); //$NON-NLS-1$ }
/** Helper method for wrapping quick calls that don't appreciate being interrupted. * Passes all exceptions and errors back to the client. * Runs in another thread - do not acquire connections from within the callable (it will fail). * N.B. (DCohen) Despite the claim in the previous line, there is code that acquires connections from within the callable successfully. * Unclear why this is bad. * * Should only use low-level type stuff. * * This method takes a connection, which the callable intends to use, * essentially declaring that the child thread now owns * this connection. */ public static <T> T runUninterruptably( final Callable<T> callable, String threadString, final @Nullable Connection connection) throws PalantirSqlException { return runUninterruptably( BasicSQL.DEFAULT_EXECUTE_EXECUTOR.get(), callable, threadString, connection); }
public static void toStringSqlArgs(final StringBuilder sb, Iterable<Object[]> args) { // then we're doing a batch query for (Object[] rowOfArgs : args) { toStringSqlArgs(sb, rowOfArgs); } }
/** Encapsulates the logic for creating a prepared statement with the arguments set*/ private PreparedStatement createPreparedStatement(Connection c, String sql, Object[] vs) throws PalantirSqlException { PreparedStatement ps; ps = Connections.prepareStatement(c, sql); List<BlobHandler> toClean = Lists.newArrayList(); if (vs != null) { try { for (int i=0; i < vs.length; i++) { BlobHandler cleanup = setObject(c, ps, i+1, vs[i]); if (cleanup != null) { toClean.add(cleanup); } } } catch (Exception e) { // if we throw, we need to clean up any blobs we have already made for (BlobHandler cleanupBlob : toClean) { try { cleanupBlob.freeTemporary(); } catch (Exception e1) { SqlLoggers.LOGGER.error("failed to free temp blob", e1); //$NON-NLS-1$ } } BasicSQLUtils.throwUncheckedIfSQLException(e); throw Throwables.throwUncheckedException(e); } } return BlobCleanupPreparedStatement.create(ps, toClean); }
public static WhereClauses create(String tableIdentifier, RangeRequest request, String... clauses) { List<String> extraWhereClauses = Lists.newArrayList(clauses); byte[] start = request.getStartInclusive(); byte[] end = request.getEndExclusive(); Collection<byte[]> cols = request.getColumnNames(); List<Object> args = Lists.newArrayListWithCapacity(2 + cols.size()); List<String> whereClauses = Lists.newArrayListWithCapacity(3 + extraWhereClauses.size()); if (start.length > 0) { whereClauses.add(tableIdentifier + (request.isReverse() ? ".row_name <= ?" : ".row_name >= ?")); args.add(start); } if (end.length > 0) { whereClauses.add(tableIdentifier + (request.isReverse() ? ".row_name > ?" : ".row_name < ?")); args.add(end); } if (!cols.isEmpty()) { whereClauses.add(tableIdentifier + ".col_name IN (" + BasicSQLUtils.nArguments(cols.size()) + ")"); args.addAll(cols); } whereClauses.addAll(extraWhereClauses); return new WhereClauses(whereClauses, args); }
private <T> T runUninterruptablyInternal(final PreparedStatement ps, final ResultSetVisitor<T> visitor, final FinalSQLString sql, final AutoClose autoClose, @Nullable Integer fetchSize) throws PalantirInterruptedException, PalantirSqlException { if (Thread.currentThread().isInterrupted()) { SqlLoggers.CANCEL_LOGGER.debug("interrupted prior to executing uninterruptable SQL call"); throw new PalantirInterruptedException("interrupted prior to executing uninterruptable SQL call"); } return BasicSQLUtils.runUninterruptably(executeStatementExecutor, () -> { if (fetchSize != null) { ps.setFetchSize(fetchSize); } ResultSet rs = null; try { rs = ps.executeQuery(); return visitor.visit(rs); } finally { if (rs != null && autoClose == AutoClose.TRUE) { rs.close(); } } }, sql.toString(), /* We no longer have a connection to worry about */ null); }
toStringSqlArgs(sb, rowOfArgs);
} catch (Exception e) { closeSilently(rs); BasicSQLUtils.throwUncheckedIfSQLException(e); throw Throwables.throwUncheckedException(e); } catch (Exception e) { closeSilently(ps); BasicSQLUtils.throwUncheckedIfSQLException(e); throw Throwables.throwUncheckedException(e);
public static WhereClauses create(String tableIdentifier, RangeRequest request, String... clauses) { List<String> extraWhereClauses = Lists.newArrayList(clauses); byte[] start = request.getStartInclusive(); byte[] end = request.getEndExclusive(); Collection<byte[]> cols = request.getColumnNames(); List<Object> args = Lists.newArrayListWithCapacity(2 + cols.size()); List<String> whereClauses = Lists.newArrayListWithCapacity(3 + extraWhereClauses.size()); if (start.length > 0) { whereClauses.add(tableIdentifier + (request.isReverse() ? ".row_name <= ?" : ".row_name >= ?")); args.add(start); } if (end.length > 0) { whereClauses.add(tableIdentifier + (request.isReverse() ? ".row_name > ?" : ".row_name < ?")); args.add(end); } if (!cols.isEmpty()) { whereClauses.add(tableIdentifier + ".col_name IN (" + BasicSQLUtils.nArguments(cols.size()) + ")"); args.addAll(cols); } whereClauses.addAll(extraWhereClauses); return new WhereClauses(whereClauses, args); }
PreparedStatement updateInternal(final Connection c, final FinalSQLString sql, final Object vs[], final AutoClose autoClose) throws PalantirSqlException { if (SqlLoggers.LOGGER.isTraceEnabled()) { SqlLoggers.LOGGER.trace("SQL update interval query: {}", sql.getQuery()); } return BasicSQLUtils.runUninterruptably (executeStatementExecutor, () -> { return wrapPreparedStatement(c, sql, vs, ps -> { PreparedStatements.execute(ps); return ps; }, "update", autoClose); //$NON-NLS-1$ }, sql.toString(), c); }
extraWhere, order); String limitQuery = BasicSQLUtils.limitQuery(query, numRowsToGet, args, dbType); return Pair.create(limitQuery, args);
private static PalantirSqlException wrapSQLExceptionWithVerboseLogging(final SQLException sqlEx, String sql, Object[] args) { try { StringBuilder why = new StringBuilder(); why.append("While attempting to execute the SQL '" + sql + "' we caught a SQLException.\n" + //$NON-NLS-1$ //$NON-NLS-2$ "The SQL was executed with the following bind args:\n"); //$NON-NLS-1$ BasicSQLUtils.toStringSqlArgs(why, args); why.append("End of verbose SQLException error message"); //$NON-NLS-1$ return PalantirSqlException.create(new VerboseSQLException(sqlEx, why.toString())); } catch (Throwable e) { // make sure we don't interfere with the real error SqlLoggers.LOGGER.error("Trapped an exception while printing out information about an exception. " + //$NON-NLS-1$ "No client requests were harmed.", e); //$NON-NLS-1$ SqlLoggers.LOGGER.error("Printing SQLException now so it doesn't get lost", sqlEx); //$NON-NLS-1$ } return PalantirSqlException.create(sqlEx); }
/** * Limits the given query to the given number of maximum rows at * the given offset. This is effective when trying to page through * a set of results. This method does not alter the query directly, * it simply wraps it in sub-selects. * <p> * Note: you cannot alter the query or varbinds after calling this method. * * @param query - query to limit * @param maxRows - maximum number of results to provide * @param offset - 0-based offset to return results from * @param varbinds - the variable bindings for the given query */ public static String limitQuery(String query, int maxRows, int offset, List<Object> varbinds, DBType dbType) { return internalLimitQuery(query, maxRows, offset, varbinds, dbType); }
/** Encapsulates the logic for creating a prepared statement with the arguments set*/ private PreparedStatement createPreparedStatement(Connection c, String sql, Object[] vs) throws PalantirSqlException { PreparedStatement ps; ps = Connections.prepareStatement(c, sql); List<BlobHandler> toClean = Lists.newArrayList(); if (vs != null) { try { for (int i=0; i < vs.length; i++) { BlobHandler cleanup = setObject(c, ps, i+1, vs[i]); if (cleanup != null) { toClean.add(cleanup); } } } catch (Exception e) { // if we throw, we need to clean up any blobs we have already made for (BlobHandler cleanupBlob : toClean) { try { cleanupBlob.freeTemporary(); } catch (Exception e1) { SqlLoggers.LOGGER.error("failed to free temp blob", e1); //$NON-NLS-1$ } } BasicSQLUtils.throwUncheckedIfSQLException(e); throw Throwables.throwUncheckedException(e); } } return BlobCleanupPreparedStatement.create(ps, toClean); }
/** * Alters the varbinds to work with limitQuery. To use this, you must have created your * query with a limitQueryNoOffset call. This decoupling of the query creating and the varbinds * allows for the registration of limit queries. * * @see SQL#formatLimitQuery(String) */ public static void addVarbindsForLimitQuery(int maxRows, List<Object> varbinds, DBType dbType) { addVarbindsForLimitQuery(maxRows, 0, varbinds, dbType); }
protected PreparedStatement execute(final Connection c, final FinalSQLString sql, final Object vs[], final AutoClose autoClose) throws PalantirSqlException { if (SqlLoggers.LOGGER.isTraceEnabled()) { SqlLoggers.LOGGER.trace("SQL execution query: {}", sql.getQuery()); } return BasicSQLUtils.runUninterruptably (executeStatementExecutor, () -> { return wrapPreparedStatement(c, sql, vs, ps -> { PreparedStatements.execute(ps); return ps; }, "execute", autoClose); //$NON-NLS-1$ }, sql.toString(), c); }
/** * Limits the given query to the given number of maximum rows. This method * does not alter the query directly, it simply wraps it in sub-selects. * <p> * Note: you cannot alter the query or varbinds after calling this method. * * @param query - query to limit * @param maxRows - maximum number of results to provide * @param varbinds - the variable bindings for the given query */ public static String limitQuery(String query, int maxRows, List<Object> varbinds, DBType dbType) { return limitQuery(query, maxRows, 0, varbinds, dbType); }
private static PalantirSqlException wrapSQLExceptionWithVerboseLogging(final PalantirSqlException sqlEx, String sql, Object[] args) { try { if (sqlEx.getCause() == null || !(sqlEx.getCause() instanceof SQLException)) { return sqlEx; } StringBuilder why = new StringBuilder(); why.append("While attempting to execute the SQL '" + sql + "' we caught a SQLException.\n" + //$NON-NLS-1$ //$NON-NLS-2$ "The SQL was executed with the following bind args:\n"); //$NON-NLS-1$ BasicSQLUtils.toStringSqlArgs(why, args); why.append("End of verbose SQLException error message"); //$NON-NLS-1$ return PalantirSqlException.create(new VerboseSQLException((SQLException) sqlEx.getCause(), why.toString())); } catch (Throwable e) { // make sure we don't interfere with the real error SqlLoggers.LOGGER.error("Trapped an exception while printing out information about an exception. " + //$NON-NLS-1$ "No client requests were harmed.", e); //$NON-NLS-1$ SqlLoggers.LOGGER.error("Printing SQLException now so it doesn't get lost", sqlEx); //$NON-NLS-1$ } return sqlEx; }