1 package com.github.davidmoten.rx.jdbc;
2
3 import com.github.davidmoten.util.Preconditions;
4
5 import rx.Observable;
6
7 /**
8 * Builds base information for a query (either select or update).
9 */
10 final class QueryBuilder {
11
12 /**
13 * JDBC sql either select/update/insert.
14 */
15 private String sql;
16
17 /**
18 * Parameters for the query corresponding to ? characters in the sql.
19 */
20 private Observable<Parameter> parameters = Observable.empty();
21
22 /**
23 * Observables to complete before the query is executed.
24 */
25 private Observable<?> depends = Observable.empty();
26
27 /**
28 * {@link Database} to use the query against.
29 */
30 private final Database db;
31
32 /**
33 * Execution context to use to run the query.
34 */
35 private final QueryContext context;
36
37 /**
38 * Constructor.
39 *
40 * @param sql
41 * @param db
42 */
43 QueryBuilder(String sql, Database db) {
44 this.sql = sql;
45 this.db = db;
46 this.context = db.queryContext();
47 }
48
49 /**
50 * Appends the given parameters to the parameter list for the query. If
51 * there are more parameters than required for one execution of the query
52 * then more than one execution of the query will occur.
53 *
54 * @param params
55 */
56 <T> void parameters(Observable<T> params) {
57 this.parameters = Observable.concat(parameters, params.map(Parameter.TO_PARAMETER));
58 }
59
60 /**
61 * Appends the given parameter values to the parameter list for the query.
62 * If there are more parameters than required for one execution of the query
63 * then more than one execution of the query will occur.
64 *
65 * @param objects
66 */
67 void parameters(Object... objects) {
68 for (Object object : objects)
69 parameter(object);
70 }
71
72 /**
73 * Appends a parameter to the parameter list for the query. If there are
74 * more parameters than required for one execution of the query then more
75 * than one execution of the query will occur.
76 *
77 * @param value
78 */
79 void parameter(Object value) {
80 // TODO check on supported types?
81 if (value instanceof Observable)
82 throw new IllegalArgumentException(
83 "use parameters() method not the parameter() method for an Observable");
84 parameters(Observable.just(value));
85 }
86
87 /**
88 * Sets a named parameter. If name is null throws a
89 * {@link NullPointerException}. If value is instance of Observable then
90 * throws an {@link IllegalArgumentException}.
91 *
92 * @param name
93 * the parameter name. Cannot be null.
94 * @param value
95 * the parameter value
96 */
97 void parameter(String name, Object value) {
98 Preconditions.checkNotNull(name, "parameter name cannot be null");
99 if (value instanceof Observable)
100 throw new IllegalArgumentException(
101 "use parameters() method not the parameter() method for an Observable");
102 this.parameters = parameters.concatWith(Observable.just(new Parameter(name, value)));
103 }
104
105 /**
106 * Appends a dependency to the dependencies that have to complete their
107 * emitting before the query is executed.
108 *
109 * @param dependency
110 */
111 void dependsOn(Observable<?> dependency) {
112 depends = Observable.concat(depends, dependency);
113 }
114
115 /**
116 * Appends a dependency on the result of the last transaction (
117 * <code>true</code> for commit or <code>false</code> for rollback) to the
118 * dependencies that have to complete their emitting before the query is
119 * executed.
120 */
121 void dependsOnLastTransaction() {
122 dependsOn(db.lastTransactionResult());
123 }
124
125 /**
126 * Returns the sql of the query.
127 *
128 * @return sql
129 */
130 String sql() {
131 return sql;
132 }
133
134 /**
135 * Returns the parameters for the query.
136 *
137 * @return parameters
138 */
139 Observable<Parameter> parameters() {
140 return parameters;
141 }
142
143 /**
144 * Returns the dependencies of the query.
145 *
146 * @return dependencies
147 */
148 public Observable<?> depends() {
149 return depends;
150 }
151
152 /**
153 * Returns the query's {@link QueryContext}.
154 *
155 * @return context
156 */
157 QueryContext context() {
158 return context;
159 }
160
161 void clearParameters() {
162 this.parameters = Observable.empty();
163 }
164
165 void setSql(String sql) {
166 this.sql = sql;
167 }
168 }