001
014
015 package com.liferay.util.dao.orm;
016
017 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
018 import com.liferay.portal.kernel.dao.orm.QueryDefinition;
019 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
020 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.util.ArrayUtil;
024 import com.liferay.portal.kernel.util.CharPool;
025 import com.liferay.portal.kernel.util.GetterUtil;
026 import com.liferay.portal.kernel.util.OrderByComparator;
027 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
028 import com.liferay.portal.kernel.util.PropsKeys;
029 import com.liferay.portal.kernel.util.PropsUtil;
030 import com.liferay.portal.kernel.util.StreamUtil;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.workflow.WorkflowConstants;
036 import com.liferay.portal.kernel.xml.Document;
037 import com.liferay.portal.kernel.xml.Element;
038 import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
039 import com.liferay.portal.util.PortalUtil;
040
041 import java.io.IOException;
042 import java.io.InputStream;
043
044 import java.sql.Connection;
045 import java.sql.DatabaseMetaData;
046 import java.sql.SQLException;
047
048 import java.util.ArrayList;
049 import java.util.HashMap;
050 import java.util.List;
051 import java.util.Map;
052 import java.util.Properties;
053
054
059 public class CustomSQL {
060
061 public static final String DB2_FUNCTION_IS_NOT_NULL =
062 "CAST(? AS VARCHAR(32672)) IS NOT NULL";
063
064 public static final String DB2_FUNCTION_IS_NULL =
065 "CAST(? AS VARCHAR(32672)) IS NULL";
066
067 public static final String INFORMIX_FUNCTION_IS_NOT_NULL =
068 "NOT lportal.isnull(?)";
069
070 public static final String INFORMIX_FUNCTION_IS_NULL = "lportal.isnull(?)";
071
072 public static final String MYSQL_FUNCTION_IS_NOT_NULL =
073 "IFNULL(?, '1') = '0'";
074
075 public static final String MYSQL_FUNCTION_IS_NULL = "IFNULL(?, '1') = '1'";
076
077 public static final String SYBASE_FUNCTION_IS_NOT_NULL =
078 "CONVERT(VARCHAR,?) IS NOT NULL";
079
080 public static final String SYBASE_FUNCTION_IS_NULL =
081 "CONVERT(VARCHAR,?) IS NULL";
082
083 public CustomSQL() throws SQLException {
084 reloadCustomSQL();
085 }
086
087 public String appendCriteria(String sql, String criteria) {
088 if (Validator.isNull(criteria)) {
089 return sql;
090 }
091
092 if (!criteria.startsWith(StringPool.SPACE)) {
093 criteria = StringPool.SPACE.concat(criteria);
094 }
095
096 if (!criteria.endsWith(StringPool.SPACE)) {
097 criteria = criteria.concat(StringPool.SPACE);
098 }
099
100 int pos = sql.indexOf(_GROUP_BY_CLAUSE);
101
102 if (pos != -1) {
103 return sql.substring(0, pos + 1).concat(criteria).concat(
104 sql.substring(pos + 1));
105 }
106
107 pos = sql.indexOf(_ORDER_BY_CLAUSE);
108
109 if (pos != -1) {
110 return sql.substring(0, pos + 1).concat(criteria).concat(
111 sql.substring(pos + 1));
112 }
113
114 return sql.concat(criteria);
115 }
116
117 public String get(String id) {
118 return _sqlPool.get(id);
119 }
120
121 public String get(String id, QueryDefinition queryDefinition) {
122 return get(id, queryDefinition, StringPool.BLANK);
123 }
124
125 public String get(
126 String id, QueryDefinition queryDefinition, String tableName) {
127
128 String sql = get(id);
129
130 if (!Validator.isBlank(tableName) &&
131 !tableName.endsWith(StringPool.PERIOD)) {
132
133 tableName = tableName.concat(StringPool.PERIOD);
134 }
135
136 if (queryDefinition.getStatus() == WorkflowConstants.STATUS_ANY) {
137 sql = sql.replace(_STATUS_KEYWORD, _STATUS_CONDITION_EMPTY);
138 }
139 else {
140 if (queryDefinition.isExcludeStatus()) {
141 sql = sql.replace(
142 _STATUS_KEYWORD,
143 tableName.concat(_STATUS_CONDITION_INVERSE));
144 }
145 else {
146 sql = sql.replace(
147 _STATUS_KEYWORD,
148 tableName.concat(_STATUS_CONDITION_DEFAULT));
149 }
150 }
151
152 if (queryDefinition.getOwnerUserId() > 0) {
153 if (queryDefinition.isIncludeOwner()) {
154 StringBundler sb = new StringBundler(7);
155
156 sb.append(StringPool.OPEN_PARENTHESIS);
157 sb.append(tableName);
158 sb.append(_OWNER_USER_ID_CONDITION_DEFAULT);
159 sb.append(" AND ");
160 sb.append(tableName);
161 sb.append(_STATUS_CONDITION_INVERSE);
162 sb.append(StringPool.CLOSE_PARENTHESIS);
163
164 sql = sql.replace(_OWNER_USER_ID_KEYWORD, sb.toString());
165
166 sql = sql.replace(_OWNER_USER_ID_AND_OR_CONNECTOR, " OR ");
167 }
168 else {
169 sql = sql.replace(
170 _OWNER_USER_ID_KEYWORD,
171 tableName.concat(_OWNER_USER_ID_CONDITION_DEFAULT));
172
173 sql = sql.replace(_OWNER_USER_ID_AND_OR_CONNECTOR, " AND ");
174 }
175 }
176 else {
177 sql = sql.replace(_OWNER_USER_ID_KEYWORD, StringPool.BLANK);
178
179 sql = sql.replace(
180 _OWNER_USER_ID_AND_OR_CONNECTOR, StringPool.BLANK);
181 }
182
183 return sql;
184 }
185
186
191 public boolean isVendorDB2() {
192 return _vendorDB2;
193 }
194
195
202 public boolean isVendorHSQL() {
203 return _vendorHSQL;
204 }
205
206
213 public boolean isVendorInformix() {
214 return _vendorInformix;
215 }
216
217
222 public boolean isVendorMySQL() {
223 return _vendorMySQL;
224 }
225
226
236 public boolean isVendorOracle() {
237 return _vendorOracle;
238 }
239
240
247 public boolean isVendorPostgreSQL() {
248 return _vendorPostgreSQL;
249 }
250
251
257 public boolean isVendorSybase() {
258 return _vendorSybase;
259 }
260
261 public String[] keywords(String keywords) {
262 return keywords(keywords, true);
263 }
264
265 public String[] keywords(String keywords, boolean lowerCase) {
266 if (Validator.isNull(keywords)) {
267 return new String[] {null};
268 }
269
270 if (_CUSTOM_SQL_AUTO_ESCAPE_WILDCARDS_ENABLED) {
271 keywords = escapeWildCards(keywords);
272 }
273
274 if (lowerCase) {
275 keywords = StringUtil.toLowerCase(keywords);
276 }
277
278 keywords = keywords.trim();
279
280 List<String> keywordsList = new ArrayList<String>();
281
282 for (int i = 0; i < keywords.length(); i++) {
283 char c = keywords.charAt(i);
284
285 if (c == CharPool.QUOTE) {
286 int pos = i + 1;
287
288 i = keywords.indexOf(CharPool.QUOTE, pos);
289
290 if (i == -1) {
291 i = keywords.length();
292 }
293
294 if (i > pos) {
295 String keyword = keywords.substring(pos, i);
296
297 keywordsList.add(
298 StringUtil.quote(keyword, StringPool.PERCENT));
299 }
300 }
301 else {
302 while (Character.isWhitespace(c)) {
303 i++;
304
305 c = keywords.charAt(i);
306 }
307
308 int pos = i;
309
310 while (!Character.isWhitespace(c)) {
311 i++;
312
313 if (i == keywords.length()) {
314 break;
315 }
316
317 c = keywords.charAt(i);
318 }
319
320 String keyword = keywords.substring(pos, i);
321
322 keywordsList.add(StringUtil.quote(keyword, StringPool.PERCENT));
323 }
324 }
325
326 return keywordsList.toArray(new String[keywordsList.size()]);
327 }
328
329 public String[] keywords(String[] keywordsArray) {
330 return keywords(keywordsArray, true);
331 }
332
333 public String[] keywords(String[] keywordsArray, boolean lowerCase) {
334 if (ArrayUtil.isEmpty(keywordsArray)) {
335 return new String[] {null};
336 }
337
338 if (lowerCase) {
339 for (int i = 0; i < keywordsArray.length; i++) {
340 keywordsArray[i] = StringUtil.lowerCase(keywordsArray[i]);
341 }
342 }
343
344 return keywordsArray;
345 }
346
347 public void reloadCustomSQL() throws SQLException {
348 PortalUtil.initCustomSQL();
349
350 Connection con = DataAccess.getConnection();
351
352 String functionIsNull = PortalUtil.getCustomSQLFunctionIsNull();
353 String functionIsNotNull = PortalUtil.getCustomSQLFunctionIsNotNull();
354
355 try {
356 if (Validator.isNotNull(functionIsNull) &&
357 Validator.isNotNull(functionIsNotNull)) {
358
359 _functionIsNull = functionIsNull;
360 _functionIsNotNull = functionIsNotNull;
361
362 if (_log.isDebugEnabled()) {
363 _log.debug(
364 "functionIsNull is manually set to " + functionIsNull);
365 _log.debug(
366 "functionIsNotNull is manually set to " +
367 functionIsNotNull);
368 }
369 }
370 else if (con != null) {
371 DatabaseMetaData metaData = con.getMetaData();
372
373 String dbName = GetterUtil.getString(
374 metaData.getDatabaseProductName());
375
376 if (_log.isInfoEnabled()) {
377 _log.info("Database name " + dbName);
378 }
379
380 if (dbName.startsWith("DB2")) {
381 _vendorDB2 = true;
382 _functionIsNull = DB2_FUNCTION_IS_NULL;
383 _functionIsNotNull = DB2_FUNCTION_IS_NOT_NULL;
384
385 if (_log.isInfoEnabled()) {
386 _log.info("Detected DB2 with database name " + dbName);
387 }
388 }
389 else if (dbName.startsWith("HSQL")) {
390 _vendorHSQL = true;
391
392 if (_log.isInfoEnabled()) {
393 _log.info("Detected HSQL with database name " + dbName);
394 }
395 }
396 else if (dbName.startsWith("Informix")) {
397 _vendorInformix = true;
398 _functionIsNull = INFORMIX_FUNCTION_IS_NULL;
399 _functionIsNotNull = INFORMIX_FUNCTION_IS_NOT_NULL;
400
401 if (_log.isInfoEnabled()) {
402 _log.info(
403 "Detected Informix with database name " + dbName);
404 }
405 }
406 else if (dbName.startsWith("MySQL")) {
407 _vendorMySQL = true;
408
409
410
411 if (_log.isInfoEnabled()) {
412 _log.info(
413 "Detected MySQL with database name " + dbName);
414 }
415 }
416 else if (dbName.startsWith("Sybase") || dbName.equals("ASE")) {
417 _vendorSybase = true;
418 _functionIsNull = SYBASE_FUNCTION_IS_NULL;
419 _functionIsNotNull = SYBASE_FUNCTION_IS_NOT_NULL;
420
421 if (_log.isInfoEnabled()) {
422 _log.info(
423 "Detected Sybase with database name " + dbName);
424 }
425 }
426 else if (dbName.startsWith("Oracle")) {
427 _vendorOracle = true;
428
429 if (_log.isInfoEnabled()) {
430 _log.info(
431 "Detected Oracle with database name " + dbName);
432 }
433 }
434 else if (dbName.startsWith("PostgreSQL")) {
435 _vendorPostgreSQL = true;
436
437 if (_log.isInfoEnabled()) {
438 _log.info(
439 "Detected PostgreSQL with database name " + dbName);
440 }
441 }
442 else {
443 if (_log.isDebugEnabled()) {
444 _log.debug(
445 "Unable to detect database with name " + dbName);
446 }
447 }
448 }
449 }
450 catch (Exception e) {
451 _log.error(e, e);
452 }
453 finally {
454 DataAccess.cleanUp(con);
455 }
456
457 if (_sqlPool == null) {
458 _sqlPool = new HashMap<String, String>();
459 }
460 else {
461 _sqlPool.clear();
462 }
463
464 try {
465 Class<?> clazz = getClass();
466
467 ClassLoader classLoader = clazz.getClassLoader();
468
469 String[] configs = getConfigs();
470
471 for (String _config : configs) {
472 read(classLoader, _config);
473 }
474 }
475 catch (Exception e) {
476 _log.error(e, e);
477 }
478 }
479
480 public String removeGroupBy(String sql) {
481 int x = sql.indexOf(_GROUP_BY_CLAUSE);
482
483 if (x != -1) {
484 int y = sql.indexOf(_ORDER_BY_CLAUSE);
485
486 if (y == -1) {
487 sql = sql.substring(0, x);
488 }
489 else {
490 sql = sql.substring(0, x) + sql.substring(y);
491 }
492 }
493
494 return sql;
495 }
496
497 public String removeOrderBy(String sql) {
498 int pos = sql.indexOf(_ORDER_BY_CLAUSE);
499
500 if (pos != -1) {
501 sql = sql.substring(0, pos);
502 }
503
504 return sql;
505 }
506
507 public String replaceAndOperator(String sql, boolean andOperator) {
508 String andOrConnector = "OR";
509 String andOrNullCheck = "AND ? IS NOT NULL";
510
511 if (andOperator) {
512 andOrConnector = "AND";
513 andOrNullCheck = "OR ? IS NULL";
514 }
515
516 sql = StringUtil.replace(
517 sql,
518 new String[] {
519 "[$AND_OR_CONNECTOR$]", "[$AND_OR_NULL_CHECK$]"
520 },
521 new String[] {
522 andOrConnector, andOrNullCheck
523 });
524
525 if (_vendorPostgreSQL) {
526 sql = StringUtil.replace(
527 sql,
528 new String[] {
529 "Date >= ? AND ? IS NOT NULL",
530 "Date <= ? AND ? IS NOT NULL", "Date >= ? OR ? IS NULL",
531 "Date <= ? OR ? IS NULL"
532 },
533 new String[] {
534 "Date >= ? AND CAST(? AS TIMESTAMP) IS NOT NULL",
535 "Date <= ? AND CAST(? AS TIMESTAMP) IS NOT NULL",
536 "Date >= ? OR CAST(? AS TIMESTAMP) IS NULL",
537 "Date <= ? OR CAST(? AS TIMESTAMP) IS NULL"
538 });
539 }
540
541 sql = replaceIsNull(sql);
542
543 return sql;
544 }
545
546 public String replaceGroupBy(String sql, String groupBy) {
547 if (groupBy == null) {
548 return sql;
549 }
550
551 int x = sql.indexOf(_GROUP_BY_CLAUSE);
552
553 if (x != -1) {
554 int y = sql.indexOf(_ORDER_BY_CLAUSE);
555
556 if (y == -1) {
557 sql = sql.substring(0, x + _GROUP_BY_CLAUSE.length()).concat(
558 groupBy);
559 }
560 else {
561 sql = sql.substring(0, x + _GROUP_BY_CLAUSE.length()).concat(
562 groupBy).concat(sql.substring(y));
563 }
564 }
565 else {
566 int y = sql.indexOf(_ORDER_BY_CLAUSE);
567
568 if (y == -1) {
569 sql = sql.concat(_GROUP_BY_CLAUSE).concat(groupBy);
570 }
571 else {
572 StringBundler sb = new StringBundler();
573
574 sb.append(sql.substring(0, y));
575 sb.append(_GROUP_BY_CLAUSE);
576 sb.append(groupBy);
577 sb.append(sql.substring(y));
578
579 sql = sb.toString();
580 }
581 }
582
583 return sql;
584 }
585
586 public String replaceIsNull(String sql) {
587 if (Validator.isNotNull(_functionIsNull)) {
588 sql = StringUtil.replace(
589 sql,
590 new String[] {
591 "? IS NULL", "? IS NOT NULL"
592 },
593 new String[] {
594 _functionIsNull, _functionIsNotNull
595 });
596 }
597
598 return sql;
599 }
600
601 public String replaceKeywords(
602 String sql, String field, boolean last, int[] values) {
603
604 if ((values != null) && (values.length == 1)) {
605 return sql;
606 }
607
608 StringBundler oldSql = new StringBundler(4);
609
610 oldSql.append(StringPool.OPEN_PARENTHESIS);
611 oldSql.append(field);
612 oldSql.append(" = ?)");
613
614 if (!last) {
615 oldSql.append(" [$AND_OR_CONNECTOR$]");
616 }
617
618 if (ArrayUtil.isEmpty(values)) {
619 return StringUtil.replace(sql, oldSql.toString(), StringPool.BLANK);
620 }
621
622 StringBundler newSql = new StringBundler(values.length * 4 + 3);
623
624 newSql.append(StringPool.OPEN_PARENTHESIS);
625
626 for (int i = 0; i < values.length; i++) {
627 if (i > 0) {
628 newSql.append(" OR ");
629 }
630
631 newSql.append(StringPool.OPEN_PARENTHESIS);
632 newSql.append(field);
633 newSql.append(" = ?)");
634 }
635
636 newSql.append(StringPool.CLOSE_PARENTHESIS);
637
638 if (!last) {
639 newSql.append(" [$AND_OR_CONNECTOR$]");
640 }
641
642 return StringUtil.replace(sql, oldSql.toString(), newSql.toString());
643 }
644
645 public String replaceKeywords(
646 String sql, String field, boolean last, long[] values) {
647
648 if ((values != null) && (values.length == 1)) {
649 return sql;
650 }
651
652 StringBundler oldSql = new StringBundler(4);
653
654 oldSql.append(StringPool.OPEN_PARENTHESIS);
655 oldSql.append(field);
656 oldSql.append(" = ?)");
657
658 if (!last) {
659 oldSql.append(" [$AND_OR_CONNECTOR$]");
660 }
661
662 if (ArrayUtil.isEmpty(values)) {
663 return StringUtil.replace(sql, oldSql.toString(), StringPool.BLANK);
664 }
665
666 StringBundler newSql = new StringBundler(values.length * 4 + 3);
667
668 newSql.append(StringPool.OPEN_PARENTHESIS);
669
670 for (int i = 0; i < values.length; i++) {
671 if (i > 0) {
672 newSql.append(" OR ");
673 }
674
675 newSql.append(StringPool.OPEN_PARENTHESIS);
676 newSql.append(field);
677 newSql.append(" = ?)");
678 }
679
680 newSql.append(StringPool.CLOSE_PARENTHESIS);
681
682 if (!last) {
683 newSql.append(" [$AND_OR_CONNECTOR$]");
684 }
685
686 return StringUtil.replace(sql, oldSql.toString(), newSql.toString());
687 }
688
689 public String replaceKeywords(
690 String sql, String field, String operator, boolean last,
691 String[] values) {
692
693 if ((values != null) && (values.length <= 1)) {
694 return sql;
695 }
696
697 StringBundler oldSql = new StringBundler(6);
698
699 oldSql.append(StringPool.OPEN_PARENTHESIS);
700 oldSql.append(field);
701 oldSql.append(" ");
702 oldSql.append(operator);
703 oldSql.append(" ? [$AND_OR_NULL_CHECK$])");
704
705 if (!last) {
706 oldSql.append(" [$AND_OR_CONNECTOR$]");
707 }
708
709 StringBundler newSql = new StringBundler(values.length * 6 + 3);
710
711 newSql.append(StringPool.OPEN_PARENTHESIS);
712
713 for (int i = 0; i < values.length; i++) {
714 if (i > 0) {
715 newSql.append(" OR ");
716 }
717
718 newSql.append(StringPool.OPEN_PARENTHESIS);
719 newSql.append(field);
720 newSql.append(" ");
721 newSql.append(operator);
722 newSql.append(" ? [$AND_OR_NULL_CHECK$])");
723 }
724
725 newSql.append(StringPool.CLOSE_PARENTHESIS);
726
727 if (!last) {
728 newSql.append(" [$AND_OR_CONNECTOR$]");
729 }
730
731 return StringUtil.replace(sql, oldSql.toString(), newSql.toString());
732 }
733
734 public String replaceOrderBy(String sql, OrderByComparator obc) {
735 if (obc == null) {
736 return sql;
737 }
738
739 String orderBy = obc.getOrderBy();
740
741 int pos = sql.indexOf(_ORDER_BY_CLAUSE);
742
743 if ((pos != -1) && (pos < sql.length())) {
744 sql = sql.substring(0, pos + _ORDER_BY_CLAUSE.length()).concat(
745 orderBy);
746 }
747 else {
748 sql = sql.concat(_ORDER_BY_CLAUSE).concat(orderBy);
749 }
750
751 return sql;
752 }
753
754 protected String[] getConfigs() {
755 if (PortalClassLoaderUtil.getClassLoader() ==
756 CustomSQL.class.getClassLoader()) {
757
758 Properties propsUtil = PortalUtil.getPortalProperties();
759
760 return StringUtil.split(
761 propsUtil.getProperty("custom.sql.configs"));
762 }
763 else {
764 return new String[] {"custom-sql/default.xml"};
765 }
766 }
767
768 protected void read(ClassLoader classLoader, String source)
769 throws Exception {
770
771 InputStream is = classLoader.getResourceAsStream(source);
772
773 if (is == null) {
774 return;
775 }
776
777 try {
778 if (_log.isDebugEnabled()) {
779 _log.debug("Loading " + source);
780 }
781
782 Document document = UnsecureSAXReaderUtil.read(is);
783
784 Element rootElement = document.getRootElement();
785
786 for (Element sqlElement : rootElement.elements("sql")) {
787 String file = sqlElement.attributeValue("file");
788
789 if (Validator.isNotNull(file)) {
790 read(classLoader, file);
791 }
792 else {
793 String id = sqlElement.attributeValue("id");
794 String content = transform(sqlElement.getText());
795
796 content = replaceIsNull(content);
797
798 _sqlPool.put(id, content);
799 }
800 }
801 }
802 finally {
803 StreamUtil.cleanUp(is);
804 }
805 }
806
807 protected String transform(String sql) {
808 sql = PortalUtil.transformCustomSQL(sql);
809
810 StringBundler sb = new StringBundler();
811
812 try {
813 UnsyncBufferedReader unsyncBufferedReader =
814 new UnsyncBufferedReader(new UnsyncStringReader(sql));
815
816 String line = null;
817
818 while ((line = unsyncBufferedReader.readLine()) != null) {
819 sb.append(line.trim());
820 sb.append(StringPool.SPACE);
821 }
822
823 unsyncBufferedReader.close();
824 }
825 catch (IOException ioe) {
826 return sql;
827 }
828
829 return sb.toString();
830 }
831
832 private String escapeWildCards(String keywords) {
833 if (!isVendorMySQL() && !isVendorOracle()) {
834 return keywords;
835 }
836
837 StringBuilder sb = new StringBuilder(keywords);
838
839 for (int i = 0; i < sb.length(); ++i) {
840 char c = sb.charAt(i);
841
842 if (c == CharPool.BACK_SLASH) {
843 i++;
844
845 continue;
846 }
847
848 if ((c == CharPool.UNDERLINE) || (c == CharPool.PERCENT)) {
849 sb.insert(i, CharPool.BACK_SLASH);
850
851 i++;
852
853 continue;
854 }
855 }
856
857 return sb.toString();
858 }
859
860 private static final boolean _CUSTOM_SQL_AUTO_ESCAPE_WILDCARDS_ENABLED =
861 GetterUtil.getBoolean(
862 PropsUtil.get(PropsKeys.CUSTOM_SQL_AUTO_ESCAPE_WILDCARDS_ENABLED));
863
864 private static final String _GROUP_BY_CLAUSE = " GROUP BY ";
865
866 private static final String _ORDER_BY_CLAUSE = " ORDER BY ";
867
868 private static final String _OWNER_USER_ID_AND_OR_CONNECTOR =
869 "[$OWNER_USER_ID_AND_OR_CONNECTOR$]";
870
871 private static final String _OWNER_USER_ID_CONDITION_DEFAULT = "userId = ?";
872
873 private static final String _OWNER_USER_ID_KEYWORD = "[$OWNER_USER_ID$]";
874
875 private static final String _STATUS_CONDITION_DEFAULT = "status = ?";
876
877 private static final String _STATUS_CONDITION_EMPTY =
878 WorkflowConstants.STATUS_ANY + " = ?";
879
880 private static final String _STATUS_CONDITION_INVERSE = "status != ?";
881
882 private static final String _STATUS_KEYWORD = "[$STATUS$]";
883
884 private static Log _log = LogFactoryUtil.getLog(CustomSQL.class);
885
886 private String _functionIsNotNull;
887 private String _functionIsNull;
888 private Map<String, String> _sqlPool;
889 private boolean _vendorDB2;
890 private boolean _vendorHSQL;
891 private boolean _vendorInformix;
892 private boolean _vendorMySQL;
893 private boolean _vendorOracle;
894 private boolean _vendorPostgreSQL;
895 private boolean _vendorSybase;
896
897 }