MentaBean

Rev

Rev 203 | Rev 205 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 203 Rev 204
1
package org.mentabean.jdbc;
1
package org.mentabean.jdbc;
2
2
3
import java.sql.PreparedStatement;
3
import java.sql.PreparedStatement;
4
import java.sql.ResultSet;
4
import java.sql.ResultSet;
5
import java.sql.SQLException;
5
import java.sql.SQLException;
6
import java.util.ArrayList;
6
import java.util.ArrayList;
7
import java.util.HashMap;
7
import java.util.HashMap;
8
import java.util.Iterator;
8
import java.util.Iterator;
9
import java.util.List;
9
import java.util.List;
10
import java.util.Map;
10
import java.util.Map;
11
11
12
import org.mentabean.BeanConfig;
12
import org.mentabean.BeanConfig;
13
import org.mentabean.BeanException;
13
import org.mentabean.BeanException;
14
import org.mentabean.DBField;
14
import org.mentabean.DBField;
15
import org.mentabean.sql.Condition;
15
import org.mentabean.sql.Condition;
16
import org.mentabean.sql.HasParams;
16
import org.mentabean.sql.HasParams;
17
import org.mentabean.sql.Sentence;
17
import org.mentabean.sql.Sentence;
18
import org.mentabean.sql.param.DefaultParamHandler;
18
import org.mentabean.sql.param.DefaultParamHandler;
19
import org.mentabean.sql.param.Param;
19
import org.mentabean.sql.param.Param;
20
import org.mentabean.sql.param.ParamHandler;
20
import org.mentabean.sql.param.ParamHandler;
21
import org.mentabean.sql.param.ParamValue;
21
import org.mentabean.sql.param.ParamValue;
22
import org.mentabean.util.PropertiesProxy;
22
import org.mentabean.util.PropertiesProxy;
23
import org.mentabean.util.SQLUtils;
23
import org.mentabean.util.SQLUtils;
24
24
25
/**
25
/**
26
 * Fluent QueryBuilder useful to create SQL queries
26
 * Fluent QueryBuilder useful to create SQL queries
27
 *
27
 *
28
 * @author margel
28
 * @author margel
29
 * @author erico
29
 * @author erico
30
 *
30
 *
31
 */
31
 */
