View Javadoc
1   package com.github.davidmoten.rx.jdbc;
2   
3   import static com.github.davidmoten.rx.RxUtil.concatButIgnoreFirstSequence;
4   import static com.github.davidmoten.rx.jdbc.Util.TO_EMPTY_PARAMETER_LIST;
5   
6   import java.util.ArrayList;
7   import java.util.Arrays;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Map.Entry;
11  
12  import rx.Observable;
13  import rx.functions.Func1;
14  
15  /**
16   * Utility methods for queries.
17   */
18  final class Queries {
19  
20      private static final Func1<Parameter, Observable<Parameter>> FLATTEN_NAMED_MAPS = new Func1<Parameter, Observable<Parameter>>() {
21  
22          @SuppressWarnings("unchecked")
23          @Override
24          public Observable<Parameter> call(Parameter p) {
25              if (p.value() instanceof Map) {
26                  List<Parameter> list = new ArrayList<Parameter>();
27                  for (Entry<String, ?> entry : ((Map<String, ?>) p.value()).entrySet()) {
28                      list.add(new Parameter(entry.getKey(), entry.getValue()));
29                  }
30                  return Observable.from(list);
31              } else
32                  return Observable.from(Arrays.asList(p));
33          }
34      };
35  
36      /**
37       * Private constructor to prevent instantiation.
38       */
39      private Queries() {
40          // prevent instantiation
41      }
42  
43      /**
44       * Returns the number of parameters required to run this query once. Roughly
45       * corresponds to the number of ? characters in the sql but have to watch
46       * out for ? characters within quoted strings.
47       * 
48       * @return number of parameters in query sql
49       */
50      static int numParamsPerQuery(Query query) {
51          return Util.parametersCount(query);
52      }
53  
54      /**
55       * Returns query.getParameters() {@link Observable} but only after query
56       * dependencies have been fully emitted (and ignored).
57       * 
58       * @return query parameters
59       */
60      static Observable<Parameter> parametersAfterDependencies(Query query) {
61          return concatButIgnoreFirstSequence(query.depends(), query.parameters());
62      }
63  
64      /**
65       * Returns {@link Observable} with one item 1 but only after query
66       * dependencies have been fully emitted (and ignored).
67       * 
68       * @param query
69       * 
70       * @return {@link Observable} with one element 1
71       */
72      static Observable<Integer> singleIntegerAfterDependencies(Query query) {
73          return concatButIgnoreFirstSequence(query.depends(), Observable.just(1));
74      }
75  
76      /**
77       * If the number of parameters in a query is >0 then group the parameters in
78       * lists of that number in size but only after the dependencies have been
79       * completed. If the number of parameteres is zero then return an observable
80       * containing one item being an empty list.
81       * 
82       * @param query
83       * @return
84       */
85      static Observable<List<Parameter>> bufferedParameters(Query query) {
86          int numParamsPerQuery = numParamsPerQuery(query);
87          if (numParamsPerQuery > 0)
88              //we don't check that parameters is empty after this because by general design 
89              //we want nothing to happen if a query is passed no parameters when it expects them
90              return parametersAfterDependencies(query)
91                      .concatMap(FLATTEN_NAMED_MAPS)
92                      .buffer(numParamsPerQuery);
93          else
94              return singleIntegerAfterDependencies(query).map(TO_EMPTY_PARAMETER_LIST);
95      }
96  
97  }