All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.davidmoten.rx.jdbc.QueryUpdate Maven / Gradle / Ivy

There is a newer version: 0.7.19
Show newest version
package com.github.davidmoten.rx.jdbc;

import static com.github.davidmoten.rx.jdbc.Conditions.checkNotNull;
import static com.github.davidmoten.rx.jdbc.Queries.bufferedParameters;

import java.util.List;

import rx.Observable;
import rx.Observable.Operator;
import rx.functions.Func1;

/**
 * Always emits an Observable of size 1 containing the number of
 * affected records.
 */
final public class QueryUpdate implements Query {

	private final String sql;
	private final Observable parameters;
	private final QueryContext context;
	private final Observable depends;

	/**
	 * Private constructor.
	 * 
	 * @param sql
	 * @param parameters
	 * @param depends
	 * @param context
	 */
	private QueryUpdate(String sql, Observable parameters,
			Observable depends, QueryContext context) {
		checkNotNull(sql);
		checkNotNull(parameters);
		checkNotNull(depends);
		checkNotNull(context);
		this.sql = sql;
		this.parameters = parameters;
		this.depends = depends;
		this.context = context;
	}

	@Override
	public String sql() {
		return sql;
	}

	@Override
	public Observable parameters() {
		return parameters;
	}

	@Override
	public QueryContext context() {
		return context;
	}

	@Override
	public String toString() {
		return "QueryUpdate [sql=" + sql + "]";
	}

	@Override
	public Observable depends() {
		return depends;
	}

	/**
	 * 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
	 */
	public Observable count() {
		return bufferedParameters(this)
		// execute query for each set of parameters
				.concatMap(executeOnce());
	}

	/**
	 * Returns a {@link Func1} that itself returns the results of pushing
	 * parameters through an update query.
	 * 
	 * @param query
	 * @return
	 */
	private Func1, Observable> executeOnce() {
		return new Func1, Observable>() {
			@Override
			public Observable call(final List params) {
				if (sql.equals(QueryUpdateOperation.BEGIN_TRANSACTION)) {
					context.beginTransactionSubscribe();
				}
				Observable result = executeOnce(params).subscribeOn(
						context.scheduler());
				if (sql.equals(QueryUpdateOperation.COMMIT)
						|| sql.equals(QueryUpdateOperation.ROLLBACK))
					context.endTransactionSubscribe();
				return result;
			}
		};
	}

	/**
	 * Returns the results of an update query. Should return an
	 * {@link Observable} of size one containing the rows affected count.
	 * 
	 * @param query
	 * @param parameters
	 * @return
	 */
	private Observable executeOnce(final List parameters) {
		return QueryUpdateOperation.execute(this, parameters);
	}

	/**
	 * Builds a {@link QueryUpdate}.
	 */
	final public static class Builder {

		/**
		 * Standard query builder.
		 */
		private final QueryBuilder builder;

		/**
		 * Constructor.
		 * 
		 * @param sql
		 * @param db
		 */
		public Builder(String sql, Database db) {
			this.builder = new QueryBuilder(sql, db);
		}

		/**
		 * Appends the given parameters to the parameter list for the query. If
		 * there are more parameters than required for one execution of the
		 * query then more than one execution of the query will occur.
		 * 
		 * @param parameters
		 * @return this
		 */
		public  Builder parameters(Observable parameters) {
			builder.parameters(parameters);
			return this;
		}

		/**
		 * Appends the given parameter values to the parameter list for the
		 * query. If there are more parameters than required for one execution
		 * of the query then more than one execution of the query will occur.
		 * 
		 * @param objects
		 * @return this
		 */
		public Builder parameters(Object... objects) {
			builder.parameters(objects);
			return this;
		}

		/**
		 * Appends a parameter to the parameter list for the query. If there are
		 * more parameters than required for one execution of the query then
		 * more than one execution of the query will occur.
		 * 
		 * @param value
		 * @return this
		 */
		public Builder parameter(Object value) {
			builder.parameter(value);
			return this;
		}

		/**
		 * Appends a dependency to the dependencies that have to complete their
		 * emitting before the query is executed.
		 * 
		 * @param dependency
		 * @return this
		 */
		public Builder dependsOn(Observable dependency) {
			builder.dependsOn(dependency);
			return this;
		}

		/**
		 * Appends a dependency on the result of the last transaction (
		 * true for commit or false for rollback) to
		 * the dependencies that have to complete their emitting before the
		 * query is executed.
		 * 
		 * @return this
		 */
		public Builder dependsOnLastTransaction() {
			builder.dependsOnLastTransaction();
			return this;
		}

		/**
		 * Returns an {@link Observable} with the count of rows affected by the
		 * update statement.
		 * 
		 * @return
		 */
		public Observable count() {
			return new QueryUpdate(builder.sql(), builder.parameters(),
					builder.depends(), builder.context()).count();
		}

		/**
		 * Returns an {@link Operator} to allow the query to be pushed
		 * parameters via the {@link Observable#lift(Operator)} method.
		 * 
		 * @return operator that acts on parameters
		 */
		public Operator parameterOperator() {
			return new QueryUpdateOperator(this, OperatorType.PARAMETER);
		}

		/**
		 * Returns an {@link Operator} to allow the query to be pushed
		 * dependencies via the {@link Observable#lift(Operator)} method.
		 * 
		 * @return operator that acts on dependencies
		 */
		public Operator dependsOnOperator() {
			return new QueryUpdateOperator(this,
					OperatorType.DEPENDENCY);
		}

		/**
		 * Returns an {@link Operator} to allow the query to be run once per
		 * parameter list in the source.
		 * 
		 * @return
		 */
		public Operator, Observable> parameterListOperator() {
			return new QueryUpdateOperatorFromObservable(this);
		}

		public Builder clearParameters() {
			builder.clearParameters();
			return this;
		}
	}
}