32
public class QueryBuilder {
32
public class QueryBuilder {
33
33
-
 
34
        private static final String REGEX = "(AND|OR|\\([\\s]*?\\)|WHERE|HAVING)[\\s]*?$";
34
        private StringBuilder sb = new StringBuilder();
35
        private StringBuilder sb = new StringBuilder();
35
        private final AnsiSQLBeanSession session;
36
        private final AnsiSQLBeanSession session;
36
        private List<Object> paramValues = new ArrayList<Object>();
37
        private List<Object> paramValues = new ArrayList<Object>();
37
        private List<Alias<?>> selectAliases;
38
        private List<Alias<?>> selectAliases;
38
        private List<Alias<?>> createdAliases = new ArrayList<Alias<?>>();
39
        private List<Alias<?>> createdAliases = new ArrayList<Alias<?>>();
39
        private Map<String, Sentence> sentences = new HashMap<String, Sentence>();
40
        private Map<String, Sentence> sentences = new HashMap<String, Sentence>();
40
        private Alias aliasFrom;
41
        private Alias aliasFrom;
41
        private int parenthesis = 0;
42
        private int parenthesis = 0;
42
        private boolean clauseIf;
43
        private boolean clauseIf;
43
        private ParamHandler paramHandler;
44
        private ParamHandler paramHandler;
44
45
45
        protected QueryBuilder(final AnsiSQLBeanSession session) {
46
        protected QueryBuilder(final AnsiSQLBeanSession session) {
46
                this.session = session;
47
                this.session = session;
47
                this.paramHandler = new DefaultParamHandler();
48
                this.paramHandler = new DefaultParamHandler();
48
        }
49
        }
49
       
50
       
50
        protected QueryBuilder(final AnsiSQLBeanSession session, ParamHandler paramHandler) {
51
        protected QueryBuilder(final AnsiSQLBeanSession session, ParamHandler paramHandler) {
51
                this.session = session;
52
                this.session = session;
52
                this.paramHandler = paramHandler;
53
                this.paramHandler = paramHandler;
53
        }
54
        }
54
       
55
       
55
        public List<Alias<?>> getCreatedAliases() {
56
        public List<Alias<?>> getCreatedAliases() {
56
                return createdAliases;
57
                return createdAliases;
57
        }
58
        }
58
       
59
       
59
        /**
60
        /**
60
         * Builds an initial <i>SELECT</i> statement with given aliases
61
         * Builds an initial <i>SELECT</i> statement with given aliases
61
         * @param as - Alias(es) with properties that will be retrieved
62
         * @param as - Alias(es) with properties that will be retrieved
62
         * @return A new <code>Select</code> object
63
         * @return A new <code>Select</code> object
63
         */
64
         */
64
        public Select select(Alias<?>... as){
65
        public Select select(Alias<?>... as){
65
66
66
                return new Select(null, as);
67
                return new Select(null, as);
67
        }
68
        }
68
       
69
       
69
        public Select selectDistinct(Alias<?>... as){
70
        public Select selectDistinct(Alias<?>... as){
70
               
71
               
71
                return new Select("DISTINCT", as);
72
                return new Select("DISTINCT", as);
72
        }
73
        }
73
       
74
       
74
        /**
75
        /**
75
         * Builds an initial <i>SELECT alias FROM alias</i> statement.<br>
76
         * Builds an initial <i>SELECT alias FROM alias</i> statement.<br>
76
         * Same as <code>select(alias).from(alias)</code>
77
         * Same as <code>select(alias).from(alias)</code>
77
         * @param as - Alias with properties that will be retrieved
78
         * @param as - Alias with properties that will be retrieved
78
         * @return A new <code>From</code> object
79
         * @return A new <code>From</code> object
79
         * @see #select(Alias...)
80
         * @see #select(Alias...)
80
         * @see Select#from(Alias)
81
         * @see Select#from(Alias)
81
         */
82
         */
82
        public From selectFrom(Alias<?> as){
83
        public From selectFrom(Alias<?> as){
83
               
84
               
84
                return select(as).from(as);
85
                return select(as).from(as);
85
        }
86
        }
86
       
87
       
87
        public From selectDistinctFrom(Alias<?> as){
88
        public From selectDistinctFrom(Alias<?> as){
88
               
89
               
89
                return new Select("DISTINCT", as).from(as);
90
                return new Select("DISTINCT", as).from(as);
90
        }
91
        }
91
       
92
       
92
        /**
93
        /**
93
         * Builds an initial <i>SELECT</i> statement with given sentences
94
         * Builds an initial <i>SELECT</i> statement with given sentences
94
         * @param sentences - Sentence(s) to insert in <i>SELECT</i> clause
95
         * @param sentences - Sentence(s) to insert in <i>SELECT</i> clause
95
         * @return A new <code>Select</code> object
96
         * @return A new <code>Select</code> object
96
         */
97
         */
97
        public Select select(Sentence... sentences){
98
        public Select select(Sentence... sentences){
98
               
99
               
99
                return new Select(null, sentences);
100
                return new Select(null, sentences);
100
        }
101
        }
101
       
102
       
102
        public Select selectDistinct(Sentence... sentences){
103
        public Select selectDistinct(Sentence... sentences){
103
               
104
               
104
                return new Select("DISTINCT", sentences);
105
                return new Select("DISTINCT", sentences);
105
        }
106
        }
106
107
107
        /**
108
        /**
108
         * Creates a new QueryBuilder with the same session. It's useful to build sub-queries from the main query
109
         * Creates a new QueryBuilder with the same session. It's useful to build sub-queries from the main query
109
         * @return The new QueryBuilder instance
110
         * @return The new QueryBuilder instance
110
         */
111
         */
111
        public QueryBuilder subQuery() {
112
        public QueryBuilder subQuery() {
112
                QueryBuilder qb = new QueryBuilder(session);
113
                QueryBuilder qb = new QueryBuilder(session);
113
                //qb.selectAliases = selectAliases;
114
                //qb.selectAliases = selectAliases;
114
                qb.createdAliases = createdAliases;
115
                qb.createdAliases = createdAliases;
115
                return qb;
116
                return qb;
116
        }
117
        }
117
118
118
        /**
119
        /**
119
         * Creates an alias to be used in this QueryBuilder
120
         * Creates an alias to be used in this QueryBuilder
120
         *
121
         *
121
         * @param clazz - Bean class that will be mapped to a BeanConfig
122
         * @param clazz - Bean class that will be mapped to a BeanConfig
122
         * @param alias - String indicating the alia's name
123
         * @param alias - String indicating the alia's name
123
         * @return - The alias object
124
         * @return - The alias object
124
         */
125
         */
125
        public <T> Alias<T> aliasTo(Class<? extends T> clazz, String alias){
126
        public <T> Alias<T> aliasTo(Class<? extends T> clazz, String alias){
126
127
127
                return new Alias<T>(clazz, alias);
128
                return new Alias<T>(clazz, alias);
128
        }
129
        }
129
130
130
        /**
131
        /**
131
         * Creates an alias to be used in this QueryBuilder. The alia's name is the simple name of the bean class
132
         * Creates an alias to be used in this QueryBuilder. The alia's name is the simple name of the bean class
132
         *
133
         *
133
         * @param clazz - Bean class that will be mapped to a BeanConfig
134
         * @param clazz - Bean class that will be mapped to a BeanConfig
134
         * @return - The alias object
135
         * @return - The alias object
135
         */
136
         */
136
        public <T> Alias<T> aliasTo(Class<? extends T> clazz){
137
        public <T> Alias<T> aliasTo(Class<? extends T> clazz){
137
138
138
                return new Alias<T>(clazz, clazz.getSimpleName().toLowerCase());
139
                return new Alias<T>(clazz, clazz.getSimpleName().toLowerCase());
139
        }
140
        }
140
141
141
        private void appendTable(Alias<?> a) {
142
        private void appendTable(Alias<?> a) {
142
143
143
                sb.append(a.config.getTableName()).append(' ').append(a.aliasStr);
144
                sb.append(a.config.getTableName()).append(' ').append(a.aliasStr);
144
        }
145
        }
145
146
146
        private void append(Param param) {
147
        private void append(Param param) {
147
148
148
                if (param != null)
149
                if (param != null)
149
                        sb.append(param.paramInQuery());
150
                        sb.append(param.paramInQuery());
150
                add(param);
151
                add(param);
151
        }
152
        }
152
       
153
       
153
        private void add(Object param) {
154
        private void add(Object param) {
154
               
155
               
155
                if (param instanceof HasParams) {
156
                if (param instanceof HasParams) {
156
                        HasParams hasParams = (HasParams) param;
157
                        HasParams hasParams = (HasParams) param;
157
                        Param[] params = hasParams.getParams();
158
                        Param[] params = hasParams.getParams();
158
                        if (params != null) {
159
                        if (params != null) {
159
                                for (Param p : params) {
160
                                for (Param p : params) {
160
                                        add(p);
161
                                        add(p);
161
                                }
162
                                }
162
                        }
163
                        }
163
                }else {
164
                }else {
164
                        Param p = paramHandler.findBetter(this, param);
165
                        Param p = paramHandler.findBetter(this, param);
165
                        if (p != null && p.values() != null && p.values().length > 0) {
166
                        if (p != null && p.values() != null && p.values().length > 0) {
166
                               
167
                               
167
                                for (Object value : p.values()) {
168
                                for (Object value : p.values()) {
168
                                        if (value != null) {
169
                                        if (value != null) {
169
                                                paramValues.add(value);
170
                                                paramValues.add(value);
170
                                        }
171
                                        }
171
                                }
172
                                }
172
                        }
173
                        }
173
                }
174
                }
174
        }
175
        }
175
       
176
       
176
        private void applyRegex() {
177
        private void applyRegex() {
177
                remove("(AND|OR|\\([\\s]*?\\)|WHERE|HAVING)[\\s]*?$");
-
 
-
 
178
                remove(REGEX);
178
        }
179
        }
179
       
180
       
180
        private void remove(String regex) {
181
        private void remove(String regex) {
181
       
182
       
182
                sb = new StringBuilder(sb.toString().replaceAll(regex, ""));
183
                sb = new StringBuilder(sb.toString().replaceAll(regex, ""));
183
               
184
               
184
        }
185
        }
185
       
186
       
186
        private void addAnd() {
187
        private void addAnd() {
187
                if (clauseIf) {
188
                if (clauseIf) {
188
                        applyRegex();
189
                        applyRegex();
189
                        sb.append(" AND ");
190
                        sb.append(" AND ");
190
                }
191
                }
191
        }
192
        }
192
       
193
       
193
        private void addOr() {
194
        private void addOr() {
194
                if (clauseIf) {
195
                if (clauseIf) {
195
                        applyRegex();
196
                        applyRegex();
196
                        sb.append(" OR ");
197
                        sb.append(" OR ");
197
                }
198
                }
198
        }
199
        }
199
       
200
       
200
        private void openPar() {
201
        private void openPar() {
201
                parenthesis++;
202
                parenthesis++;
202
                sb.append('(');
203
                sb.append('(');
203
        }
204
        }
204
       
205
       
205
        private void closePar() {
206
        private void closePar() {
206
                applyRegex();
207
                applyRegex();
207
                parenthesis--;
208
                parenthesis--;
208
                sb.append(')');
209
                sb.append(')');
209
                applyRegex();
210
                applyRegex();
-
 
211
                clauseIf = true;
210
        }
212
        }
211
       
213
       
212
        private Alias<?> findAlias() {
214
        private Alias<?> findAlias() {
213
               
215
               
214
                Object[] instances = PropertiesProxy.getBeanInstances();
216
                Object[] instances = PropertiesProxy.getBeanInstances();
215
                if (instances == null || instances.length == 0) throw new IllegalStateException("Cannot find proxy instance!");
217
                if (instances == null || instances.length == 0) throw new IllegalStateException("Cannot find proxy instance!");
216
               
218
               
217
                Object instance = instances[0];
219
                Object instance = instances[0];
218
               
220
               
219
                //TODO PropertiesProxy.addBeanInstance(instance);
221
                //TODO PropertiesProxy.addBeanInstance(instance);
220
               
222
               
221
                for (Alias<?> a : createdAliases) {
223
                for (Alias<?> a : createdAliases) {
222
                        if (a.pxy() == instance)
224
                        if (a.pxy() == instance)
223
                                return a;
225
                                return a;
224
                }
226
                }
225
               
227
               
226
                throw new IllegalStateException("Cannot find alias for " + instance);
228
                throw new IllegalStateException("Cannot find alias for " + instance);
227
        }
229
        }
228
       
230
       
229
        public class Alias<T> {
231
        public class Alias<T> {
230
232
231
                private BeanConfig config;
233
                private BeanConfig config;
232
                private String aliasStr;
234
                private String aliasStr;
233
                private T pxy;
235
                private T pxy;
234
                private String[] returns;
236
                private String[] returns;
235
                private String[] returnMinus;
237
                private String[] returnMinus;
236
                private Map<Key, Alias> joined = new HashMap<Key, Alias>();
238
                private Map<Key, Alias> joined = new HashMap<Key, Alias>();
237
239
238
                private Alias(Class<? extends T> clazz, String aliasStr) {
240
                private Alias(Class<? extends T> clazz, String aliasStr) {
239
241
240
                        this.aliasStr = aliasStr;
242
                        this.aliasStr = aliasStr;
241
                        this.config = session.getConfigFor(clazz);
243
                        this.config = session.getConfigFor(clazz);
242
244
243
                        if (this.config == null)
245
                        if (this.config == null)
244
                                throw new BeanException("BeanConfig not found for "+clazz);
246
                                throw new BeanException("BeanConfig not found for "+clazz);
245
                       
247
                       
246
                        this.pxy = (T) PropertiesProxy.create(config.getBeanClass());
248
                        this.pxy = (T) PropertiesProxy.create(config.getBeanClass());
247
                       
249
                       
248
                        createdAliases.add(this);
250
                        createdAliases.add(this);
249
                }
251
                }
250
252
251
                /**
253
                /**
252
                 * Defines the properties that will return. In other words, <b>only</b> these properties will be populated
254
                 * Defines the properties that will return. In other words, <b>only</b> these properties will be populated
253
                 * @param returns
255
                 * @param returns
254
                 */
256
                 */
255
                public void setReturns(Object... returns){
257
                public void setReturns(Object... returns){
256
258
257
                        this.returns = AnsiSQLBeanSession.getProperties(returns);
259
                        this.returns = AnsiSQLBeanSession.getProperties(returns);
258
                }
260
                }
259
261
260
                /**
262
                /**
261
                 * Defines the properties that will <b>NOT</b> return. In other words, these properties will be not populated
263
                 * Defines the properties that will <b>NOT</b> return. In other words, these properties will be not populated
262
                 * @param returns
264
                 * @param returns
263
                 */
265
                 */
264
                public void setReturnMinus(Object... returns){
266
                public void setReturnMinus(Object... returns){
265
267
266
                        this.returnMinus = AnsiSQLBeanSession.getProperties(returns);
268
                        this.returnMinus = AnsiSQLBeanSession.getProperties(returns);
267
                }
269
                }
268
270
269
                /**
271
                /**
270
                 * Returns the proxy for bean class
272
                 * Returns the proxy for bean class
271
                 * @return The proxy
273
                 * @return The proxy
272
                 */
274
                 */
273
                public T pxy(){
275
                public T pxy(){
274
276
275
                        return pxy;
277
                        return pxy;
276
                }
278
                }
277
279
278
                /**
280
                /**
279
                 * Convert the given property to database column
281
                 * Convert the given property to database column
280
                 * @param property - The bean property (can be through proxy)
282
                 * @param property - The bean property (can be through proxy)
281
                 * @return The database column name
283
                 * @return The database column name
282
                 */
284
                 */
283
                public String toColumn(Object property){
285
                public String toColumn(Object property){
284
286
285
                        return session.propertyToColumn(config.getBeanClass(), property, aliasStr);
287
                        return session.propertyToColumn(config.getBeanClass(), property, aliasStr);
286
                }
288
                }
287
289
288
                /**
290
                /**
289
                 * Populates the bean according to ResultSet
291
                 * Populates the bean according to ResultSet
290
                 * @param rs
292
                 * @param rs
291
                 * @param bean
293
                 * @param bean
292
                 */
294
                 */
293
                public void populateBean(ResultSet rs, T bean){
295
                public void populateBean(ResultSet rs, T bean){
294
296
295
                        session.populateBeanImpl(rs, bean, aliasStr, returns, returnMinus, false);
297
                        session.populateBeanImpl(rs, bean, aliasStr, returns, returnMinus, false);
296
                }
298
                }
297
               
299
               
298
                public void populateAll(ResultSet rs, T bean) {
300
                public void populateAll(ResultSet rs, T bean) {
299
301
300
                        populateBean(rs, bean);
302
                        populateBean(rs, bean);
301
303
302
                        for (Map.Entry<Key, Alias> m : joined.entrySet()) {
304
                        for (Map.Entry<Key, Alias> m : joined.entrySet()) {
303
                               
305
                               
304
                                //only if alias is in SELECT clause
306
                                //only if alias is in SELECT clause
305
                                if (selectAliases.contains(m.getValue())) {
307
                                if (selectAliases.contains(m.getValue())) {
306
                                       
308
                                       
307
                                        Object value = session.getPropertyBean(bean, m.getKey().property, m.getKey().forceInstance);
309
                                        Object value = session.getPropertyBean(bean, m.getKey().property, m.getKey().forceInstance);
308
                                       
310
                                       
309
                                        if (value != null) {
311
                                        if (value != null) {
310
                                                m.getValue().populateAll(rs, value);
312
                                                m.getValue().populateAll(rs, value);
311
                                        }
313
                                        }
312
                                }
314
                                }
313
315
314
                        }
316
                        }
315
                }
317
                }
316
               
318
               
317
                @Override
319
                @Override
318
                public String toString() {
320
                public String toString() {
319
                        return "Alias "+aliasStr+" of "+config.getBeanClass();
321
                        return "Alias "+aliasStr+" of "+config.getBeanClass();
320
                }
322
                }
321
               
323
               
322
                /**
324
                /**
323
                 * Configures a property name to receive data from alias. When <code>forceIntance</code> is <b>true</b>
325
                 * Configures a property name to receive data from alias. When <code>forceIntance</code> is <b>true</b>
324
                 * it will force the creation of a new instance for the property, in other words,
326
                 * it will force the creation of a new instance for the property, in other words,
325
                 * the value will never be <code>null</code>
327
                 * the value will never be <code>null</code>
326
                 * @param property - Bean property to populate
328
                 * @param property - Bean property to populate
327
                 * @param forceInstance
329
                 * @param forceInstance
328
                 * @param alias - Alias
330
                 * @param alias - Alias
329
                 */
331
                 */
330
                private void put(Object property, boolean forceInstance, Alias<?> alias) {
332
                private void put(Object property, boolean forceInstance, Alias<?> alias) {
331
                        joined.put(new Key().property(property).forceInstance(forceInstance), alias);
333
                        joined.put(new Key().property(property).forceInstance(forceInstance), alias);
332
                }
334
                }
333
               
335
               
334
                private class Key {
336
                private class Key {
335
                       
337
                       
336
                        private String property;
338
                        private String property;
337
                        private boolean forceInstance;
339
                        private boolean forceInstance;
338
                       
340
                       
339
                        public Key property(Object property) {
341
                        public Key property(Object property) {
340
                                this.property = AnsiSQLBeanSession.getProperties(new Object[] {property})[0];
342
                                this.property = AnsiSQLBeanSession.getProperties(new Object[] {property})[0];
341
                                //this.property = PropertiesProxy.getPropertyName();
343
                                //this.property = PropertiesProxy.getPropertyName();
342
                                return this;
344
                                return this;
343
                        }
345
                        }
344
                       
346
                       
345
                        public Key forceInstance(boolean force) {
347
                        public Key forceInstance(boolean force) {
346
                                this.forceInstance = force;
348
                                this.forceInstance = force;
347
                                return this;
349
                                return this;
348
                        }
350
                        }
349
                }
351
                }
350
352
351
        }
353
        }
352
354
353
        public class Select implements Appendable<Select> {
355
        public class Select implements Appendable<Select> {
354
356
355
                private boolean init = false;
357
                private boolean init = false;
356
               
358
               
357
                private Select(String str) {
359
                private Select(String str) {
358
                        sb.append("SELECT "+(str == null || str.isEmpty() ? "" : str+" "));
360
                        sb.append("SELECT "+(str == null || str.isEmpty() ? "" : str+" "));
359
                        selectAliases = new ArrayList<Alias<?>>();
361
                        selectAliases = new ArrayList<Alias<?>>();
360
                }
362
                }
361
               
363
               
362
                private Select(String str, Alias<?>... as) {
364
                private Select(String str, Alias<?>... as) {
363
                        this(str);
365
                        this(str);
364
                        this.add(as);
366
                        this.add(as);
365
                }
367
                }
366
               
368
               
367
                private Select(String str, Sentence... sentences) {
369
                private Select(String str, Sentence... sentences) {
368
                        this(str);
370
                        this(str);
369
                        this.add(sentences);
371
                        this.add(sentences);
370
                }
372
                }
371
               
373
               
372
                /**
374
                /**
373
                 * Add the sentences in <code>SELECT</code> clause
375
                 * Add the sentences in <code>SELECT</code> clause
374
                 * @param sentences
376
                 * @param sentences
375
                 * @return this
377
                 * @return this
376
                 */
378
                 */
377
                public Select add(Sentence... sentences) {
379
                public Select add(Sentence... sentences) {
378
                       
380
                       
379
                        for (Sentence s : sentences) {
381
                        for (Sentence s : sentences) {
380
                               
382
                               
381
                                if (s.getName() == null || s.getName().isEmpty())
383
                                if (s.getName() == null || s.getName().isEmpty())
382
                                        throw new BeanException("The sentence ("+s.build()+") in SELECT clause must have a name");
384
                                        throw new BeanException("The sentence ("+s.build()+") in SELECT clause must have a name");
383
                               
385
                               
384
                                if(init)
386
                                if(init)
385
                                        sb.append(",");
387
                                        sb.append(",");
386
                               
388
                               
387
                                sb.append(s.build()).append(' ').append(s.getName());
389
                                sb.append(s.build()).append(' ').append(s.getName());
388
                                QueryBuilder.this.sentences.put(s.getName(), s);
390
                                QueryBuilder.this.sentences.put(s.getName(), s);
389
                                QueryBuilder.this.add(s);
391
                                QueryBuilder.this.add(s);
390
                                init = true;
392
                                init = true;
391
                        }
393
                        }
392
                       
394
                       
393
                        return this;
395
                        return this;
394
                }
396
                }
395
               
397
               
396
                /**
398
                /**
397
                 * Add the alias columns in <code>SELECT</code> clause
399
                 * Add the alias columns in <code>SELECT</code> clause
398
                 * @param as
400
                 * @param as
399
                 * @return this
401
                 * @return this
400
                 */
402
                 */
401
                public Select add(Alias<?>... as) {
403
                public Select add(Alias<?>... as) {
402
404
403
                        for (Alias<?> alias: as) {
405
                        for (Alias<?> alias: as) {
404
406
405
                                if(init)
407
                                if(init)
406
                                        sb.append(",");
408
                                        sb.append(",");
407
409
408
                                selectAliases.add(alias);
410
                                selectAliases.add(alias);
409
                                sb.append(session.buildSelectImpl(alias.config.getBeanClass(), alias.aliasStr, alias.returns, alias.returnMinus, false, true));
411
                                sb.append(session.buildSelectImpl(alias.config.getBeanClass(), alias.aliasStr, alias.returns, alias.returnMinus, false, true));
410
                                init = true;
412
                                init = true;
411
                        }
413
                        }
412
                       
414
                       
413
                        return this;
415
                        return this;
414
                }
416
                }
415
417
416
                /**
418
                /**
417
                 * Creates the <b>FROM</b> keyword for given alias appending the table name in SQL query.
419
                 * Creates the <b>FROM</b> keyword for given alias appending the table name in SQL query.
418
                 * @param alias
420
                 * @param alias
419
                 * @return A new <code>From</code> object
421
                 * @return A new <code>From</code> object
420
                 */
422
                 */
421
                public From from(Alias<?> alias){
423
                public From from(Alias<?> alias){
422
424
423
                        return new From(alias);
425
                        return new From(alias);
424
                }
426
                }
425
427
426
                @Override
428
                @Override
427
                public Select append(Param p) {
429
                public Select append(Param p) {
428
430
429
                        QueryBuilder.this.append(p);
431
                        QueryBuilder.this.append(p);
430
                        return this;
432
                        return this;
431
                }
433
                }
432
        }
434
        }
433
435
434
        public class From extends Query implements CanOrder, CanLimit, CanGroupBy, Appendable<From> {
436
        public class From extends Query implements CanOrder, CanLimit, CanGroupBy, Appendable<From> {
435
437
436
                private From(Alias<?> alias) {
438
                private From(Alias<?> alias) {
437
                       
439
                       
438
                        aliasFrom = alias;
440
                        aliasFrom = alias;
439
                        sb.append(" FROM ").append(alias.config.getTableName()).append(" ").append(alias.aliasStr);
441
                        sb.append(" FROM ").append(alias.config.getTableName()).append(" ").append(alias.aliasStr);
440
                }
442
                }
441
443
442
                private From() {}
444
                private From() {}
443
445
444
                /**
446
                /**
445
                 * Creates a <b>LEFT JOIN</b> sentence using the given alias
447
                 * Creates a <b>LEFT JOIN</b> sentence using the given alias
446
                 * <br><br>
448
                 * <br><br>
447
                 * <b>E.g.:</b>
449
                 * <b>E.g.:</b>
448
                 * <ul>
450
                 * <ul>
449
                 * <code>
451
                 * <code>
450
                 *      builder.select(...)<br><ul>
452
                 *      builder.select(...)<br><ul>
451
                 *              .from(a)<br>
453
                 *              .from(a)<br>
452
                 *              .leftJoin(b)<br>
454
                 *              .leftJoin(b)<br>
453
                 *              ...</ul>
455
                 *              ...</ul>
454
                 * </code>
456
                 * </code>
455
                 * </ul>
457
                 * </ul>
456
                 *
458
                 *
457
                 * @param a - The alias to join
459
                 * @param a - The alias to join
458
                 * @return a new {@link On} object
460
                 * @return a new {@link On} object
459
                 */
461
                 */
460
                public On leftJoin(Alias<?> a){
462
                public On leftJoin(Alias<?> a){
461
                        return join(a, "LEFT JOIN");
463
                        return join(a, "LEFT JOIN");
462
                }
464
                }
463
465
464
                /**
466
                /**
465
                 * Creates a <b>RIGHT JOIN</b> sentence using the given alias
467
                 * Creates a <b>RIGHT JOIN</b> sentence using the given alias
466
                 * <br><br>
468
                 * <br><br>
467
                 * <b>E.g.:</b>
469
                 * <b>E.g.:</b>
468
                 * <ul>
470
                 * <ul>
469
                 * <code>
471
                 * <code>
470
                 *      builder.select(...)<br><ul>
472
                 *      builder.select(...)<br><ul>
471
                 *              .from(a)<br>
473
                 *              .from(a)<br>
472
                 *              .rightJoin(b)<br>
474
                 *              .rightJoin(b)<br>
473
                 *              ...</ul>
475
                 *              ...</ul>
474
                 * </code>
476
                 * </code>
475
                 * </ul>
477
                 * </ul>
476
                 *
478
                 *
477
                 * @param a - The alias to join
479
                 * @param a - The alias to join
478
                 * @return a new {@link On} object
480
                 * @return a new {@link On} object
479
                 */
481
                 */
480
                public On rightJoin(Alias<?> a){
482
                public On rightJoin(Alias<?> a){
481
                        return join(a, "RIGHT JOIN");
483
                        return join(a, "RIGHT JOIN");
482
                }
484
                }
483
485
484
                /**
486
                /**
485
                 * Creates a <b>JOIN</b> sentence using the given alias
487
                 * Creates a <b>JOIN</b> sentence using the given alias
486
                 * <br><br>
488
                 * <br><br>
487
                 * <b>E.g.:</b>
489
                 * <b>E.g.:</b>
488
                 * <ul>
490
                 * <ul>
489
                 * <code>
491
                 * <code>
490
                 *      builder.select(...)<br><ul>
492
                 *      builder.select(...)<br><ul>
491
                 *              .from(a)<br>
493
                 *              .from(a)<br>
492
                 *              .join(b)<br>
494
                 *              .join(b)<br>
493
                 *              ...</ul>
495
                 *              ...</ul>
494
                 * </code>
496
                 * </code>
495
                 * </ul>
497
                 * </ul>
496
                 *
498
                 *
497
                 * @param a - The alias to join
499
                 * @param a - The alias to join
498
                 * @return a new {@link On} object
500
                 * @return a new {@link On} object
499
                 */
501
                 */
500
                public On join(Alias<?> a){
502
                public On join(Alias<?> a){
501
                        return join(a, "JOIN");
503
                        return join(a, "JOIN");
502
                }
504
                }
503
               
505
               
504
                /**
506
                /**
505
                 * Creates a join using the given join type
507
                 * Creates a join using the given join type
506
                 * @param a - Alias to join
508
                 * @param a - Alias to join
507
                 * @param joinType - The join type (E.g: <code>"CROSS JOIN"</code> or <code>"LEFT OUTER JOIN"</code>)
509
                 * @param joinType - The join type (E.g: <code>"CROSS JOIN"</code> or <code>"LEFT OUTER JOIN"</code>)
508
                 * @return a new {@link On} object
510
                 * @return a new {@link On} object
509
                 */
511
                 */
510
                public On join(Alias<?> a, String joinType) {
512
                public On join(Alias<?> a, String joinType) {
511
                        sb.append(" "+joinType+" ");
513
                        sb.append(" "+joinType+" ");
512
                        appendTable(a);
514
                        appendTable(a);
513
                        return new On(a, true);                
515
                        return new On(a, true);                
514
                }
516
                }
515
517
516
                public Where where() {
518
                public Where where() {
517
                        return new Where(true);
519
                        return new Where(true);
518
                }
520
                }
519
521
520
                @Override
522
                @Override
521
                public Order orderBy() {
523
                public Order orderBy() {
522
524
523
                        return new Order();
525
                        return new Order();
524
                }
526
                }
525
527
526
                @Override
528
                @Override
527
                public Limit limit(Object lim) {
529
                public Limit limit(Object lim) {
528
530
529
                        return new Limit(lim);
531
                        return new Limit(lim);
530
                }
532
                }
531
               
533
               
532
                @Override
534
                @Override
533
                public From append(Param p) {
535
                public From append(Param p) {
534
536
535
                        QueryBuilder.this.append(p);
537
                        QueryBuilder.this.append(p);
536
                        return this;
538
                        return this;
537
                }
539
                }
538
540
539
                @Override
541
                @Override
540
                public GroupBy groupBy(Alias<?>... aliases) {
542
                public GroupBy groupBy(Alias<?>... aliases) {
541
                        return new GroupBy(aliases);
543
                        return new GroupBy(aliases);
542
                }
544
                }
543
545
544
                @Override
546
                @Override
545
                public GroupBy groupByProp(Alias<?> alias, Object... properties) {
547
                public GroupBy groupByProp(Alias<?> alias, Object... properties) {
546
                        return new GroupBy(alias, properties);
548
                        return new GroupBy(alias, properties);
547
                }
549
                }
548
550
549
                @Override
551
                @Override
550
                public GroupBy groupBy() {
552
                public GroupBy groupBy() {
551
                        return new GroupBy();
553
                        return new GroupBy();
552
                }
554
                }
553
555
554
                @Override
556
                @Override
555
                public GroupBy groupBy(Param... p) {
557
                public GroupBy groupBy(Param... p) {
556
                        return new GroupBy(p);
558
                        return new GroupBy(p);
557
                }
559
                }
558
        }
560
        }
559
561
560
        /**
562
        /**
561
         * Class representing a 'pos-join' operation
563
         * Class representing a 'pos-join' operation
562
         * @author erico
564
         * @author erico
563
         *
565
         *
564
         */
566
         */
565
        public class On {
567
        public class On {
566
568
567
                private Alias<?> aliasPK;
569
                private Alias<?> aliasPK;
568
570
569
                private On(Alias<?> aliasPK, boolean init) {
571
                private On(Alias<?> aliasPK, boolean init) {
570
572
571
                        sb.append(init ? " ON " : " AND ");
573
                        sb.append(init ? " ON " : " AND ");
572
                        this.aliasPK = aliasPK;
574
                        this.aliasPK = aliasPK;
573
                }
575
                }
574
576
575
                public OnEquals on(Object property) {
577
                public OnEquals on(Object property) {
576
                        sb.append(aliasPK.toColumn(property));
578
                        sb.append(aliasPK.toColumn(property));
577
                        return new OnEquals(aliasPK);
579
                        return new OnEquals(aliasPK);
578
                }
580
                }
579
581
580
                public UsingPK pkOf(Alias<?> alias) {
582
                public UsingPK pkOf(Alias<?> alias) {
581
                        return new UsingPK(alias);
583
                        return new UsingPK(alias);
582
                }
584
                }
583
585
584
        }
586
        }
585
587
586
        public class UsingPK {
588
        public class UsingPK {
587
589
588
                private Alias<?> aliasPK;
590
                private Alias<?> aliasPK;
589
               
591
               
590
                private UsingPK(Alias<?> aliasPK) {
592
                private UsingPK(Alias<?> aliasPK) {
591
                        this.aliasPK = aliasPK;
593
                        this.aliasPK = aliasPK;
592
                }
594
                }
593
595
594
                public PopulateUsing in(Alias<?> aliasFK) {
596
                public PopulateUsing in(Alias<?> aliasFK) {
595
                        buildOn(aliasPK, aliasFK);
597
                        buildOn(aliasPK, aliasFK);
596
                        return new PopulateUsing(aliasPK, aliasFK);
598
                        return new PopulateUsing(aliasPK, aliasFK);
597
                }
599
                }
598
               
600
               
599
                private void buildOn(Alias<?> aPK, Alias<?> aFK){
601
                private void buildOn(Alias<?> aPK, Alias<?> aFK){
600
602
601
                        Iterator<DBField> pks = aPK.config.pks();
603
                        Iterator<DBField> pks = aPK.config.pks();
602
                        DBField df = pks.next();
604
                        DBField df = pks.next();
603
605
604
                        sb.append(aPK.aliasStr).append(".").append(df.getDbName()).append(" = ")
606
                        sb.append(aPK.aliasStr).append(".").append(df.getDbName()).append(" = ")
605
                        .append(aFK.aliasStr).append(".").append(df.getDbName());
607
                        .append(aFK.aliasStr).append(".").append(df.getDbName());
606
608
607
                        while (pks.hasNext()){
609
                        while (pks.hasNext()){
608
610
609
                                df = pks.next();
611
                                df = pks.next();
610
612
611
                                sb.append(" AND ").append(aPK.aliasStr).append(".").append(df.getDbName())
613
                                sb.append(" AND ").append(aPK.aliasStr).append(".").append(df.getDbName())
612
                                .append(" = ").append(aFK.aliasStr).append(".").append(df.getDbName());
614
                                .append(" = ").append(aFK.aliasStr).append(".").append(df.getDbName());
613
615
614
                        }
616
                        }
615
                }
617
                }
616
        }
618
        }
617
       
619
       
618
        public class PopulateUsing extends From {
620
        public class PopulateUsing extends From {
619
               
621
               
620
                private Alias<?> aliasPK, aliasFK;
622
                private Alias<?> aliasPK, aliasFK;
621
               
623
               
622
                public PopulateUsing(Alias<?> aliasPK, Alias<?> aliasFK) {
624
                public PopulateUsing(Alias<?> aliasPK, Alias<?> aliasFK) {
623
                        this.aliasFK = aliasFK;
625
                        this.aliasFK = aliasFK;
624
                        this.aliasPK = aliasPK;
626
                        this.aliasPK = aliasPK;
625
                }
627
                }
626
               
628
               
627
                /**
629
                /**
628
                 * Defines the property of foreign bean <b>(specified on {@link UsingPK#in(Alias)} method)</b>
630
                 * Defines the property of foreign bean <b>(specified on {@link UsingPK#in(Alias)} method)</b>
629
                 * that will receive the value from alias PK <b>(specified on {@link On#pkOf(Alias)} method)</b> and
631
                 * that will receive the value from alias PK <b>(specified on {@link On#pkOf(Alias)} method)</b> and
630
                 * force the creation of a new instance if bean property is not set.
632
                 * force the creation of a new instance if bean property is not set.
631
                 * <br><br>
633
                 * <br><br>
632
                 * <b>E.g.:</b>
634
                 * <b>E.g.:</b>
633
                 * <ul>
635
                 * <ul>
634
                 * <code>
636
                 * <code>
635
                 *      builder.select(user, city)<br><ul>
637
                 *      builder.select(user, city)<br><ul>
636
                 *              .from(user)<br>
638
                 *              .from(user)<br>
637
                 *              .join(city)<br>
639
                 *              .join(city)<br>
638
                 *              .pkOf(city).in(user)<br>
640
                 *              .pkOf(city).in(user)<br>
639
                 *              <b>.inPropertyForcingInstance(user.pxy().getCity())</b><br>
641
                 *              <b>.inPropertyForcingInstance(user.pxy().getCity())</b><br>
640
                 *              ...</ul>
642
                 *              ...</ul>
641
                 * </code>
643
                 * </code>
642
                 * </ul>
644
                 * </ul>
643
                 * @param propertyBean
645
                 * @param propertyBean
644
                 * @return this
646
                 * @return this
645
                 * @see Alias#put(Object, boolean, Alias)
647
                 * @see Alias#put(Object, boolean, Alias)
646
                 */
648
                 */
647
                public From inPropertyForcingInstance(Object propertyBean) {
649
                public From inPropertyForcingInstance(Object propertyBean) {
648
                        aliasFK.put(propertyBean, true, aliasPK);
650
                        aliasFK.put(propertyBean, true, aliasPK);
649
                        return this;
651
                        return this;
650
                }
652
                }
651
               
653
               
652
                /**
654
                /**
653
                 * Defines the property of foreign bean <b>(specified on {@link UsingPK#in(Alias)} method)</b>
655
                 * Defines the property of foreign bean <b>(specified on {@link UsingPK#in(Alias)} method)</b>
654
                 * that will receive the value from alias PK <b>(specified on {@link On#pkOf(Alias)} method)</b>
656
                 * that will receive the value from alias PK <b>(specified on {@link On#pkOf(Alias)} method)</b>
655
                 * <br><br>
657
                 * <br><br>
656
                 * <b>E.g.:</b>
658
                 * <b>E.g.:</b>
657
                 * <ul>
659
                 * <ul>
658
                 * <code>
660
                 * <code>
659
                 *      builder.select(user, city)<br><ul>
661
                 *      builder.select(user, city)<br><ul>
660
                 *              .from(user)<br>
662
                 *              .from(user)<br>
661
                 *              .join(city)<br>
663
                 *              .join(city)<br>
662
                 *              .pkOf(city).in(user)<br>
664
                 *              .pkOf(city).in(user)<br>
663
                 *              <b>.inProperty(user.pxy().getCity())</b><br>
665
                 *              <b>.inProperty(user.pxy().getCity())</b><br>
664
                 *              ...</ul>
666
                 *              ...</ul>
665
                 * </code>
667
                 * </code>
666
                 * </ul>
668
                 * </ul>
667
                 * @param propertyBean
669
                 * @param propertyBean
668
                 * @return this
670
                 * @return this
669
                 * @see Alias#put(Object, boolean, Alias)
671
                 * @see Alias#put(Object, boolean, Alias)
670
                 */
672
                 */
671
                public From inProperty(Object propertyBean) {
673
                public From inProperty(Object propertyBean) {
672
                        aliasFK.put(propertyBean, false, aliasPK);
674
                        aliasFK.put(propertyBean, false, aliasPK);
673
                        return this;
675
                        return this;
674
                }
676
                }
675
               
677
               
676
                /**
678
                /**
677
                 * Defines the property of primary bean <b>(specified on {@link On#pkOf(Alias)} method)</b>
679
                 * Defines the property of primary bean <b>(specified on {@link On#pkOf(Alias)} method)</b>
678
                 * that will receive the value from foreign alias (aliasFK) <b>(specified on {@link UsingPK#in(Alias)} method)</b> and
680
                 * that will receive the value from foreign alias (aliasFK) <b>(specified on {@link UsingPK#in(Alias)} method)</b> and
679
                 * force the creation of a new instance if bean property is not set.
681
                 * force the creation of a new instance if bean property is not set.
680
                 * <br><br><b>Note: </b>The <b>pkProperty</b> is generally used in 1x1 relationship.
682
                 * <br><br><b>Note: </b>The <b>pkProperty</b> is generally used in 1x1 relationship.
681
                 * <br><br>
683
                 * <br><br>
682
                 * <b>E.g.:</b>
684
                 * <b>E.g.:</b>
683
                 * <ul>
685
                 * <ul>
684
                 * <code>
686
                 * <code>
685
                 *      builder.select(person, identity)<br><ul>
687
                 *      builder.select(person, identity)<br><ul>
686
                 *              .from(person)<br>
688
                 *              .from(person)<br>
687
                 *              .join(identity)<br>
689
                 *              .join(identity)<br>
688
                 *              .pkOf(person).in(identity)<br>
690
                 *              .pkOf(person).in(identity)<br>
689
                 *              <b>.pkPropertyForcingInstance(person.pxy().getIdentity())</b><br>
691
                 *              <b>.pkPropertyForcingInstance(person.pxy().getIdentity())</b><br>
690
                 *              ...</ul>
692
                 *              ...</ul>
691
                 * </code>
693
                 * </code>
692
                 * </ul>
694
                 * </ul>
693
                 * @param propertyBean
695
                 * @param propertyBean
694
                 * @return this
696
                 * @return this
695
                 * @see Alias#put(Object, boolean, Alias)
697
                 * @see Alias#put(Object, boolean, Alias)
696
                 */
698
                 */
697
                public From pkPropertyForcingInstance(Object propertyBean) {
699
                public From pkPropertyForcingInstance(Object propertyBean) {
698
                        aliasPK.put(propertyBean, true, aliasFK);
700
                        aliasPK.put(propertyBean, true, aliasFK);
699
                        return this;
701
                        return this;
700
                }
702
                }
701
               
703
               
702
                /**
704
                /**
703
                 * Defines the property of primary bean <b>(specified on {@link On#pkOf(Alias)} method)</b>
705
                 * Defines the property of primary bean <b>(specified on {@link On#pkOf(Alias)} method)</b>
704
                 * that will receive the value from foreign alias (aliasFK) <b>(specified on {@link UsingPK#in(Alias)} method)</b>
706
                 * that will receive the value from foreign alias (aliasFK) <b>(specified on {@link UsingPK#in(Alias)} method)</b>
705
                 * <br><br><b>Note: </b>The <b>pkProperty</b> is generally used in 1x1 relationship.
707
                 * <br><br><b>Note: </b>The <b>pkProperty</b> is generally used in 1x1 relationship.
706
                 * <br><br>
708
                 * <br><br>
707
                 * <b>E.g.:</b>
709
                 * <b>E.g.:</b>
708
                 * <ul>
710
                 * <ul>
709
                 * <code>
711
                 * <code>
710
                 *      builder.select(person, identity)<br><ul>
712
                 *      builder.select(person, identity)<br><ul>
711
                 *              .from(person)<br>
713
                 *              .from(person)<br>
712
                 *              .join(identity)<br>
714
                 *              .join(identity)<br>
713
                 *              .pkOf(person).in(identity)<br>
715
                 *              .pkOf(person).in(identity)<br>
714
                 *              <b>.pkProperty(person.pxy().getIdentity())</b><br>
716
                 *              <b>.pkProperty(person.pxy().getIdentity())</b><br>
715
                 *              ...</ul>
717
                 *              ...</ul>
716
                 * </code>
718
                 * </code>
717
                 * </ul>
719
                 * </ul>
718
                 * @param propertyBean
720
                 * @param propertyBean
719
                 * @return this
721
                 * @return this
720
                 * @see Alias#put(Object, boolean, Alias)
722
                 * @see Alias#put(Object, boolean, Alias)
721
                 */
723
                 */
722
                public From pkProperty(Object propertyBean) {
724
                public From pkProperty(Object propertyBean) {
723
                        aliasPK.put(propertyBean, false, aliasFK);
725
                        aliasPK.put(propertyBean, false, aliasFK);
724
                        return this;
726
                        return this;
725
                }
727
                }
726
        }
728
        }
727
       
729
       
728
        public class OnEquals {
730
        public class OnEquals {
729
731
730
                private Alias<?> aliasPK;
732
                private Alias<?> aliasPK;
731
733
732
                private OnEquals(Alias<?> aliasPK) {
734
                private OnEquals(Alias<?> aliasPK) {
733
                        sb.append('=');
735
                        sb.append('=');
734
                        this.aliasPK = aliasPK;
736
                        this.aliasPK = aliasPK;
735
                }
737
                }
736
738
737
                /**
739
                /**
738
                 * Equals the given property to the property defined in <b>on</b> method
740
                 * Equals the given property to the property defined in <b>on</b> method
739
                 * <br><br>
741
                 * <br><br>
740
                 * <b>E.g.:</b>
742
                 * <b>E.g.:</b>
741
                 * <ul>
743
                 * <ul>
742
                 * <code>
744
                 * <code>
743
                 *      builder.select(a, b)<br><ul>
745
                 *      builder.select(a, b)<br><ul>
744
                 *              .from(a)<br>
746
                 *              .from(a)<br>
745
                 *              .join(b)<br>
747
                 *              .join(b)<br>
746
                 *              .on(b.pxy().getSomething())<br>
748
                 *              .on(b.pxy().getSomething())<br>
747
                 *              <b>.eq(a.pxy().getSomething())</b><br>
749
                 *              <b>.eq(a.pxy().getSomething())</b><br>
748
                 *              ...</ul>
750
                 *              ...</ul>
749
                 * </code>
751
                 * </code>
750
                 * </ul>
752
                 * </ul>
751
                 * @param property
753
                 * @param property
752
                 * @return A new <code>Equals</code> object
754
                 * @return A new <code>Equals</code> object
753
                 */
755
                 */
754
                public Equals eq(Object property) {
756
                public Equals eq(Object property) {
755
                       
757
                       
756
                        Alias<?> alias = findAlias();
758
                        Alias<?> alias = findAlias();
757
                       
759
                       
758
                        sb.append(alias.toColumn(property));
760
                        sb.append(alias.toColumn(property));
759
                        return new Equals(this.aliasPK, alias);
761
                        return new Equals(this.aliasPK, alias);
760
                }
762
                }
761
               
763
               
762
        }
764
        }
763
       
765
       
764
        public class Equals extends From {
766
        public class Equals extends From {
765
767
766
                private Alias<?> aliasFK, aliasPK;
768
                private Alias<?> aliasFK, aliasPK;
767
769
768
                private Equals(Alias<?> aliasPK, Alias<?> aliasFK) {
770
                private Equals(Alias<?> aliasPK, Alias<?> aliasFK) {
769
                        this.aliasPK = aliasPK;
771
                        this.aliasPK = aliasPK;
770
                        this.aliasFK = aliasFK;
772
                        this.aliasFK = aliasFK;
771
                }
773
                }
772
               
774
               
773
                /**
775
                /**
774
                 * Defines the property of bean <b>specified as alias on {@link OnEquals#eq(Alias, Object)} method</b>
776
                 * Defines the property of bean <b>specified as alias on {@link OnEquals#eq(Alias, Object)} method</b>
775
                 * that will receive the value from alias <b>specified on {@link From#join(Alias)} method</b> and
777
                 * that will receive the value from alias <b>specified on {@link From#join(Alias)} method</b> and
776
                 * force the creation of a new instance if bean property is not set.
778
                 * force the creation of a new instance if bean property is not set.
777
                 * <br><br>
779
                 * <br><br>
778
                 * <b>E.g.:</b>
780
                 * <b>E.g.:</b>
779
                 * <ul>
781
                 * <ul>
780
                 * <code>
782
                 * <code>
781
                 *      builder.select(user, city)<br><ul>
783
                 *      builder.select(user, city)<br><ul>
782
                 *              .from(user)<br>
784
                 *              .from(user)<br>
783
                 *              .join(city)<br>
785
                 *              .join(city)<br>
784
                 *              .on(city.pxy().getId())<br>
786
                 *              .on(city.pxy().getId())<br>
785
                 *              .eq(user, user.pxy().getCity().getId())<br>
787
                 *              .eq(user, user.pxy().getCity().getId())<br>
786
                 *              <b>.inPropertyForcingInstance(user.pxy().getCity())</b><br>
788
                 *              <b>.inPropertyForcingInstance(user.pxy().getCity())</b><br>
787
                 *              ...</ul>
789
                 *              ...</ul>
788
                 * </code>
790
                 * </code>
789
                 * </ul>
791
                 * </ul>
790
                 * @param propertyBean
792
                 * @param propertyBean
791
                 * @return this
793
                 * @return this
792
                 * @see Alias#put(Object, boolean, Alias)
794
                 * @see Alias#put(Object, boolean, Alias)
793
                 */
795
                 */
794
                public Equals eqPropertyForcingInstance(Object propertyBean) {
796
                public Equals eqPropertyForcingInstance(Object propertyBean) {
795
                        aliasFK.put(propertyBean, true, aliasPK);
797
                        aliasFK.put(propertyBean, true, aliasPK);
796
                        return this;
798
                        return this;
797
                }
799
                }
798
               
800
               
799
                /**
801
                /**
800
                 * Defines the property of bean <b>specified as alias on {@link OnEquals#eq(Alias, Object)} method</b>
802
                 * Defines the property of bean <b>specified as alias on {@link OnEquals#eq(Alias, Object)} method</b>
801
                 * that will receive the value from alias <b>specified on {@link From#join(Alias)} method</b>
803
                 * that will receive the value from alias <b>specified on {@link From#join(Alias)} method</b>
802
                 * <br><br>
804
                 * <br><br>
803
                 * <b>E.g.:</b>
805
                 * <b>E.g.:</b>
804
                 * <ul>
806
                 * <ul>
805
                 * <code>
807
                 * <code>
806
                 *      builder.select(user, city)<br><ul>
808
                 *      builder.select(user, city)<br><ul>
807
                 *              .from(user)<br>
809
                 *              .from(user)<br>
808
                 *              .join(city)<br>
810
                 *              .join(city)<br>
809
                 *              .on(city.pxy().getId())<br>
811
                 *              .on(city.pxy().getId())<br>
810
                 *              .eq(user, user.pxy().getCity().getId())<br>
812
                 *              .eq(user, user.pxy().getCity().getId())<br>
811
                 *              <b>.inProperty(user.pxy().getCity())</b><br>
813
                 *              <b>.inProperty(user.pxy().getCity())</b><br>
812
                 *              ...</ul>
814
                 *              ...</ul>
813
                 * </code>
815
                 * </code>
814
                 * </ul>
816
                 * </ul>
815
                 * @param propertyBean
817
                 * @param propertyBean
816
                 * @return this
818
                 * @return this
817
                 * @see Alias#put(Object, boolean, Alias)
819
                 * @see Alias#put(Object, boolean, Alias)
818
                 */
820
                 */
819
                public Equals eqProperty(Object propertyBean) {
821
                public Equals eqProperty(Object propertyBean) {
820
                        aliasFK.put(propertyBean, false, aliasPK);
822
                        aliasFK.put(propertyBean, false, aliasPK);
821
                        return this;
823
                        return this;
822
                }
824
                }
823
825
824
                public OnEquals and(Object property) {
826
                public OnEquals and(Object property) {
825
                        return new On(aliasPK, false).on(property);
827
                        return new On(aliasPK, false).on(property);
826
                }
828
                }
827
        }
829
        }
828
830
829
        public class Where implements Appendable<Where>, HasInitClause<InitClauseWhere> {
831
        public class Where implements Appendable<Where>, HasInitClause<InitClauseWhere> {
830
832
831
                private Where (boolean init) {
833
                private Where (boolean init) {
832
                        if (init) {
834
                        if (init) {
833
                                sb.append(" WHERE ");
835
                                sb.append(" WHERE ");
834
                        }
836
                        }
835
                }
837
                }
836
               
838
               
837
                @Override
839
                @Override
838
                public InitClauseWhere clauseIf(boolean clauseIf, Object param) {
840
                public InitClauseWhere clauseIf(boolean clauseIf, Object param) {
839
                        QueryBuilder.this.clauseIf = clauseIf;
841
                        QueryBuilder.this.clauseIf = clauseIf;
840
                        return new InitClauseWhere(param);
842
                        return new InitClauseWhere(param);
841
                }
843
                }
842
844
843
                @Override
845
                @Override
844
                public Where append(Param p) {
846
                public Where append(Param p) {
845
847
846
                        QueryBuilder.this.append(p);
848
                        QueryBuilder.this.append(p);
847
                        return this;
849
                        return this;
848
                }
850
                }
849
851
850
                @Override
852
                @Override
851
                public InitClauseWhere clause(Object param) {
853
                public InitClauseWhere clause(Object param) {
852
                        return clauseIf(true, param);
854
                        return clauseIf(true, param);
853
                }
855
                }
854
856
855
                /**
857
                /**
856
                 * Insert a left parenthesis '(' in query
858
                 * Insert a left parenthesis '(' in query
857
                 * @return this
859
                 * @return this
858
                 */
860
                 */
859
                public Where openPar() {
861
                public Where openPar() {
860
                        QueryBuilder.this.openPar();
862
                        QueryBuilder.this.openPar();
861
                        return this;
863
                        return this;
862
                }
864
                }
863
865
864
        }
866
        }
865
867
866
        public class InitClauseWhere extends InitClause implements Appendable<InitClauseWhere>, HasEndClause<EndClauseWhere> {
868
        public class InitClauseWhere extends InitClause implements Appendable<InitClauseWhere>, HasEndClause<EndClauseWhere> {
867
869
868
                private InitClauseWhere(Object param) {
870
                private InitClauseWhere(Object param) {
869
                       
871
                       
870
                        super(param);
872
                        super(param);
871
                }
873
                }
872
               
874
               
873
                @Override
875
                @Override
874
                public InitClauseWhere append(Param p) {
876
                public InitClauseWhere append(Param p) {
875
877
876
                        QueryBuilder.this.append(p);
878
                        QueryBuilder.this.append(p);
877
                        return this;
879
                        return this;
878
                }
880
                }
879
881
880
                @Override
882
                @Override
881
                public EndClauseWhere condition(String condition) {
883
                public EndClauseWhere condition(String condition) {
882
884
883
                        return new EndClauseWhere(condition);
885
                        return new EndClauseWhere(condition);
884
                }
886
                }
885
887
886
                @Override
888
                @Override
887
                public EndClauseWhere condition(Condition condition) {
889
                public EndClauseWhere condition(Condition condition) {
888
890
889
                        return new EndClauseWhere(condition);
891
                        return new EndClauseWhere(condition);
890
                }
892
                }
891
893
892
        }
894
        }
893
895
894
        public class InitClauseHaving extends InitClause implements Appendable<InitClauseHaving>, HasEndClause<EndClauseHaving> {
896
        public class InitClauseHaving extends InitClause implements Appendable<InitClauseHaving>, HasEndClause<EndClauseHaving> {
895
               
897
               
896
                private InitClauseHaving(Object param) {
898
                private InitClauseHaving(Object param) {
897
                       
899
                       
898
                        super(param);
900
                        super(param);
899
                }
901
                }
900
902
901
                @Override
903
                @Override
902
                public InitClauseHaving append(Param p) {
904
                public InitClauseHaving append(Param p) {
903
905
904
                        QueryBuilder.this.append(p);
906
                        QueryBuilder.this.append(p);
905
                        return this;
907
                        return this;
906
                }
908
                }
907
909
908
                @Override
910
                @Override
909
                public EndClauseHaving condition(String condition) {
911
                public EndClauseHaving condition(String condition) {
910
912
911
                        return new EndClauseHaving(condition);
913
                        return new EndClauseHaving(condition);
912
                }
914
                }
913
915
914
                @Override
916
                @Override
915
                public EndClauseHaving condition(Condition condition) {
917
                public EndClauseHaving condition(Condition condition) {
916
918
917
                        return new EndClauseHaving(condition);
919
                        return new EndClauseHaving(condition);
918
                }
920
                }
919
921
920
        }
922
        }
921
923
922
        public class InitClause {
924
        public class InitClause {
923
               
925
               
924
                private InitClause (Object param) {
926
                private InitClause (Object param) {
925
                       
927
                       
926
                        Param p = paramHandler.findBetter(QueryBuilder.this, param);
928
                        Param p = paramHandler.findBetter(QueryBuilder.this, param);
927
                       
929
                       
928
                        if (clauseIf) {
930
                        if (clauseIf) {
929
//                              System.out.println(p.getClass()+" - "+p.paramInQuery());
931
//                              System.out.println(p.getClass()+" - "+p.paramInQuery());
930
//                              if (p.values() != null)
932
//                              if (p.values() != null)
931
//                              for (Object o : p.values()) {
933
//                              for (Object o : p.values()) {
932
//                                      if (o != null)
934
//                                      if (o != null)
933
//                                      System.out.println("type: "+o.getClass());
935
//                                      System.out.println("type: "+o.getClass());
934
//                              }
936
//                              }
935
                                       
937
                                       
936
                                add(p);
938
                                add(p);
937
                                sb.append(' ').append(p.paramInQuery());
939
                                sb.append(' ').append(p.paramInQuery());
938
                        }
940
                        }
939
                       
941
                       
940
                }
942
                }
941
943
942
        }
944
        }
943
945
944
        public class EndClauseWhere extends EndClause implements Appendable<EndClauseWhere>, CanGroupBy {
946
        public class EndClauseWhere extends EndClause implements Appendable<EndClauseWhere>, CanGroupBy {
945
947
946
                private EndClauseWhere(Condition condition) {
948
                private EndClauseWhere(Condition condition) {
947
949
948
                        if (clauseIf) {
950
                        if (clauseIf) {
949
                                add(condition);
951
                                add(condition);
950
                                init(condition.build());
952
                                init(condition.build());
951
                        }
953
                        }
952
                }
954
                }
953
955
954
                private EndClauseWhere(String condition) {
956
                private EndClauseWhere(String condition) {
955
957
956
                        if (clauseIf) {
958
                        if (clauseIf) {
957
                                init(condition);
959
                                init(condition);
958
                        }
960
                        }
959
                }
961
                }
960
               
962
               
961
                /**
963
                /**
962
                 * Insert a left parenthesis '(' in query
964
                 * Insert a left parenthesis '(' in query
963
                 * @return this
965
                 * @return this
964
                 */
966
                 */
965
                public EndClauseWhere openPar() {
967
                public EndClauseWhere openPar() {
966
                        QueryBuilder.this.openPar();
968
                        QueryBuilder.this.openPar();
967
                        return this;
969
                        return this;
968
                }
970
                }
969
               
971
               
970
                /**
972
                /**
971
                 * Insert a right parenthesis ')' in query
973
                 * Insert a right parenthesis ')' in query
972
                 * @return this
974
                 * @return this
973
                 */
975
                 */
974
                public EndClauseWhere closePar() {
976
                public EndClauseWhere closePar() {
975
                        QueryBuilder.this.closePar();
977
                        QueryBuilder.this.closePar();
976
                        return this;
978
                        return this;
977
                }
979
                }
978
980
979
                public Where and() {
981
                public Where and() {
980
                       
982
                       
981
                        addAnd();
983
                        addAnd();
982
                        return new Where(false);
984
                        return new Where(false);
983
                }
985
                }
984
986
985
                public Where or() {
987
                public Where or() {
986
                       
988
                       
987
                        addOr();
989
                        addOr();
988
                        return new Where(false);
990
                        return new Where(false);
989
                }
991
                }
990
992
991
                @Override
993
                @Override
992
                public EndClauseWhere append(Param p) {
994
                public EndClauseWhere append(Param p) {
993
995
994
                        QueryBuilder.this.append(p);
996
                        QueryBuilder.this.append(p);
995
                        return this;
997
                        return this;
996
                }
998
                }
997
999
998
                @Override
1000
                @Override
999
                public GroupBy groupBy(Alias<?>... aliases) {
1001
                public GroupBy groupBy(Alias<?>... aliases) {
1000
                        return new GroupBy(aliases);
1002
                        return new GroupBy(aliases);
1001
                }
1003
                }
1002
               
1004
               
1003
                @Override
1005
                @Override
1004
                public GroupBy groupBy(Param... params) {
1006
                public GroupBy groupBy(Param... params) {
1005
                        return new GroupBy(params);
1007
                        return new GroupBy(params);
1006
                }
1008
                }
1007
1009
1008
                @Override
1010
                @Override
1009
                public GroupBy groupByProp(Alias<?> alias, Object... properties) {
1011
                public GroupBy groupByProp(Alias<?> alias, Object... properties) {
1010
                        return new GroupBy(alias, properties);
1012
                        return new GroupBy(alias, properties);
1011
                }
1013
                }
1012
1014
1013
                @Override
1015
                @Override
1014
                public GroupBy groupBy() {
1016
                public GroupBy groupBy() {
1015
                        return new GroupBy();
1017
                        return new GroupBy();
1016
                }
1018
                }
1017
1019
1018
        }
1020
        }
1019
1021
1020
        public class EndClauseHaving extends EndClause implements Appendable<EndClauseHaving> {
1022
        public class EndClauseHaving extends EndClause implements Appendable<EndClauseHaving> {
1021
1023
1022
                private EndClauseHaving(Condition condition) {
1024
                private EndClauseHaving(Condition condition) {
1023
1025
1024
                        if (clauseIf) {
1026
                        if (clauseIf) {
1025
                                add(condition);
1027
                                add(condition);
1026
                                init(condition.build());
1028
                                init(condition.build());
1027
                        }
1029
                        }
1028
                }
1030
                }
1029
1031
1030
                private EndClauseHaving(String condition) {
1032
                private EndClauseHaving(String condition) {
1031
1033
1032
                        if (clauseIf) {
1034
                        if (clauseIf) {
1033
                                init(condition);
1035
                                init(condition);
1034
                        }
1036
                        }
1035
                }
1037
                }
1036
               
1038
               
1037
                /**
1039
                /**
1038
                 * Insert a left parenthesis '(' in query
1040
                 * Insert a left parenthesis '(' in query
1039
                 * @return this
1041
                 * @return this
1040
                 */
1042
                 */
1041
                public EndClauseHaving openPar() {
1043
                public EndClauseHaving openPar() {
1042
                       
1044
                       
1043
                        QueryBuilder.this.openPar();
1045
                        QueryBuilder.this.openPar();
1044
                        return this;
1046
                        return this;
1045
                }
1047
                }
1046
               
1048
               
1047
                /**
1049
                /**
1048
                 * Insert a right parenthesis ')' in query
1050
                 * Insert a right parenthesis ')' in query
1049
                 * @return this
1051
                 * @return this
1050
                 */
1052
                 */
1051
                public EndClauseHaving closePar() {
1053
                public EndClauseHaving closePar() {
1052
                       
1054
                       
1053
                        QueryBuilder.this.closePar();
1055
                        QueryBuilder.this.closePar();
1054
                        return this;
1056
                        return this;
1055
                }
1057
                }
1056
1058
1057
                public Having and() {
1059
                public Having and() {
1058
                       
1060
                       
1059
                        addAnd();
1061
                        addAnd();
1060
                        return new Having(false);
1062
                        return new Having(false);
1061
                }
1063
                }
1062
1064
1063
                public Having or() {
1065
                public Having or() {
1064
                       
1066
                       
1065
                        addOr();
1067
                        addOr();
1066
                        return new Having(false);
1068
                        return new Having(false);
1067
                }
1069
                }
1068
1070
1069
                @Override
1071
                @Override
1070
                public EndClauseHaving append(Param p) {
1072
                public EndClauseHaving append(Param p) {
1071
1073
1072
                        QueryBuilder.this.append(p);
1074
                        QueryBuilder.this.append(p);
1073
                        return this;
1075
                        return this;
1074
                }
1076
                }
1075
1077
1076
        }
1078
        }
1077
1079
1078
        public abstract class EndClause extends Query implements CanOrder, CanLimit {
1080
        public abstract class EndClause extends Query implements CanOrder, CanLimit {
1079
1081
1080
                protected void init(String condition) {
1082
                protected void init(String condition) {
1081
1083
1082
                        sb.append(' ').append(condition);
1084
                        sb.append(' ').append(condition);
1083
                }
1085
                }
1084
1086
1085
                @Override
1087
                @Override
1086
                public Order orderBy() {
1088
                public Order orderBy() {
1087
1089
1088
                        return new Order();
1090
                        return new Order();
1089
                }
1091
                }
1090
1092
1091
                @Override
1093
                @Override
1092
                public Limit limit(Object lim) {
1094
                public Limit limit(Object lim) {
1093
1095
1094
                        return new Limit(lim);
1096
                        return new Limit(lim);
1095
                }
1097
                }
1096
               
1098
               
1097
        }
1099
        }
1098
1100
1099
        public class Limit extends Query implements CanOrder, Appendable<Limit> {
1101
        public class Limit extends Query implements CanOrder, Appendable<Limit> {
1100
1102
1101
                private Limit(Object lim) {
1103
                private Limit(Object lim) {
1102
1104
1103
                        Param param = paramHandler.findBetter(QueryBuilder.this, lim);
1105
                        Param param = paramHandler.findBetter(QueryBuilder.this, lim);
1104
                       
1106
                       
1105
                        if (param != null) {
1107
                        if (param != null) {
1106
                                applyRegex();
1108
                                applyRegex();
1107
                                add(param);
1109
                                add(param);
1108
                               
1110
                               
1109
                                Object numberObj = paramValues.get(paramValues.size()-1);
1111
                                Object numberObj = paramValues.get(paramValues.size()-1);
1110
                                if (numberObj instanceof Number) {
1112
                                if (numberObj instanceof Number) {
1111
                                        Number numberLimit = (Number) numberObj;
1113
                                        Number numberLimit = (Number) numberObj;
1112
                                        if (numberLimit.longValue() <= 0) {
1114
                                        if (numberLimit.longValue() <= 0) {
1113
                                                paramValues.remove(paramValues.size()-1);
1115
                                                paramValues.remove(paramValues.size()-1);
1114
                                                return;
1116
                                                return;
1115
                                        }
1117
                                        }
1116
                                }
1118
                                }
1117
                               
1119
                               
1118
                                sb.append(" LIMIT ").append(param.paramInQuery());
1120
                                sb.append(" LIMIT ").append(param.paramInQuery());
1119
                        }
1121
                        }
1120
                }
1122
                }
1121
               
1123
               
1122
                @Override
1124
                @Override
1123
                public Order orderBy() {
1125
                public Order orderBy() {
1124
1126
1125
                        return new Order();
1127
                        return new Order();
1126
                }
1128
                }
1127
1129
1128
                public Offset offset(Integer offset) {
1130
                public Offset offset(Integer offset) {
1129
1131
1130
                        return new Offset(offset);
1132
                        return new Offset(offset);
1131
                }
1133
                }
1132
               
1134
               
1133
                public Offset offset(Param param) {
1135
                public Offset offset(Param param) {
1134
                       
1136
                       
1135
                        return new Offset(param);
1137
                        return new Offset(param);
1136
                }
1138
                }
1137
1139
1138
                @Override
1140
                @Override
1139
                public Limit append(Param p) {
1141
                public Limit append(Param p) {
1140
1142
1141
                        QueryBuilder.this.append(p);
1143
                        QueryBuilder.this.append(p);
1142
                        return this;
1144
                        return this;
1143
                }
1145
                }
1144
        }
1146
        }
1145
1147
1146
        public class Offset extends Query implements Appendable<Offset> {
1148
        public class Offset extends Query implements Appendable<Offset> {
1147
1149
1148
                public Offset(Number offset) {
1150
                public Offset(Number offset) {
1149
                        this(offset != null && offset.longValue() > 0 ? new ParamValue(offset) : null);
1151
                        this(offset != null && offset.longValue() > 0 ? new ParamValue(offset) : null);
1150
                }
1152
                }
1151
               
1153
               
1152
                public Offset(Param param) {
1154
                public Offset(Param param) {
1153
                       
1155
                       
1154
                        if (param != null) {
1156
                        if (param != null) {
1155
                                add(param);
1157
                                add(param);
1156
                                sb.append(" OFFSET ").append(param.paramInQuery());
1158
                                sb.append(" OFFSET ").append(param.paramInQuery());
1157
                        }
1159
                        }
1158
                }
1160
                }
1159
1161
1160
                public Order orderBy() {
1162
                public Order orderBy() {
1161
1163
1162
                        return new Order();
1164
                        return new Order();
1163
                }
1165
                }
1164
1166
1165
                @Override
1167
                @Override
1166
                public Offset append(Param p) {
1168
                public Offset append(Param p) {
1167
1169
1168
                        QueryBuilder.this.append(p);
1170
                        QueryBuilder.this.append(p);
1169
                        return this;
1171
                        return this;
1170
                }
1172
                }
1171
1173
1172
        }
1174
        }
1173
1175
1174
        public class Order implements Appendable<Order> {
1176
        public class Order implements Appendable<Order> {
1175
1177
1176
                private Order() {
1178
                private Order() {
1177
1179
1178
                        applyRegex();
1180
                        applyRegex();
1179
                        sb.append(" ORDER BY ");                       
1181
                        sb.append(" ORDER BY ");                       
1180
                }
1182
                }
1181
               
1183
               
1182
                public Ordering asc(Param param) {
1184
                public Ordering asc(Param param) {
1183
                       
1185
                       
1184
                        return new Ordering().asc(param);
1186
                        return new Ordering().asc(param);
1185
                }
1187
                }
1186
               
1188
               
1187
                public Ordering desc(Param param) {
1189
                public Ordering desc(Param param) {
1188
                       
1190
                       
1189
                        return new Ordering().desc(param);
1191
                        return new Ordering().desc(param);
1190
                }
1192
                }
1191
1193
1192
                public Ordering asc(Alias<?> alias, Object... properties){
1194
                public Ordering asc(Alias<?> alias, Object... properties){
1193
1195
1194
                        return new Ordering().asc(alias, properties);
1196
                        return new Ordering().asc(alias, properties);
1195
                }
1197
                }
1196
1198
1197
                public Ordering desc(Alias<?> alias, Object... properties){
1199
                public Ordering desc(Alias<?> alias, Object... properties){
1198
                       
1200
                       
1199
                        return new Ordering().desc(alias, properties);
1201
                        return new Ordering().desc(alias, properties);
1200
                }
1202
                }
1201
               
1203
               
1202
                @Override
1204
                @Override
1203
                public Order append(Param p) {
1205
                public Order append(Param p) {
1204
1206
1205
                        QueryBuilder.this.append(p);
1207
                        QueryBuilder.this.append(p);
1206
                        return this;
1208
                        return this;
1207
                }
1209
                }
1208
        }
1210
        }
1209
       
1211
       
1210
        public class Ordering extends Query implements CanLimit, Appendable<Ordering> {
1212
        public class Ordering extends Query implements CanLimit, Appendable<Ordering> {
1211
               
1213
               
1212
                private boolean alreadyOrder = false;
1214
                private boolean alreadyOrder = false;
1213
               
1215
               
1214
                private void initOrder() {
1216
                private void initOrder() {
1215
                       
1217
                       
1216
                        if (alreadyOrder) {
1218
                        if (alreadyOrder) {
1217
                                sb.append(',');
1219
                                sb.append(',');
1218
                        }
1220
                        }
1219
                       
1221
                       
1220
                        alreadyOrder = true;
1222
                        alreadyOrder = true;
1221
                }
1223
                }
1222
               
1224
               
1223
                public Ordering asc(Param param) {
1225
                public Ordering asc(Param param) {
1224
                       
1226
                       
1225
                        initOrder();
1227
                        initOrder();
1226
                        add(param);
1228
                        add(param);
1227
                        sb.append(param.paramInQuery()).append(" ASC ");
1229
                        sb.append(param.paramInQuery()).append(" ASC ");
1228
                        return this;
1230
                        return this;
1229
                }
1231
                }
1230
               
1232
               
1231
                public Ordering desc(Param param) {
1233
                public Ordering desc(Param param) {
1232
                       
1234
                       
1233
                        initOrder();
1235
                        initOrder();
1234
                        add(param);
1236
                        add(param);
1235
                        sb.append(param.paramInQuery()).append(" DESC ");
1237
                        sb.append(param.paramInQuery()).append(" DESC ");
1236
                        return this;
1238
                        return this;
1237
                }
1239
                }
1238
1240
1239
                public Ordering asc(Alias<?> alias, Object... properties){
1241
                public Ordering asc(Alias<?> alias, Object... properties){
1240
                        iterateOrderBy(" ASC ", alias, properties);
1242
                        iterateOrderBy(" ASC ", alias, properties);
1241
                        return this;
1243
                        return this;
1242
                }
1244
                }
1243
1245
1244
                public Ordering desc(Alias<?> alias, Object... properties){
1246
                public Ordering desc(Alias<?> alias, Object... properties){
1245
                        iterateOrderBy(" DESC ", alias, properties);
1247
                        iterateOrderBy(" DESC ", alias, properties);
1246
                        return this;
1248
                        return this;
1247
                }
1249
                }
1248
               
1250
               
1249
                @Override
1251
                @Override
1250
                public Limit limit(Object lim) {
1252
                public Limit limit(Object lim) {
1251
1253
1252
                        return new Limit(lim);
1254
                        return new Limit(lim);
1253
                }
1255
                }
1254
               
1256
               
1255
                private void iterateOrderBy(String orderType, Alias<?> alias, Object[] properties){
1257
                private void iterateOrderBy(String orderType, Alias<?> alias, Object[] properties){
1256
1258
1257
                        String[] props = AnsiSQLBeanSession.getProperties(properties);
1259
                        String[] props = AnsiSQLBeanSession.getProperties(properties);
1258
1260
1259
                        initOrder();
1261
                        initOrder();
1260
1262
1261
                        for(String prop : props){
1263
                        for(String prop : props){
1262
1264
1263
                                sb.append(alias.toColumn(prop)).append(orderType).append(",");
1265
                                sb.append(alias.toColumn(prop)).append(orderType).append(",");
1264
                        }
1266
                        }
1265
1267
1266
                        sb.setCharAt(sb.length()-1, ' ');
1268
                        sb.setCharAt(sb.length()-1, ' ');
1267
                }
1269
                }
1268
1270
1269
                @Override
1271
                @Override
1270
                public Ordering append(Param p) {
1272
                public Ordering append(Param p) {
1271
                        QueryBuilder.this.append(p);
1273
                        QueryBuilder.this.append(p);
1272
                        return this;
1274
                        return this;
1273
                }
1275
                }
1274
        }
1276
        }
1275
1277
1276
        public class GroupBy extends Query implements Appendable<GroupBy>, CanLimit, CanOrder {
1278
        public class GroupBy extends Query implements Appendable<GroupBy>, CanLimit, CanOrder {
1277
1279
1278
                private void init() {
1280
                private void init() {
1279
                       
1281
                       
1280
                        applyRegex();
1282
                        applyRegex();
1281
                        sb.append(!sb.toString().endsWith(" GROUP BY ") ? " GROUP BY " : ",");
1283
                        sb.append(!sb.toString().endsWith(" GROUP BY ") ? " GROUP BY " : ",");
1282
                }
1284
                }
1283
1285
1284
                private GroupBy(Alias<?> alias, Object... properties) {
1286
                private GroupBy(Alias<?> alias, Object... properties) {
1285
                        init();
1287
                        init();
1286
                        add(alias, properties);
1288
                        add(alias, properties);
1287
                }
1289
                }
1288
1290
1289
                private GroupBy(Alias<?>... alias) {
1291
                private GroupBy(Alias<?>... alias) {
1290
                        init();
1292
                        init();
1291
                        add(alias);
1293
                        add(alias);
1292
                }
1294
                }
1293
               
1295
               
1294
                private GroupBy(Param... params) {
1296
                private GroupBy(Param... params) {
1295
                        init();
1297
                        init();
1296
                        add(params);
1298
                        add(params);
1297
                }
1299
                }
1298
               
1300
               
1299
                private GroupBy() {
1301
                private GroupBy() {
1300
                        init();
1302
                        init();
1301
                        add(selectAliases.toArray(new Alias<?>[0]));
1303
                        add(selectAliases.toArray(new Alias<?>[0]));
1302
                }
1304
                }
1303
1305
1304
                public GroupBy add(Alias<?> alias, Object... properties) {
1306
                public GroupBy add(Alias<?> alias, Object... properties) {
1305
                       
1307
                       
1306
                        if (!sb.toString().endsWith(" GROUP BY ")) {
1308
                        if (!sb.toString().endsWith(" GROUP BY ")) {
1307
                                sb.append(',');
1309
                                sb.append(',');
1308
                        }
1310
                        }
1309
                       
1311
                       
1310
                        sb.append(session.buildSelectImpl(alias.config.getBeanClass(), alias.aliasStr,
1312
                        sb.append(session.buildSelectImpl(alias.config.getBeanClass(), alias.aliasStr,
1311
                                        AnsiSQLBeanSession.getProperties(properties), null, false, false));
1313
                                        AnsiSQLBeanSession.getProperties(properties), null, false, false));
1312
                       
1314
                       
1313
                        return this;
1315
                        return this;
1314
                }
1316
                }
1315
1317
1316
                public GroupBy add(Alias<?>... aliases) {
1318
                public GroupBy add(Alias<?>... aliases) {
1317
                       
1319
                       
1318
                        for (Alias<?> alias : aliases) {
1320
                        for (Alias<?> alias : aliases) {
1319
                               
1321
                               
1320
                                if (!sb.toString().endsWith(" GROUP BY "))
1322
                                if (!sb.toString().endsWith(" GROUP BY "))
1321
                                        sb.append(',');
1323
                                        sb.append(',');
1322
                               
1324
                               
1323
                                sb.append(session.buildSelectImpl(alias.config.getBeanClass(), alias.aliasStr,
1325
                                sb.append(session.buildSelectImpl(alias.config.getBeanClass(), alias.aliasStr,
1324
                                                alias.returns, alias.returnMinus, false, false));
1326
                                                alias.returns, alias.returnMinus, false, false));
1325
                        }
1327
                        }
1326
                       
1328
                       
1327
                        return this;
1329
                        return this;
1328
                }
1330
                }
1329
               
1331
               
1330
                public GroupBy add(Param... params) {
1332
                public GroupBy add(Param... params) {
1331
                       
1333
                       
1332
                        for (Param p : params) {
1334
                        for (Param p : params) {
1333
                                if (!sb.toString().endsWith(" GROUP BY "))
1335
                                if (!sb.toString().endsWith(" GROUP BY "))
1334
                                        sb.append(',');
1336
                                        sb.append(',');
1335
                               
1337
                               
1336
                                append(p);
1338
                                append(p);
1337
                        }
1339
                        }
1338
                       
1340
                       
1339
                        return this;
1341
                        return this;
1340
                }
1342
                }
1341
1343
1342
                public Having having() {
1344
                public Having having() {
1343
                        return new Having(true);
1345
                        return new Having(true);
1344
                }
1346
                }
1345
1347
1346
                @Override
1348
                @Override
1347
                public GroupBy append(Param p) {
1349
                public GroupBy append(Param p) {
1348
                        QueryBuilder.this.append(p);
1350
                        QueryBuilder.this.append(p);
1349
                        return this;
1351
                        return this;
1350
                }
1352
                }
1351
1353
1352
                @Override
1354
                @Override
1353
                public Order orderBy() {
1355
                public Order orderBy() {
1354
                        return new Order();
1356
                        return new Order();
1355
                }
1357
                }
1356
1358
1357
                @Override
1359
                @Override
1358
                public Limit limit(Object lim) {
1360
                public Limit limit(Object lim) {
1359
                        return new Limit(lim);
1361
                        return new Limit(lim);
1360
                }
1362
                }
1361
1363
1362
        }
1364
        }
1363
1365
1364
        public class Having extends Query implements Appendable<Having>, HasInitClause<InitClauseHaving>{
1366
        public class Having extends Query implements Appendable<Having>, HasInitClause<InitClauseHaving>{
1365
1367
1366
                private Having (boolean init) {
1368
                private Having (boolean init) {
1367
                        if (init) {
1369
                        if (init) {
1368
                                sb.append(" HAVING ");
1370
                                sb.append(" HAVING ");
1369
                        }
1371
                        }
1370
                }
1372
                }
1371
1373
1372
                @Override
1374
                @Override
1373
                public InitClauseHaving clauseIf(boolean clauseIf, Object param){
1375
                public InitClauseHaving clauseIf(boolean clauseIf, Object param){
1374
                       
1376
                       
1375
                        QueryBuilder.this.clauseIf = clauseIf;
1377
                        QueryBuilder.this.clauseIf = clauseIf;
1376
                        return new InitClauseHaving(param);
1378
                        return new InitClauseHaving(param);
1377
                }
1379
                }
1378
               
1380
               
1379
                @Override
1381
                @Override
1380
                public Having append(Param p) {
1382
                public Having append(Param p) {
1381
                        QueryBuilder.this.append(p);
1383
                        QueryBuilder.this.append(p);
1382
                        return this;
1384
                        return this;
1383
                }
1385
                }
1384
1386
1385
                @Override
1387
                @Override
1386
                public InitClauseHaving clause(Object param) {
1388
                public InitClauseHaving clause(Object param) {
1387
                        return clauseIf(true, param);
1389
                        return clauseIf(true, param);
1388
                }
1390
                }
1389
1391
1390
                /**
1392
                /**
1391
                 * Insert a left parenthesis '(' in query
1393
                 * Insert a left parenthesis '(' in query
1392
                 * @return this
1394
                 * @return this
1393
                 */
1395
                 */
1394
                public Having openPar() {
1396
                public Having openPar() {
1395
                        QueryBuilder.this.openPar();
1397
                        QueryBuilder.this.openPar();
1396
                        return this;
1398
                        return this;
1397
                }
1399
                }
1398
1400
1399
        }
1401
        }
1400
1402
1401
        public interface HasInitClause<T extends InitClause> {
1403
        public interface HasInitClause<T extends InitClause> {
1402
1404
1403
                /**
1405
                /**
1404
                 * Insert the param as a clause in query (same of <code>clauseIf(true, param)</code>).
1406
                 * Insert the param as a clause in query (same of <code>clauseIf(true, param)</code>).
1405
                 * <p>
1407
                 * <p>
1406
                 * <b>E.g.:</b>
1408
                 * <b>E.g.:</b>
1407
                 * <ul>
1409
                 * <ul>
1408
                 * <code>
1410
                 * <code>
1409
                 *              ...<br>
1411
                 *              ...<br>
1410
                 *              .where()<br>
1412
                 *              .where()<br>
1411
                 *              .clause(new ParamNative("anything"))<br>
1413
                 *              .clause(new ParamNative("anything"))<br>
1412
                 *              .condition(...)<br>
1414
                 *              .condition(...)<br>
1413
                 *              ...<br>
1415
                 *              ...<br>
1414
                 *
1416
                 *
1415
                 * </code>
1417
                 * </code>
1416
                 * </ul>
1418
                 * </ul>
1417
                 * </p>
1419
                 * </p>
1418
                 * @param param
1420
                 * @param param
1419
                 */
1421
                 */
1420
                public T clause(Object param);
1422
                public T clause(Object param);
1421
               
1423
               
1422
                /**
1424
                /**
1423
                 * Insert the param as a clause in query if and only if the flag <b>clauseIf</b> is <b>true</b>
1425
                 * Insert the param as a clause in query if and only if the flag <b>clauseIf</b> is <b>true</b>
1424
                 * @param clauseIf - Flag indicating if this clause will be inserted in SQL query
1426
                 * @param clauseIf - Flag indicating if this clause will be inserted in SQL query
1425
                 * @param param
1427
                 * @param param
1426
                 * @see #clause(Param)
1428
                 * @see #clause(Param)
1427
                 */
1429
                 */
1428
                public T clauseIf(boolean clauseIf, Object param);
1430
                public T clauseIf(boolean clauseIf, Object param);
1429
               
1431
               
1430
        }
1432
        }
1431
1433
1432
        public interface HasEndClause<T extends EndClause> {
1434
        public interface HasEndClause<T extends EndClause> {
1433
1435
1434
                public T condition(String condition);
1436
                public T condition(String condition);
1435
1437
1436
                public T condition(Condition condition);
1438
                public T condition(Condition condition);
1437
1439
1438
        }
1440
        }
1439
1441
1440
        public interface CanOrder {
1442
        public interface CanOrder {
1441
1443
1442
                public Order orderBy();
1444
                public Order orderBy();
1443
        }
1445
        }
1444
1446
1445
        public interface CanLimit {
1447
        public interface CanLimit {
1446
1448
1447
                public Limit limit(Object lim);
1449
                public Limit limit(Object lim);
1448
        }
1450
        }
1449
1451
1450
        public interface CanGroupBy {
1452
        public interface CanGroupBy {
1451
1453
1452
                public GroupBy groupBy(Alias<?>... aliases);
1454
                public GroupBy groupBy(Alias<?>... aliases);
1453
               
1455
               
1454
                public GroupBy groupBy(Param... p);
1456
                public GroupBy groupBy(Param... p);
1455
1457
1456
                public GroupBy groupByProp(Alias<?> alias, Object... properties);
1458
                public GroupBy groupByProp(Alias<?> alias, Object... properties);
1457
               
1459
               
1458
                /**
1460
                /**
1459
                 * Group by all aliases fields used in <i>SELECT</i> clause
1461
                 * Group by all aliases fields used in <i>SELECT</i> clause
1460
                 * @return this
1462
                 * @return this
1461
                 */
1463
                 */
1462
                public GroupBy groupBy();
1464
                public GroupBy groupBy();
1463
               
1465
               
1464
        }
1466
        }
1465
1467
1466
        public interface Appendable<T> {
1468
        public interface Appendable<T> {
1467
1469
1468
                /**
1470
                /**
1469
                 * Appends the parameter directly in query
1471
                 * Appends the parameter directly in query
1470
                 * @param p - Param
1472
                 * @param p - Param
1471
                 * @return this
1473
                 * @return this
1472
                 */
1474
                 */
1473
                public T append(Param p);
1475
                public T append(Param p);
1474
        }
1476
        }
1475
       
1477
       
1476
        public void finish() {
1478
        public void finish() {
1477
               
1479
               
1478
                for (Alias<?> a : selectAliases) {
1480
                for (Alias<?> a : selectAliases) {
1479
                        a.joined.clear();
1481
                        a.joined.clear();
1480
                }
1482
                }
1481
               
1483
               
1482
                paramValues.clear();
1484
                paramValues.clear();
1483
                sb = new StringBuilder();                      
1485
                sb = new StringBuilder();                      
1484
        }
1486
        }
1485
       
1487
       
1486
        /**
1488
        /**
1487
         * Represents a query ready to execute
1489
         * Represents a query ready to execute
1488
         * @author erico
1490
         * @author erico
1489
         *
1491
         *
1490
         */
1492
         */
1491
        public class Query {
1493
        public class Query {
1492
1494
1493
                private Query() {}
1495
                private Query() {}
1494
               
1496
               
1495
                /**
1497
                /**
1496
                 * Returns a <code>PreparedStatement</code> setting all given parameters in order.
1498
                 * Returns a <code>PreparedStatement</code> setting all given parameters in order.
1497
                 *
1499
                 *
1498
                 * @param params
1500
                 * @param params
1499
                 * @return A <code>PreparedStatement</code> using this session connection
1501
                 * @return A <code>PreparedStatement</code> using this session connection
1500
                 * @see #getSQL()
1502
                 * @see #getSQL()
1501
                 * @see SQLUtils#prepare(java.sql.Connection, String, Object...)
1503
                 * @see SQLUtils#prepare(java.sql.Connection, String, Object...)
1502
                 */
1504
                 */
1503
                private PreparedStatement prepare(Object... params) {
1505
                private PreparedStatement prepare(Object... params) {
1504
1506
1505
                        try {
1507
                        try {
1506
1508
1507
                                PreparedStatement ppst = SQLUtils.prepare(session.getConnection(), getSQL(), params);
1509
                                PreparedStatement ppst = SQLUtils.prepare(session.getConnection(), getSQL(), params);
1508
                               
1510
                               
1509
                                if (AnsiSQLBeanSession.DEBUG_NATIVE) {
1511
                                if (AnsiSQLBeanSession.DEBUG_NATIVE) {
1510
                                        System.out.println("CUSTOM QUERY (NATIVE): "+ppst);
1512
                                        System.out.println("CUSTOM QUERY (NATIVE): "+ppst);
1511
                                }
1513
                                }
1512
                               
1514
                               
1513
                                return ppst;
1515
                                return ppst;
1514
                               
1516
                               
1515
                        } catch (SQLException e) {
1517
                        } catch (SQLException e) {
1516
1518
1517
                                throw new BeanException("Error preparing statement", e);
1519
                                throw new BeanException("Error preparing statement", e);
1518
                        }
1520
                        }
1519
                }
1521
                }
1520
               
1522
               
1521
                /**
1523
                /**
1522
                 * Prepares a statement with paramValues to execute the query manually.
1524
                 * Prepares a statement with paramValues to execute the query manually.
1523
                 * @return A <code>PreparedStatement</code> using this session connection
1525
                 * @return A <code>PreparedStatement</code> using this session connection
1524
                 */
1526
                 */
1525
                public PreparedStatement prepare() {
1527
                public PreparedStatement prepare() {
1526
1528
1527
                        return prepare(paramValues.toArray());
1529
                        return prepare(paramValues.toArray());
1528
                }
1530
                }
1529
               
1531
               
1530
                /**
1532
                /**
1531
                 * Executes the query returning a <code>List</code> of beans declared in <b>FROM</b> clause.
1533
                 * Executes the query returning a <code>List</code> of beans declared in <b>FROM</b> clause.
1532
                 *
1534
                 *
1533
                 * @return A list containing all beans retrieved by <code>ResultSet</code>
1535
                 * @return A list containing all beans retrieved by <code>ResultSet</code>
1534
                 * @see Alias#populateAll(ResultSet, Object)
1536
                 * @see Alias#populateAll(ResultSet, Object)
1535
                 */
1537
                 */
1536
                public <T> List<T> executeQuery() {
1538
                public <T> List<T> executeQuery() {
1537
                       
1539
                       
1538
                        PreparedStatement ppst = null;
1540
                        PreparedStatement ppst = null;
1539
                       
1541
                       
1540
                        try {
1542
                        try {
1541
                                ppst = prepare();
1543
                                ppst = prepare();
1542
                               
1544
                               
1543
                                ResultSet rs = ppst.executeQuery();
1545
                                ResultSet rs = ppst.executeQuery();
1544
                               
1546
                               
1545
                                List<T> list = new ArrayList<T>();
1547
                                List<T> list = new ArrayList<T>();
1546
                                T bean;
1548
                                T bean;
1547
                               
1549
                               
1548
                                while (rs.next()) {
1550
                                while (rs.next()) {
1549
                                       
1551
                                       
1550
                                        bean = (T) aliasFrom.config.getBeanClass().newInstance();
1552
                                        bean = (T) aliasFrom.config.getBeanClass().newInstance();
1551
                                        aliasFrom.populateAll(rs, bean);
1553
                                        aliasFrom.populateAll(rs, bean);
1552
                                       
1554
                                       
1553
                                        for (Sentence s : sentences.values()) {
1555
                                        for (Sentence s : sentences.values()) {
1554
                                                session.injectValue(bean, s.getProperty(),
1556
                                                session.injectValue(bean, s.getProperty(),
1555
                                                                s.getValue(rs), s.getReturnType().getTypeClass());
1557
                                                                s.getValue(rs), s.getReturnType().getTypeClass());
1556
                                        }
1558
                                        }
1557
                                       
1559
                                       
1558
                                        list.add(bean);
1560
                                        list.add(bean);
1559
                                }
1561
                                }
1560
                               
1562
                               
1561
                                return list;
1563
                                return list;
1562
                               
1564
                               
1563
                        } catch (Exception e) {
1565
                        } catch (Exception e) {
1564
                               
1566
                               
1565
                                throw new BeanException("Unable to execute query from QueryBuilder\n"+
1567
                                throw new BeanException("Unable to execute query from QueryBuilder\n"+
1566
                                                e.getMessage(), e);
1568
                                                e.getMessage(), e);
1567
                        }finally {
1569
                        }finally {
1568
                               
1570
                               
1569
                                finish();
1571
                                finish();
1570
                               
1572
                               
1571
                                SQLUtils.close(ppst);
1573
                                SQLUtils.close(ppst);
1572
                        }
1574
                        }
1573
                }
1575
                }
1574
               
1576
               
1575
                /**
1577
                /**
1576
                 * Executes the query returning a single value according returnType of sentence in query.
1578
                 * Executes the query returning a single value according returnType of sentence in query.
1577
                 * @return The value returned by query
1579
                 * @return The value returned by query
1578
                 */
1580
                 */
1579
                public <T> T executeSentence() {
1581
                public <T> T executeSentence() {
1580
1582
1581
                        if (sentences.values().size() != 1)
1583
                        if (sentences.values().size() != 1)
1582
                                throw new BeanException("This query must have exactly one sentence to execute");
1584
                                throw new BeanException("This query must have exactly one sentence to execute");
1583
                       
1585
                       
1584
                        PreparedStatement ppst = null;
1586
                        PreparedStatement ppst = null;
1585
1587
1586
                        try {
1588
                        try {
1587
                                ppst = prepare();
1589
                                ppst = prepare();
1588
1590
1589
                                ResultSet rs = ppst.executeQuery();
1591
                                ResultSet rs = ppst.executeQuery();
1590
1592
1591
                                if (rs.next()) {
1593
                                if (rs.next()) {
1592
1594
1593
                                        if (!rs.isLast()) {
1595
                                        if (!rs.isLast()) {
1594
                                                throw new BeanException("The query returns more than one result");
1596
                                                throw new BeanException("The query returns more than one result");
1595
                                        }
1597
                                        }
1596
                                        Sentence s = sentences.values().iterator().next();
1598
                                        Sentence s = sentences.values().iterator().next();
1597
                                        return (T) s.getValue(rs);
1599
                                        return (T) s.getValue(rs);
1598
1600
1599
                                }
1601
                                }
1600
1602
1601
                                return null;
1603
                                return null;
1602
1604
1603
                        } catch (Exception e) {
1605
                        } catch (Exception e) {
1604
1606
1605
                                throw new BeanException("Unable to execute sentence from QueryBuilder\n"+
1607
                                throw new BeanException("Unable to execute sentence from QueryBuilder\n"+
1606
                                                e.getMessage(), e);
1608
                                                e.getMessage(), e);
1607
                        }finally {
1609
                        }finally {
1608
                               
1610
                               
1609
                                finish();
1611
                                finish();
1610
1612
1611
                                SQLUtils.close(ppst);
1613
                                SQLUtils.close(ppst);
1612
                        }
1614
                        }
1613
                }
1615
                }
1614
               
1616
               
1615
                @SuppressWarnings("unchecked")
1617
                @SuppressWarnings("unchecked")
1616
                public <T> T getValueFromResultSet(ResultSet rs, String name) throws SQLException {
1618
                public <T> T getValueFromResultSet(ResultSet rs, String name) throws SQLException {
1617
                       
1619
                       
1618
                        Sentence s = sentences.get(name);
1620
                        Sentence s = sentences.get(name);
1619
                       
1621
                       
1620
                        if (s == null)
1622
                        if (s == null)
1621
                                throw new BeanException("The sentence name '"+name+"' is not included in query");
1623
                                throw new BeanException("The sentence name '"+name+"' is not included in query");
1622
                       
1624
                       
1623
                        return (T) s.getValue(rs);
1625
                        return (T) s.getValue(rs);
1624
                }
1626
                }
1625
               
1627
               
1626
                /**
1628
                /**
1627
                 * Returns the SQL generated by QueryBuilder
1629
                 * Returns the SQL generated by QueryBuilder
1628
                 * @return The String SQL
1630
                 * @return The String SQL
1629
                 */
1631
                 */
1630
                public String getSQL() {
1632
                public String getSQL() {
1631
1633
1632
                        if (parenthesis != 0) {
1634
                        if (parenthesis != 0) {
1633
                                throw new BeanException("Invalid parenthesis");
1635
                                throw new BeanException("Invalid parenthesis");
1634
                        }
1636
                        }
1635
                       
1637
                       
1636
                        applyRegex();
1638
                        applyRegex();
1637
                       
1639
                       
1638
                        if (AnsiSQLBeanSession.DEBUG) {
1640
                        if (AnsiSQLBeanSession.DEBUG) {
1639
                                System.out.println("CUSTOM QUERY: "+sb.toString());
1641
                                System.out.println("CUSTOM QUERY: "+sb.toString());
1640
                        }
1642
                        }
1641
1643
1642
                        return sb.toString();
1644
                        return sb.toString();
1643
                }
1645
                }
1644
               
1646
               
1645
                public List<Object> getParamValues() {
1647
                public List<Object> getParamValues() {
1646
                        return paramValues;
1648
                        return paramValues;
1647
                }
1649
                }
1648
       
1650
       
1649
        }
1651
        }
1650
       
1652
       
1651
}
1653
}
1652
 
1654