1 package org.apache.torque.sql;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.torque.Column;
30 import org.apache.torque.ColumnImpl;
31 import org.apache.torque.Database;
32 import org.apache.torque.Torque;
33 import org.apache.torque.TorqueException;
34 import org.apache.torque.adapter.Adapter;
35 import org.apache.torque.criteria.Criteria;
36 import org.apache.torque.criteria.CriteriaInterface;
37 import org.apache.torque.criteria.Criterion;
38 import org.apache.torque.criteria.FromElement;
39 import org.apache.torque.criteria.PreparedStatementPart;
40 import org.apache.torque.criteria.SqlEnum;
41 import org.apache.torque.map.ColumnMap;
42 import org.apache.torque.map.DatabaseMap;
43 import org.apache.torque.map.MapHelper;
44 import org.apache.torque.map.TableMap;
45 import org.apache.torque.om.ObjectKey;
46 import org.apache.torque.sql.whereclausebuilder.CurrentDateTimePsPartBuilder;
47 import org.apache.torque.sql.whereclausebuilder.CustomBuilder;
48 import org.apache.torque.sql.whereclausebuilder.InBuilder;
49 import org.apache.torque.sql.whereclausebuilder.LikeBuilder;
50 import org.apache.torque.sql.whereclausebuilder.NullValueBuilder;
51 import org.apache.torque.sql.whereclausebuilder.StandardBuilder;
52 import org.apache.torque.sql.whereclausebuilder.VerbatimSqlConditionBuilder;
53 import org.apache.torque.sql.whereclausebuilder.WhereClausePsPartBuilder;
54 import org.apache.torque.util.UniqueColumnList;
55 import org.apache.torque.util.UniqueList;
56
57
58
59
60
61
62
63
64
65
66 @SuppressWarnings("deprecation")
67 public final class SqlBuilder
68 {
69
70 protected static final Log log = LogFactory.getLog(SqlBuilder.class);
71
72
73 public static final String[] FUNCTION_DELIMITERS
74 = {" ", ",", "(", ")", "<", ">"};
75
76
77 private static final char BACKSLASH = '\\';
78
79
80
81
82 private static List<WhereClausePsPartBuilder> whereClausePsPartBuilders
83 = new ArrayList<WhereClausePsPartBuilder>();
84
85 static
86 {
87 whereClausePsPartBuilders.add(new VerbatimSqlConditionBuilder());
88 whereClausePsPartBuilders.add(new CustomBuilder());
89 whereClausePsPartBuilders.add(new CurrentDateTimePsPartBuilder());
90 whereClausePsPartBuilders.add(new NullValueBuilder());
91 whereClausePsPartBuilders.add(new LikeBuilder());
92 whereClausePsPartBuilders.add(new InBuilder());
93 whereClausePsPartBuilders.add(new StandardBuilder());
94 }
95
96
97
98
99
100
101
102 private SqlBuilder()
103 {
104
105 }
106
107
108
109
110
111
112
113
114 public static List<WhereClausePsPartBuilder> getWhereClausePsPartBuilders()
115 {
116 return whereClausePsPartBuilders;
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130 @Deprecated
131 public static Query buildQuery(final org.apache.torque.util.Criteria crit)
132 throws TorqueException
133 {
134 Query sqlStatement = new Query();
135
136 JoinBuilder.processJoins(crit, sqlStatement);
137 processModifiers(crit, sqlStatement);
138 processSelectColumns(crit, sqlStatement);
139 processAsColumns(crit, sqlStatement);
140 processCriterions(crit, sqlStatement);
141 processGroupBy(crit, sqlStatement);
142 processHaving(crit, sqlStatement);
143 processOrderBy(crit, sqlStatement);
144 processLimits(crit, sqlStatement);
145
146 return sqlStatement;
147 }
148
149
150
151
152
153
154
155
156
157
158 public static Query buildQuery(final Criteria crit)
159 throws TorqueException
160 {
161 Query sqlStatement = new Query();
162
163 JoinBuilder.processJoins(crit, sqlStatement);
164 processModifiers(crit, sqlStatement);
165 processSelectColumns(crit, sqlStatement);
166 processAsColumns(crit, sqlStatement);
167 processCriterions(crit, sqlStatement);
168 processGroupBy(crit, sqlStatement);
169 processHaving(crit, sqlStatement);
170 processOrderBy(crit, sqlStatement);
171 processLimits(crit, sqlStatement);
172 processFromElements(crit, sqlStatement);
173 sqlStatement.setFetchSize(crit.getFetchSize());
174
175 return sqlStatement;
176 }
177
178
179
180
181
182
183
184
185
186 private static void processSelectColumns(
187 final CriteriaInterface<?> criteria,
188 final Query query)
189 throws TorqueException
190 {
191 UniqueList<String> selectClause = query.getSelectClause();
192 UniqueColumnList selectColumns = criteria.getSelectColumns();
193
194 for (Column column : selectColumns)
195 {
196 String sqlExpression = column.getSqlExpression();
197 Column resolvedAlias = criteria.getAsColumns().get(sqlExpression);
198 if (resolvedAlias != null)
199 {
200
201 continue;
202 }
203 selectClause.add(sqlExpression);
204 addTableToFromClause(
205 column,
206 criteria,
207 query);
208 }
209 }
210
211
212
213
214
215
216
217
218
219
220
221
222 private static void processAsColumns(
223 final CriteriaInterface<?> criteria,
224 final Query query)
225 throws TorqueException
226 {
227 UniqueList<String> querySelectClause = query.getSelectClause();
228 Map<String, Column> criteriaAsColumns = criteria.getAsColumns();
229
230 for (Map.Entry<String, Column> entry : criteriaAsColumns.entrySet())
231 {
232 Column column = entry.getValue();
233 querySelectClause.add(
234 column.getSqlExpression()
235 + SqlEnum.AS
236 + entry.getKey());
237 addTableToFromClause(
238 column,
239 criteria,
240 query);
241 }
242 }
243
244
245
246
247
248
249
250
251
252 private static void processModifiers(
253 final CriteriaInterface<?> criteria,
254 final Query query)
255 {
256 UniqueList<String> selectModifiers = query.getSelectModifiers();
257 UniqueList<String> modifiers = criteria.getSelectModifiers();
258 for (String modifier : modifiers)
259 {
260 selectModifiers.add(modifier);
261 }
262 }
263
264
265
266
267
268
269
270
271
272 private static void processCriterions(
273 final Criteria criteria,
274 final Query query)
275 throws TorqueException
276 {
277 if (criteria.getTopLevelCriterion() == null)
278 {
279 return;
280 }
281 StringBuilder where = new StringBuilder();
282 appendCriterion(
283 criteria.getTopLevelCriterion(),
284 criteria,
285 where,
286 query);
287 query.getWhereClause().add(where.toString());
288 }
289
290 static void appendCriterion(
291 Criterion criterion,
292 CriteriaInterface<?> criteria,
293 StringBuilder where,
294 Query query)
295 throws TorqueException
296 {
297 if (criterion.isComposite())
298 {
299 where.append('(');
300 boolean firstPart = true;
301 for (Criterion part : criterion.getParts())
302 {
303 if (!firstPart)
304 {
305 where.append(criterion.getConjunction());
306 }
307 appendCriterion(
308 part,
309 criteria,
310 where,
311 query);
312 firstPart = false;
313 }
314 where.append(')');
315 return;
316 }
317
318
319
320
321 addTableToFromClause(
322 criterion.getLValue(),
323 criteria,
324 query);
325 addTableToFromClause(
326 criterion.getRValue(),
327 criteria,
328 query);
329
330 PreparedStatementPart whereClausePartOutput
331 = processCriterion(criterion, criteria);
332
333 where.append(whereClausePartOutput.getSql());
334 query.getWhereClausePreparedStatementReplacements().addAll(
335 whereClausePartOutput.getPreparedStatementReplacements());
336 }
337
338 static PreparedStatementPart processCriterion(
339 Criterion criterion,
340 CriteriaInterface<?> criteria)
341 throws TorqueException
342 {
343 final String dbName = criteria.getDbName();
344 final Database database = Torque.getDatabase(dbName);
345 final Adapter adapter = Torque.getAdapter(dbName);
346
347 boolean ignoreCase
348 = isIgnoreCase(criterion, criteria, database);
349
350 WhereClauseExpression whereClausePartInput
351 = new WhereClauseExpression(
352 criterion.getLValue(),
353 criterion.getComparison(),
354 criterion.getRValue(),
355 criterion.getSql(),
356 criterion.getPreparedStatementReplacements());
357 PreparedStatementPart whereClausePartOutput = null;
358 for (WhereClausePsPartBuilder builder : whereClausePsPartBuilders)
359 {
360 if (builder.isApplicable(whereClausePartInput, adapter))
361 {
362 whereClausePartOutput = builder.buildPs(
363 whereClausePartInput,
364 ignoreCase,
365 adapter);
366 break;
367 }
368 }
369
370 if (whereClausePartOutput == null)
371 {
372
373
374 throw new RuntimeException("No handler found for whereClausePart "
375 + whereClausePartInput);
376 }
377 return whereClausePartOutput;
378 }
379
380
381
382
383
384
385
386
387
388
389
390 @Deprecated
391 private static void processCriterions(
392 final org.apache.torque.util.Criteria criteria,
393 final Query query)
394 throws TorqueException
395 {
396 UniqueList<String> whereClause = query.getWhereClause();
397
398 for (org.apache.torque.util.Criteria.Criterion criterion
399 : criteria.values())
400 {
401 StringBuilder sb = new StringBuilder();
402 appendCriterionToPs(
403 criterion,
404 criteria,
405 sb,
406 query);
407 whereClause.add(sb.toString());
408 }
409 }
410
411
412
413
414
415 @Deprecated
416 private static void appendCriterionToPs(
417 org.apache.torque.util.Criteria.Criterion criterion,
418 org.apache.torque.util.Criteria criteria,
419 StringBuilder sb,
420 Query query)
421 throws TorqueException
422 {
423 Column column = criterion.getColumn();
424
425
426
427
428
429 addTableToFromClause(
430 column,
431 criteria,
432 query);
433
434 boolean ignoreCase
435 = criteria.isIgnoreCase() || criterion.isIgnoreCase();
436 final String dbName = criteria.getDbName();
437 final Adapter adapter = Torque.getAdapter(dbName);
438 final Database database = Torque.getDatabase(dbName);
439 {
440 Column databaseColumn = resolveAliasAndAsColumnAndSchema(
441 column,
442 criteria);
443 ColumnMap columnMap = null;
444 {
445 DatabaseMap databaseMap = database.getDatabaseMap();
446 TableMap tableMap = databaseMap.getTable(
447 databaseColumn.getTableName());
448 if (tableMap != null)
449 {
450 columnMap = tableMap.getColumn(
451 databaseColumn.getColumnName());
452 }
453 }
454 if (columnMap != null)
455 {
456
457
458 ignoreCase = ignoreCase
459 && columnMap.getType() instanceof String;
460 }
461 }
462
463 for (int j = 0; j < criterion.getClauses().size(); j++)
464 {
465 sb.append('(');
466 }
467 String columnName = criterion.getColumn().getSqlExpression();
468 WhereClauseExpression whereClausePartInput
469 = new WhereClauseExpression(
470 columnName,
471 criterion.getComparison(),
472 criterion.getValue(),
473 null,
474 null);
475 PreparedStatementPart whereClausePartOutput
476 = buildPs(
477 whereClausePartInput,
478 ignoreCase,
479 adapter);
480 sb.append(whereClausePartOutput.getSql());
481 query.getWhereClausePreparedStatementReplacements().addAll(
482 whereClausePartOutput.getPreparedStatementReplacements());
483
484 for (int i = 0; i < criterion.getClauses().size(); i++)
485 {
486 sb.append(criterion.getConjunctions().get(i));
487 org.apache.torque.util.Criteria.Criterion clause
488 = criterion.getClauses().get(i);
489 appendCriterionToPs(
490 clause,
491 criteria,
492 sb,
493 query);
494 sb.append(')');
495 }
496 }
497
498
499
500
501
502
503 private static void processOrderBy(
504 final CriteriaInterface<?> crit,
505 final Query query)
506 throws TorqueException
507 {
508 UniqueList<String> orderByClause = query.getOrderByClause();
509 UniqueList<String> selectClause = query.getSelectClause();
510
511 UniqueList<OrderBy> orderByList = crit.getOrderByColumns();
512
513
514
515 for (OrderBy orderBy : orderByList)
516 {
517 Column column = orderBy.getColumn();
518 ColumnMap columnMap = MapHelper.getColumnMap(column, crit);
519 String sqlExpression = column.getSqlExpression();
520
521
522
523
524
525
526
527 if (columnMap == null
528 || (columnMap.getType() instanceof String
529 && sqlExpression.indexOf('(') == -1))
530 {
531 if (orderBy.isIgnoreCase() || crit.isIgnoreCase())
532 {
533 final Adapter adapter = Torque.getAdapter(crit.getDbName());
534 orderByClause.add(
535 adapter.ignoreCaseInOrderBy(sqlExpression)
536 + ' ' + orderBy.getOrder());
537 selectClause.add(
538 adapter.ignoreCaseInOrderBy(sqlExpression));
539 }
540 else
541 {
542 orderByClause.add(sqlExpression + ' ' + orderBy.getOrder());
543 if (crit.getAsColumns().get(sqlExpression) == null)
544 {
545 selectClause.add(sqlExpression);
546 }
547 }
548 }
549 else
550 {
551 orderByClause.add(sqlExpression + ' ' + orderBy.getOrder());
552 if (crit.getAsColumns().get(sqlExpression) == null)
553 {
554 selectClause.add(sqlExpression);
555 }
556 }
557 addTableToFromClause(
558 column,
559 crit,
560 query);
561 }
562 }
563
564
565
566
567
568
569
570
571
572 private static void processGroupBy(
573 final CriteriaInterface<?> criteria,
574 final Query query)
575 throws TorqueException
576 {
577 UniqueList<String> groupByClause = query.getGroupByClause();
578 UniqueList<String> selectClause = query.getSelectClause();
579 UniqueColumnList groupBy = criteria.getGroupByColumns();
580
581 for (Column groupByColumn : groupBy)
582 {
583 Column column = criteria.getAsColumns().get(
584 groupByColumn.getSqlExpression());
585
586 if (column == null)
587 {
588 column = groupByColumn;
589 }
590
591 groupByClause.add(column.getSqlExpression());
592 selectClause.add(column.getSqlExpression());
593 addTableToFromClause(column, criteria, query);
594 }
595 }
596
597
598
599
600
601
602
603 private static void processHaving(
604 final Criteria crit,
605 final Query query)
606 throws TorqueException
607 {
608 Criterion having = crit.getHaving();
609 if (having != null)
610 {
611 query.setHaving(having.toString());
612 }
613 }
614
615
616
617
618
619
620
621 private static void processHaving(
622 final org.apache.torque.util.Criteria crit,
623 final Query query)
624 throws TorqueException
625 {
626 org.apache.torque.util.Criteria.Criterion having = crit.getHaving();
627 if (having != null)
628 {
629 query.setHaving(having.toString());
630 }
631 }
632
633
634
635
636
637
638
639
640 private static void processLimits(
641 final CriteriaInterface<?> crit,
642 final Query query)
643 throws TorqueException
644 {
645 int limit = crit.getLimit();
646 long offset = crit.getOffset();
647
648 if (offset > 0 || limit >= 0)
649 {
650 Adapter adapter = Torque.getAdapter(crit.getDbName());
651 adapter.generateLimits(query, offset, limit);
652 }
653 }
654
655
656
657
658
659
660
661
662 private static void processFromElements(
663 final Criteria criteria,
664 final Query query)
665 {
666 if (criteria.getFromElements().isEmpty())
667 {
668 log.trace("criteria's from Elements is empty,"
669 + " using automatically calculated from clause");
670 return;
671 }
672 query.getFromClause().clear();
673 query.getFromClause().addAll(criteria.getFromElements());
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693 static PreparedStatementPart getExpressionForFromClause(
694 final Object toAddToFromClause,
695 final CriteriaInterface<?> criteria)
696 throws TorqueException
697 {
698 if (!(toAddToFromClause instanceof Column))
699 {
700
701 return new PreparedStatementPart("?", toAddToFromClause);
702 }
703 Column column = (Column) toAddToFromClause;
704 Column resolvedColumn
705 = resolveAliasAndAsColumnAndSchema(column, criteria);
706 String fullTableName
707 = resolvedColumn.getFullTableName();
708
709 if (!StringUtils.equals(
710 resolvedColumn.getTableName(),
711 column.getTableName()))
712 {
713
714
715 PreparedStatementPart result = new PreparedStatementPart();
716 result.getSql()
717 .append(fullTableName)
718 .append(" ")
719 .append(column.getTableName());
720 return result;
721 }
722 Object resolvedAlias = criteria.getAliases().get(
723 resolvedColumn.getTableName());
724 if (resolvedAlias != null)
725 {
726 if (resolvedAlias instanceof Criteria)
727 {
728 Criteria subquery = (Criteria) resolvedAlias;
729 Query renderedSubquery = SqlBuilder.buildQuery(subquery);
730 PreparedStatementPart result = new PreparedStatementPart();
731 result.getSql().append("(")
732 .append(renderedSubquery.toString())
733 .append(") ")
734 .append(resolvedColumn.getTableName());
735 result.getPreparedStatementReplacements().addAll(
736 renderedSubquery.getPreparedStatementReplacements());
737 return result;
738 }
739 else
740 {
741 throw new TorqueException("Table name "
742 + resolvedColumn.getTableName()
743 + " resolved to an unhandleable class "
744 + resolvedAlias.getClass().getName());
745 }
746 }
747
748 return new PreparedStatementPart(fullTableName);
749 }
750
751
752
753
754
755
756
757
758
759
760
761
762
763 public static String getFullTableName(
764 final String table,
765 final String dbName)
766 throws TorqueException
767 {
768 if (table == null)
769 {
770 return table;
771 }
772
773 int dotIndex = table.indexOf(".");
774 if (dotIndex == -1)
775 {
776 String targetDBName = (dbName == null)
777 ? Torque.getDefaultDB()
778 : dbName;
779
780 String targetSchema = Torque.getSchema(targetDBName);
781
782
783
784 if (StringUtils.isNotEmpty(targetSchema))
785 {
786 return new StringBuffer()
787 .append(targetSchema)
788 .append(".")
789 .append(table)
790 .toString();
791 }
792 }
793
794 return table;
795 }
796
797
798
799
800
801
802
803
804
805 public static String getUnqualifiedName(
806 final String name,
807 final String dbName)
808 throws TorqueException
809 {
810 if (name == null)
811 {
812 return null;
813 }
814
815 int dotIndex = name.lastIndexOf(".");
816 if (dotIndex == -1)
817 {
818 return name;
819 }
820
821 return name.substring(dotIndex + 1);
822 }
823
824
825
826
827
828
829
830
831
832
833
834 public static String guessFullTableFromCriteria(Criteria criteria)
835 throws TorqueException
836 {
837 org.apache.torque.criteria.Criterion criterion
838 = criteria.getTopLevelCriterion();
839 if (criterion == null)
840 {
841 throw new TorqueException("Could not determine table name "
842 + " as criteria contains no criterion");
843 }
844 while (criterion.isComposite())
845 {
846 criterion = criterion.getParts().iterator().next();
847 }
848 String tableName = null;
849
850 Object lValue = criterion.getLValue();
851 if (lValue instanceof Column)
852 {
853 Column column = (Column) lValue;
854 tableName = column.getFullTableName();
855 }
856 if (tableName == null)
857 {
858 throw new TorqueException("Could not determine table name "
859 + " as first criterion contains no table name");
860 }
861 return tableName;
862 }
863
864
865
866
867
868
869
870
871
872
873
874 public static TableMap getTableMap(String tableName, String dbName)
875 throws TorqueException
876 {
877
878 if (dbName == null)
879 {
880 dbName = Torque.getDefaultDB();
881 }
882 DatabaseMap databaseMap = Torque.getDatabaseMap(dbName);
883 if (databaseMap == null)
884 {
885 throw new TorqueException("Could not find database map"
886 + " for database "
887 + dbName);
888 }
889 String unqualifiedTableName = getUnqualifiedName(tableName, dbName);
890 TableMap result = databaseMap.getTable(unqualifiedTableName);
891 if (result == null)
892 {
893 throw new TorqueException("Could not find table "
894 + tableName
895 + " in database map of database "
896 + dbName);
897 }
898 return result;
899 }
900
901
902
903
904
905
906
907
908
909
910
911 static Column resolveAliasAndAsColumnAndSchema(
912 final Column columnToResolve,
913 final CriteriaInterface<?> criteria)
914 throws TorqueException
915 {
916 String columnNameToResolve = columnToResolve.getColumnName();
917 Column resolvedColumn = criteria.getAsColumns().get(columnNameToResolve);
918 boolean sqlExpressionModified = false;
919 if (resolvedColumn == null)
920 {
921 resolvedColumn = columnToResolve;
922 }
923 else
924 {
925 sqlExpressionModified = true;
926 }
927 String tableNameToResolve = resolvedColumn.getTableName();
928 Object resolvedAlias = criteria.getAliases().get(tableNameToResolve);
929 String resolvedTableName;
930 if (resolvedAlias == null || !(resolvedAlias instanceof String))
931 {
932 resolvedTableName = tableNameToResolve;
933 }
934 else
935 {
936 resolvedTableName = (String) resolvedAlias;
937 sqlExpressionModified = true;
938 }
939 String resolvedSchemaName = resolvedColumn.getSchemaName();
940 if (resolvedSchemaName == null)
941 {
942 final String dbName = criteria.getDbName();
943 final Database database = Torque.getDatabase(dbName);
944 resolvedSchemaName = database.getSchema();
945 }
946 if (sqlExpressionModified)
947 {
948 return new ColumnImpl(
949 resolvedSchemaName,
950 resolvedTableName,
951 resolvedColumn.getColumnName());
952 }
953 else
954 {
955 return new ColumnImpl(
956 resolvedSchemaName,
957 resolvedTableName,
958 resolvedColumn.getColumnName(),
959 resolvedColumn.getSqlExpression());
960 }
961 }
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978 static boolean fromClauseContainsExpression(
979 final UniqueList<FromElement> fromClause,
980 final PreparedStatementPart fromExpression)
981 {
982 if (fromExpression == null || fromExpression.getSql().length() == 0)
983 {
984 return false;
985 }
986 String fromExpressionSql = fromExpression.getSql().toString();
987 for (FromElement fromElement : fromClause)
988 {
989 if (fromExpressionSql.equals(fromElement.getFromExpression()))
990 {
991 return true;
992 }
993 }
994 return false;
995 }
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008 static void addTableToFromClause(
1009 final Object possibleColumn,
1010 final CriteriaInterface<?> criteria,
1011 Query query)
1012 throws TorqueException
1013 {
1014 if (possibleColumn == null)
1015 {
1016 return;
1017 }
1018 if (!(possibleColumn instanceof Column))
1019 {
1020 return;
1021 }
1022 Column column = (Column) possibleColumn;
1023 if (column.getTableName() == null)
1024 {
1025 return;
1026 }
1027 PreparedStatementPart fromClauseExpression = getExpressionForFromClause(
1028 column,
1029 criteria);
1030
1031 UniqueList<FromElement> queryFromClause = query.getFromClause();
1032
1033
1034
1035 if (!fromClauseContainsExpression(
1036 queryFromClause,
1037 fromClauseExpression))
1038 {
1039 FromElement fromElement = new FromElement(
1040 fromClauseExpression.getSql().toString(),
1041 null,
1042 null,
1043 fromClauseExpression.getPreparedStatementReplacements());
1044 queryFromClause.add(fromElement);
1045 }
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 static boolean isIgnoreCase(
1062 Criterion criterion,
1063 CriteriaInterface<?> criteria,
1064 Database database)
1065 throws TorqueException
1066 {
1067 boolean ignoreCase
1068 = criteria.isIgnoreCase() || criterion.isIgnoreCase();
1069 ignoreCase = ignoreCase
1070 && ignoreCaseApplicable(
1071 criterion.getLValue(),
1072 criteria,
1073 database)
1074 && ignoreCaseApplicable(
1075 criterion.getRValue(),
1076 criteria,
1077 database);
1078 return ignoreCase;
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 private static boolean ignoreCaseApplicable(
1096 Object value,
1097 CriteriaInterface<?> criteria,
1098 Database database)
1099 throws TorqueException
1100 {
1101 if (value == null)
1102 {
1103 return true;
1104 }
1105 if (!(value instanceof Column))
1106 {
1107 if (value instanceof String
1108 || value instanceof Iterable
1109 || value.getClass().isArray())
1110 {
1111 return true;
1112 }
1113 return false;
1114 }
1115 Column column = (Column) value;
1116 Column databaseColumn = resolveAliasAndAsColumnAndSchema(
1117 column,
1118 criteria);
1119 ColumnMap columnMap = null;
1120 {
1121 DatabaseMap databaseMap = database.getDatabaseMap();
1122 TableMap tableMap = databaseMap.getTable(
1123 databaseColumn.getTableName());
1124 if (tableMap != null)
1125 {
1126 columnMap = tableMap.getColumn(
1127 databaseColumn.getColumnName());
1128 }
1129 }
1130 if (columnMap == null)
1131 {
1132 return true;
1133 }
1134
1135
1136 return columnMap.getType() instanceof String;
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152 @Deprecated
1153 private static PreparedStatementPart buildPs(
1154 WhereClauseExpression whereClausePart,
1155 boolean ignoreCase,
1156 Adapter adapter)
1157 throws TorqueException
1158 {
1159 PreparedStatementPart result = new PreparedStatementPart();
1160
1161
1162 if (SqlEnum.CUSTOM == whereClausePart.getOperator())
1163 {
1164 result.getSql().append(whereClausePart.getRValue());
1165 return result;
1166 }
1167
1168
1169 if (whereClausePart.getRValue() instanceof SqlEnum)
1170 {
1171 result.getSql().append(whereClausePart.getLValue())
1172 .append(whereClausePart.getOperator())
1173 .append(whereClausePart.getRValue());
1174 return result;
1175 }
1176
1177
1178 if (whereClausePart.getRValue() instanceof ObjectKey)
1179 {
1180 whereClausePart.setRValue(
1181 ((ObjectKey) whereClausePart.getRValue()).getValue());
1182 }
1183
1184
1185
1186
1187
1188 if (whereClausePart.getRValue() == null)
1189 {
1190 if (whereClausePart.getOperator().equals(SqlEnum.EQUAL))
1191 {
1192 result.getSql().append(whereClausePart.getLValue())
1193 .append(SqlEnum.ISNULL);
1194 return result;
1195 }
1196 if (whereClausePart.getOperator().equals(SqlEnum.NOT_EQUAL)
1197 || whereClausePart.getOperator().equals(
1198 SqlEnum.ALT_NOT_EQUAL))
1199 {
1200 result.getSql().append(whereClausePart.getLValue())
1201 .append(SqlEnum.ISNOTNULL);
1202 return result;
1203 }
1204 }
1205
1206
1207 if (whereClausePart.getOperator().equals(SqlEnum.ISNULL)
1208 || whereClausePart.getOperator().equals(SqlEnum.ISNOTNULL))
1209 {
1210 result.getSql().append(whereClausePart.getLValue())
1211 .append(whereClausePart.getOperator());
1212 return result;
1213 }
1214
1215
1216 if (whereClausePart.getRValue() instanceof Criteria)
1217 {
1218 Query subquery = SqlBuilder.buildQuery(
1219 (Criteria) whereClausePart.getRValue());
1220 result.getPreparedStatementReplacements().addAll(
1221 subquery.getPreparedStatementReplacements());
1222 result.getSql().append(whereClausePart.getLValue())
1223 .append(whereClausePart.getOperator())
1224 .append("(").append(subquery.toString()).append(")");
1225 return result;
1226 }
1227 if (whereClausePart.getRValue()
1228 instanceof org.apache.torque.util.Criteria)
1229 {
1230 Query subquery = SqlBuilder.buildQuery(
1231 (org.apache.torque.util.Criteria)
1232 whereClausePart.getRValue());
1233 result.getPreparedStatementReplacements().addAll(
1234 subquery.getPreparedStatementReplacements());
1235 result.getSql().append(whereClausePart.getLValue())
1236 .append(whereClausePart.getOperator())
1237 .append("(").append(subquery.toString()).append(")");
1238 return result;
1239 }
1240
1241
1242 if (whereClausePart.getOperator().equals(Criteria.LIKE)
1243 || whereClausePart.getOperator().equals(Criteria.NOT_LIKE)
1244 || whereClausePart.getOperator().equals(Criteria.ILIKE)
1245 || whereClausePart.getOperator().equals(Criteria.NOT_ILIKE))
1246 {
1247 return buildPsLike(whereClausePart, ignoreCase, adapter);
1248 }
1249
1250
1251 if (whereClausePart.getOperator().equals(Criteria.IN)
1252 || whereClausePart.getOperator().equals(Criteria.NOT_IN))
1253 {
1254 return buildPsIn(whereClausePart, ignoreCase, adapter);
1255 }
1256
1257
1258 result.getPreparedStatementReplacements().add(
1259 whereClausePart.getRValue());
1260 if (ignoreCase
1261 && whereClausePart.getRValue() instanceof String)
1262 {
1263 result.getSql().append(
1264 adapter.ignoreCase((String) whereClausePart.getLValue()))
1265 .append(whereClausePart.getOperator())
1266 .append(adapter.ignoreCase("?"));
1267 }
1268 else
1269 {
1270 result.getSql().append(whereClausePart.getLValue())
1271 .append(whereClausePart.getOperator())
1272 .append("?");
1273 }
1274 return result;
1275 }
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 @Deprecated
1302 static PreparedStatementPart buildPsLike(
1303 WhereClauseExpression whereClausePart,
1304 boolean ignoreCase,
1305 Adapter adapter)
1306 throws TorqueException
1307 {
1308 if (!(whereClausePart.getRValue() instanceof String))
1309 {
1310 throw new TorqueException(
1311 "rValue must be a String for the operator "
1312 + whereClausePart.getOperator());
1313 }
1314 String value = (String) whereClausePart.getRValue();
1315
1316
1317
1318
1319
1320
1321
1322
1323 int position = 0;
1324 StringBuffer sb = new StringBuffer();
1325 boolean replaceWithEquals = true;
1326 while (position < value.length())
1327 {
1328 char checkWildcard = value.charAt(position);
1329
1330 switch (checkWildcard)
1331 {
1332 case BACKSLASH:
1333 if (position + 1 >= value.length())
1334 {
1335
1336 break;
1337 }
1338 position++;
1339 char escapedChar = value.charAt(position);
1340 if (escapedChar != '*' && escapedChar != '?')
1341 {
1342 sb.append(checkWildcard);
1343 }
1344
1345 checkWildcard = escapedChar;
1346 break;
1347 case '%':
1348 case '_':
1349 replaceWithEquals = false;
1350 break;
1351 case '*':
1352 replaceWithEquals = false;
1353 checkWildcard = '%';
1354 break;
1355 case '?':
1356 replaceWithEquals = false;
1357 checkWildcard = '_';
1358 break;
1359 default:
1360 break;
1361 }
1362
1363 sb.append(checkWildcard);
1364 position++;
1365 }
1366 value = sb.toString();
1367
1368 if (ignoreCase)
1369 {
1370 if (adapter.useIlike() && !replaceWithEquals)
1371 {
1372 if (SqlEnum.LIKE.equals(whereClausePart.getOperator()))
1373 {
1374 whereClausePart.setOperator(SqlEnum.ILIKE);
1375 }
1376 else if (SqlEnum.NOT_LIKE.equals(whereClausePart.getOperator()))
1377 {
1378 whereClausePart.setOperator(SqlEnum.NOT_ILIKE);
1379 }
1380 }
1381 else
1382 {
1383
1384
1385
1386 whereClausePart.setLValue(
1387 adapter.ignoreCase((String) whereClausePart.getLValue()));
1388 }
1389 }
1390
1391 PreparedStatementPart result = new PreparedStatementPart();
1392 result.getSql().append(whereClausePart.getLValue());
1393
1394 if (replaceWithEquals)
1395 {
1396 if (whereClausePart.getOperator().equals(SqlEnum.NOT_LIKE)
1397 || whereClausePart.getOperator().equals(SqlEnum.NOT_ILIKE))
1398 {
1399 result.getSql().append(SqlEnum.NOT_EQUAL);
1400 }
1401 else
1402 {
1403 result.getSql().append(SqlEnum.EQUAL);
1404 }
1405
1406
1407 position = 0;
1408 sb = new StringBuffer();
1409 while (position < value.length())
1410 {
1411 char checkWildcard = value.charAt(position);
1412
1413 if (checkWildcard == BACKSLASH
1414 && position + 1 < value.length())
1415 {
1416 position++;
1417
1418 checkWildcard = value.charAt(position);
1419 }
1420 sb.append(checkWildcard);
1421 position++;
1422 }
1423 value = sb.toString();
1424 }
1425 else
1426 {
1427 result.getSql().append(whereClausePart.getOperator());
1428 }
1429
1430 String rValueSql = "?";
1431
1432 if (ignoreCase && (!(adapter.useIlike()) || replaceWithEquals))
1433 {
1434 rValueSql = adapter.ignoreCase(rValueSql);
1435 }
1436
1437 if (!replaceWithEquals && adapter.useEscapeClauseForLike())
1438 {
1439 rValueSql = rValueSql + SqlEnum.ESCAPE + "'\\'";
1440 }
1441
1442 result.getPreparedStatementReplacements().add(value);
1443 result.getSql().append(rValueSql);
1444 return result;
1445 }
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464 @Deprecated
1465 static PreparedStatementPart buildPsIn(
1466 WhereClauseExpression whereClausePart,
1467 boolean ignoreCase,
1468 Adapter adapter)
1469 {
1470 PreparedStatementPart result = new PreparedStatementPart();
1471
1472 boolean ignoreCaseApplied = false;
1473 List<String> inClause = new ArrayList<String>();
1474 boolean nullContained = false;
1475 if (whereClausePart.getRValue() instanceof Iterable)
1476 {
1477 for (Object listValue : (Iterable<?>) whereClausePart.getRValue())
1478 {
1479 if (listValue == null)
1480 {
1481 nullContained = true;
1482 continue;
1483 }
1484 result.getPreparedStatementReplacements().add(listValue);
1485 if (ignoreCase && listValue instanceof String)
1486 {
1487 inClause.add(adapter.ignoreCase("?"));
1488 ignoreCaseApplied = true;
1489 }
1490 else
1491 {
1492 inClause.add("?");
1493 }
1494 }
1495 }
1496 else if (whereClausePart.getRValue().getClass().isArray())
1497 {
1498 for (Object arrayValue : (Object[]) whereClausePart.getRValue())
1499 {
1500 if (arrayValue == null)
1501 {
1502 nullContained = true;
1503 continue;
1504 }
1505 result.getPreparedStatementReplacements().add(arrayValue);
1506 if (ignoreCase && arrayValue instanceof String)
1507 {
1508 inClause.add(adapter.ignoreCase("?"));
1509 ignoreCaseApplied = true;
1510 }
1511 else
1512 {
1513 inClause.add("?");
1514 }
1515 }
1516 }
1517 else
1518 {
1519 throw new IllegalArgumentException(
1520 "Unknown rValue type "
1521 + whereClausePart.getRValue().getClass().getName()
1522 + ". rValue must be an instance of "
1523 + " Iterable or Array");
1524 }
1525
1526 if (nullContained)
1527 {
1528 result.getSql().append('(');
1529 }
1530
1531 if (ignoreCaseApplied)
1532 {
1533 result.getSql().append(
1534 adapter.ignoreCase((String) whereClausePart.getLValue()));
1535 }
1536 else
1537 {
1538 result.getSql().append(whereClausePart.getLValue());
1539 }
1540
1541 result.getSql().append(whereClausePart.getOperator())
1542 .append('(')
1543 .append(StringUtils.join(inClause.iterator(), ","))
1544 .append(')');
1545 if (nullContained)
1546 {
1547 if (whereClausePart.getOperator() == SqlEnum.IN)
1548 {
1549 result.getSql().append(Criterion.OR)
1550 .append(whereClausePart.getLValue()).append(SqlEnum.ISNULL);
1551 }
1552 else if (whereClausePart.getOperator() == SqlEnum.NOT_IN)
1553 {
1554 result.getSql().append(Criterion.AND)
1555 .append(whereClausePart.getLValue()).append(
1556 SqlEnum.ISNOTNULL);
1557 }
1558 result.getSql().append(')');
1559 }
1560 return result;
1561 }
1562 }