/** * Returns the results of an update query. Should be an {@link Observable} * of size 1 containing the number of records affected by the update (or * insert) statement. * * @param query * @return */ @SuppressWarnings("unchecked") public Observable<Integer> count() { return (Observable<Integer>) QueryUpdate.get(this); }
@Override public String toString() { return "QueryUpdate [sql=" + sql() + "]"; }
if (query.context().batchSize() > 1 && !query.context().isTransactionOpen()) { throw new SQLRuntimeException("batching can only be performed within a transaction"); if (query.returnGeneratedKeys()) { keysOption = Statement.RETURN_GENERATED_KEYS; } else { keysOption = Statement.NO_GENERATED_KEYS; state.ps = state.con.prepareStatement(query.sql(), keysOption); Util.setParameters(state.ps, parameters, query.names()); debug("executing sql={}, parameters {}", query.sql(), parameters); if (state.ps instanceof PreparedStatementBatch && parameters instanceof ArrayListFinal) { if (query.returnGeneratedKeys()) { debug("getting generated keys"); ResultSet rs = state.ps.getGeneratedKeys(); Observable<Object> depends = Observable.empty(); Observable<T> o = new QuerySelect(QuerySelect.RETURN_GENERATED_KEYS, params, depends, query.context(), query.context().resultSetTransform()) .execute(query.returnGeneratedKeysFunction()); Subscriber<T> sub = createSubscriber(subscriber); o.unsafeSubscribe(sub); throw new SQLException("failed to execute sql=" + query.sql(), e); if (!query.returnGeneratedKeys()) {
/** * Transforms the results using the given function. * * @param function * @return */ public <T> Observable<T> get(ResultSetMapper<? extends T> function) { return QueryUpdate.get(new QueryUpdate<T>(builder.sql(), builder.parameters(), builder.depends(), builder.context(), function)); }
static <T> Observable<T> get(QueryUpdate<T> queryUpdate) { if (queryUpdate.context().batchSize() > 1) { return bufferedParameters(queryUpdate) // // mark the last parameter list as such .compose(Transformers.mapLast(toFinalArrayList))// // execute query for each set of parameters .concatMap(queryUpdate.executeOnce()); } else { return bufferedParameters(queryUpdate) // // execute query for each set of parameters .concatMap(queryUpdate.executeOnce()); } }
@SuppressWarnings("unchecked") private void performBeginTransaction(Subscriber<? super T> subscriber) { query.context().beginTransactionObserve(); debug("beginTransaction emitting 1"); subscriber.onNext((T) Integer.valueOf(1)); debug("emitted 1"); complete(subscriber); }
/** * Returns an {@link Observable} with the count of rows affected by the * update statement. * * @return Observable of counts of rows affected. */ public Observable<Integer> count() { QueryContext ctxt; if (batchSize > 1) { ctxt = builder.context().batched(batchSize); } else { ctxt = builder.context(); } return new QueryUpdate<Integer>(builder.sql(), builder.parameters(), builder.depends(), ctxt, null).count(); }
/** * Rolls back the current transaction. Throws {@link RuntimeException} if * connection is in autoCommit mode. * * @param subscriber * @param state */ @SuppressWarnings("unchecked") private void performRollback(Subscriber<? super T> subscriber, State state) { debug("rolling back"); query.context().endTransactionObserve(); Conditions.checkTrue(!Util.isAutoCommit(state.con)); Util.rollback(state.con); // must close before onNext so that connection is released and is // available to a query that might process the onNext close(state); subscriber.onNext((T) Integer.valueOf(0)); debug("rolled back"); complete(subscriber); }
/** * Returns true if and only if the sql statement is a commit command. * * @return if is commit */ private boolean isCommit() { return query.sql().equals(COMMIT); }
@Override public void call(Subscriber<? super T> subscriber) { final State state = new State(); try { if (isBeginTransaction()) performBeginTransaction(subscriber); else { query.context().setupBatching(); getConnection(state); subscriber.add(createUnsubscriptionAction(state)); if (isCommit()) performCommit(subscriber, state); else if (isRollback()) performRollback(subscriber, state); else performUpdate(subscriber, state); } } catch (Throwable e) { query.context().endTransactionObserve(); query.context().endTransactionSubscribe(); try { close(state); } finally { handleException(e, subscriber); } } }
/** * Returns true if and only if the sql statement is a rollback command. * * @return if is rollback */ private boolean isRollback() { return query.sql().equals(ROLLBACK); }
/** * Commits the current transaction. Throws {@link RuntimeException} if * connection is in autoCommit mode. * * @param subscriber * @param state */ @SuppressWarnings("unchecked") private void performCommit(Subscriber<? super T> subscriber, State state) { getConnection(state); query.context().endTransactionObserve(); if (subscriber.isUnsubscribed()) return; debug("committing"); Conditions.checkTrue(!Util.isAutoCommit(state.con)); Util.commit(state.con); // must close before onNext so that connection is released and is // available to a query that might process the onNext close(state); if (subscriber.isUnsubscribed()) return; subscriber.onNext((T) Integer.valueOf(1)); debug("committed"); complete(subscriber); }
private boolean isBeginTransaction() { return query.sql().equals(BEGIN_TRANSACTION); }