001
014
015 package com.liferay.portal.dao.db;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.dao.orm.common.SQLTransformer;
019 import com.liferay.portal.kernel.dao.db.DB;
020 import com.liferay.portal.kernel.dao.db.Index;
021 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
022 import com.liferay.portal.kernel.exception.SystemException;
023 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
024 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
025 import com.liferay.portal.kernel.log.Log;
026 import com.liferay.portal.kernel.log.LogFactoryUtil;
027 import com.liferay.portal.kernel.util.FileUtil;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.PropertiesUtil;
030 import com.liferay.portal.kernel.util.StringBundler;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.StringUtil;
033 import com.liferay.portal.kernel.util.Validator;
034 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
035 import com.liferay.portal.util.ClassLoaderUtil;
036 import com.liferay.portal.velocity.VelocityUtil;
037 import com.liferay.util.SimpleCounter;
038
039 import java.io.File;
040 import java.io.FileReader;
041 import java.io.IOException;
042 import java.io.InputStream;
043
044 import java.sql.Connection;
045 import java.sql.SQLException;
046 import java.sql.Statement;
047
048 import java.util.Collections;
049 import java.util.Enumeration;
050 import java.util.HashMap;
051 import java.util.HashSet;
052 import java.util.List;
053 import java.util.Map;
054 import java.util.Properties;
055 import java.util.Set;
056 import java.util.regex.Matcher;
057 import java.util.regex.Pattern;
058
059 import javax.naming.NamingException;
060
061
067 public abstract class BaseDB implements DB {
068
069 @Override
070 public void addIndexes(
071 Connection con, String indexesSQL, Set<String> validIndexNames)
072 throws IOException {
073
074 if (_log.isInfoEnabled()) {
075 _log.info("Adding indexes");
076 }
077
078 UnsyncBufferedReader bufferedReader = new UnsyncBufferedReader(
079 new UnsyncStringReader(indexesSQL));
080
081 String sql = null;
082
083 while ((sql = bufferedReader.readLine()) != null) {
084 if (Validator.isNull(sql)) {
085 continue;
086 }
087
088 int y = sql.indexOf(" on ");
089 int x = sql.lastIndexOf(" ", y - 1);
090
091 String indexName = sql.substring(x + 1, y);
092
093 if (validIndexNames.contains(indexName)) {
094 continue;
095 }
096
097 if (_log.isInfoEnabled()) {
098 _log.info(sql);
099 }
100
101 try {
102 runSQL(con, sql);
103 }
104 catch (Exception e) {
105 if (_log.isWarnEnabled()) {
106 _log.warn(e.getMessage() + ": " + sql);
107 }
108 }
109 }
110 }
111
112 @Override
113 public void buildCreateFile(String sqlDir, String databaseName)
114 throws IOException {
115
116 buildCreateFile(sqlDir, databaseName, BARE);
117 buildCreateFile(sqlDir, databaseName, DEFAULT);
118 buildCreateFile(sqlDir, databaseName, SHARDED);
119 }
120
121 @Override
122 public void buildCreateFile(
123 String sqlDir, String databaseName, int population)
124 throws IOException {
125
126 String suffix = getSuffix(population);
127
128 File file = new File(
129 sqlDir + "/create" + suffix + "/create" + suffix + "-" +
130 getServerName() + ".sql");
131
132 if (population != SHARDED) {
133 String content = buildCreateFileContent(
134 sqlDir, databaseName, population);
135
136 if (content != null) {
137 FileUtil.write(file, content);
138 }
139 }
140 else {
141 String content = buildCreateFileContent(
142 sqlDir, databaseName, DEFAULT);
143
144 if (content != null) {
145 FileUtil.write(file, content);
146 }
147
148 content = buildCreateFileContent(
149 sqlDir, databaseName + "1", DEFAULT);
150
151 if (content != null) {
152 FileUtil.write(file, content, false, true);
153 }
154
155 content = buildCreateFileContent(
156 sqlDir, databaseName + "2", DEFAULT);
157
158 if (content != null) {
159 FileUtil.write(file, content, false, true);
160 }
161 }
162 }
163
164 @Override
165 public abstract String buildSQL(String template) throws IOException;
166
167 @Override
168 public void buildSQLFile(String sqlDir, String fileName)
169 throws IOException {
170
171 String template = buildTemplate(sqlDir, fileName);
172
173 if (Validator.isNull(template)) {
174 return;
175 }
176
177 template = buildSQL(template);
178
179 FileUtil.write(
180 sqlDir + "/" + fileName + "/" + fileName + "-" + getServerName() +
181 ".sql",
182 template);
183 }
184
185 @Override
186 @SuppressWarnings("unused")
187 public List<Index> getIndexes(Connection con) throws SQLException {
188 return Collections.emptyList();
189 }
190
191 @Override
192 public String getTemplateFalse() {
193 return getTemplate()[2];
194 }
195
196 @Override
197 public String getTemplateTrue() {
198 return getTemplate()[1];
199 }
200
201 @Override
202 public String getType() {
203 return _type;
204 }
205
206 @Override
207 public long increment() throws SystemException {
208 return CounterLocalServiceUtil.increment();
209 }
210
211 @Override
212 public long increment(String name) throws SystemException {
213 return CounterLocalServiceUtil.increment(name);
214 }
215
216 @Override
217 public boolean isSupportsAlterColumnName() {
218 return _SUPPORTS_ALTER_COLUMN_NAME;
219 }
220
221 @Override
222 public boolean isSupportsAlterColumnType() {
223 return _SUPPORTS_ALTER_COLUMN_TYPE;
224 }
225
226 @Override
227 public boolean isSupportsDateMilliseconds() {
228 return _SUPPORTS_DATE_MILLISECONDS;
229 }
230
231 @Override
232 public boolean isSupportsInlineDistinct() {
233 return _SUPPORTS_INLINE_DISTINCT;
234 }
235
236 @Override
237 public boolean isSupportsQueryingAfterException() {
238 return _SUPPORTS_QUERYING_AFTER_EXCEPTION;
239 }
240
241 @Override
242 public boolean isSupportsScrollableResults() {
243 return _SUPPORTS_SCROLLABLE_RESULTS;
244 }
245
246 @Override
247 public boolean isSupportsStringCaseSensitiveQuery() {
248 return _supportsStringCaseSensitiveQuery;
249 }
250
251 @Override
252 public boolean isSupportsUpdateWithInnerJoin() {
253 return _SUPPORTS_UPDATE_WITH_INNER_JOIN;
254 }
255
256 @Override
257 public void runSQL(Connection con, String sql)
258 throws IOException, SQLException {
259
260 runSQL(con, new String[] {sql});
261 }
262
263 @Override
264 public void runSQL(Connection con, String[] sqls)
265 throws IOException, SQLException {
266
267 Statement s = null;
268
269 try {
270 s = con.createStatement();
271
272 for (int i = 0; i < sqls.length; i++) {
273 String sql = buildSQL(sqls[i]);
274
275 sql = SQLTransformer.transform(sql.trim());
276
277 if (sql.endsWith(";")) {
278 sql = sql.substring(0, sql.length() - 1);
279 }
280
281 if (sql.endsWith("go")) {
282 sql = sql.substring(0, sql.length() - 2);
283 }
284
285 if (_log.isDebugEnabled()) {
286 _log.debug(sql);
287 }
288
289 try {
290 s.executeUpdate(sql);
291 }
292 catch (SQLException sqle) {
293 handleSQLException(sql, sqle);
294 }
295 }
296 }
297 finally {
298 DataAccess.cleanUp(s);
299 }
300 }
301
302 @Override
303 public void runSQL(String sql) throws IOException, SQLException {
304 runSQL(new String[] {sql});
305 }
306
307 @Override
308 public void runSQL(String[] sqls) throws IOException, SQLException {
309 Connection con = DataAccess.getConnection();
310
311 try {
312 runSQL(con, sqls);
313 }
314 finally {
315 DataAccess.cleanUp(con);
316 }
317 }
318
319 @Override
320 public void runSQLTemplate(String path)
321 throws IOException, NamingException, SQLException {
322
323 runSQLTemplate(path, true);
324 }
325
326 @Override
327 public void runSQLTemplate(String path, boolean failOnError)
328 throws IOException, NamingException, SQLException {
329
330 ClassLoader classLoader = ClassLoaderUtil.getContextClassLoader();
331
332 InputStream is = classLoader.getResourceAsStream(
333 "com/liferay/portal/tools/sql/dependencies/" + path);
334
335 if (is == null) {
336 is = classLoader.getResourceAsStream(path);
337 }
338
339 if (is == null) {
340 _log.error("Invalid path " + path);
341
342 if (failOnError) {
343 throw new IOException("Invalid path " + path);
344 }
345 else {
346 return;
347 }
348 }
349
350 String template = StringUtil.read(is);
351
352 boolean evaluate = path.endsWith(".vm");
353
354 runSQLTemplateString(template, evaluate, failOnError);
355 }
356
357 @Override
358 public void runSQLTemplateString(
359 String template, boolean evaluate, boolean failOnError)
360 throws IOException, NamingException, SQLException {
361
362 if (evaluate) {
363 try {
364 template = evaluateVM(template);
365 }
366 catch (Exception e) {
367 _log.error(e, e);
368 }
369 }
370
371 StringBundler sb = new StringBundler();
372
373 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
374 new UnsyncStringReader(template));
375
376 String line = null;
377
378 while ((line = unsyncBufferedReader.readLine()) != null) {
379 if (!line.startsWith("##")) {
380 if (line.startsWith("@include ")) {
381 int pos = line.indexOf(" ");
382
383 String includeFileName = line.substring(pos + 1);
384
385 ClassLoader classLoader =
386 ClassLoaderUtil.getContextClassLoader();
387
388 InputStream is = classLoader.getResourceAsStream(
389 "com/liferay/portal/tools/sql/dependencies/" +
390 includeFileName);
391
392 if (is == null) {
393 is = classLoader.getResourceAsStream(includeFileName);
394 }
395
396 String include = StringUtil.read(is);
397
398 if (includeFileName.endsWith(".vm")) {
399 try {
400 include = evaluateVM(include);
401 }
402 catch (Exception e) {
403 _log.error(e, e);
404 }
405 }
406
407 include = convertTimestamp(include);
408 include = replaceTemplate(include, getTemplate());
409
410 runSQLTemplateString(include, false, true);
411 }
412 else {
413 sb.append(line);
414
415 if (line.endsWith(";")) {
416 String sql = sb.toString();
417
418 sb.setIndex(0);
419
420 try {
421 if (!sql.equals("COMMIT_TRANSACTION;")) {
422 runSQL(sql);
423 }
424 else {
425 if (_log.isDebugEnabled()) {
426 _log.debug("Skip commit sql");
427 }
428 }
429 }
430 catch (IOException ioe) {
431 if (failOnError) {
432 throw ioe;
433 }
434 else if (_log.isWarnEnabled()) {
435 _log.warn(ioe.getMessage());
436 }
437 }
438 catch (SecurityException se) {
439 if (failOnError) {
440 throw se;
441 }
442 else if (_log.isWarnEnabled()) {
443 _log.warn(se.getMessage());
444 }
445 }
446 catch (SQLException sqle) {
447 if (failOnError) {
448 throw sqle;
449 }
450
451 String message = GetterUtil.getString(
452 sqle.getMessage());
453
454 if (!message.startsWith("Duplicate key name") &&
455 _log.isWarnEnabled()) {
456
457 _log.warn(message + ": " + buildSQL(sql));
458 }
459
460 if (message.startsWith("Duplicate entry") ||
461 message.startsWith(
462 "Specified key was too long")) {
463
464 _log.error(line);
465 }
466 }
467 }
468 }
469 }
470 }
471
472 unsyncBufferedReader.close();
473 }
474
475 @Override
476 public void setSupportsStringCaseSensitiveQuery(
477 boolean supportsStringCaseSensitiveQuery) {
478
479 if (_log.isInfoEnabled()) {
480 if (supportsStringCaseSensitiveQuery) {
481 _log.info("Database supports case sensitive queries");
482 }
483 else {
484 _log.info("Database does not support case sensitive queries");
485 }
486 }
487
488 _supportsStringCaseSensitiveQuery = supportsStringCaseSensitiveQuery;
489 }
490
491 @Override
492 public void updateIndexes(
493 Connection con, String tablesSQL, String indexesSQL,
494 String indexesProperties, boolean dropIndexes)
495 throws IOException, SQLException {
496
497 List<Index> indexes = getIndexes(con);
498
499 Set<String> validIndexNames = null;
500
501 if (dropIndexes) {
502 validIndexNames = dropIndexes(
503 con, tablesSQL, indexesSQL, indexesProperties, indexes);
504 }
505 else {
506 validIndexNames = new HashSet<String>();
507
508 for (Index index : indexes) {
509 String indexName = StringUtil.toUpperCase(index.getIndexName());
510
511 validIndexNames.add(indexName);
512 }
513 }
514
515 addIndexes(con, indexesSQL, validIndexNames);
516 }
517
518 protected BaseDB(String type) {
519 _type = type;
520
521 String[] actual = getTemplate();
522
523 for (int i = 0; i < TEMPLATE.length; i++) {
524 _templateMap.put(TEMPLATE[i], actual[i]);
525 }
526 }
527
528 protected String[] buildColumnNameTokens(String line) {
529 String[] words = StringUtil.split(line, ' ');
530
531 String nullable = "";
532
533 if (words.length == 7) {
534 nullable = "not null;";
535 }
536
537 String[] template = {
538 words[1], words[2], words[3], words[4], nullable
539 };
540
541 return template;
542 }
543
544 protected String[] buildColumnTypeTokens(String line) {
545 String[] words = StringUtil.split(line, ' ');
546
547 String nullable = "";
548
549 if (words.length == 6) {
550 nullable = "not null;";
551 }
552 else if (words.length == 5) {
553 nullable = words[4];
554 }
555 else if (words.length == 4) {
556 nullable = "not null;";
557
558 if (words[3].endsWith(";")) {
559 words[3] = words[3].substring(0, words[3].length() - 1);
560 }
561 }
562
563 String[] template = {
564 words[1], words[2], "", words[3], nullable
565 };
566
567 return template;
568 }
569
570 protected abstract String buildCreateFileContent(
571 String sqlDir, String databaseName, int population)
572 throws IOException;
573
574 protected String[] buildTableNameTokens(String line) {
575 String[] words = StringUtil.split(line, StringPool.SPACE);
576
577 return new String[] {words[1], words[2]};
578 }
579
580 protected String buildTemplate(String sqlDir, String fileName)
581 throws IOException {
582
583 String template = readFile(sqlDir + "/" + fileName + ".sql");
584
585 if (fileName.equals("portal") ||
586 fileName.equals("update-5.0.1-5.1.0")) {
587
588 UnsyncBufferedReader unsyncBufferedReader =
589 new UnsyncBufferedReader(new UnsyncStringReader(template));
590
591 StringBundler sb = new StringBundler();
592
593 String line = null;
594
595 while ((line = unsyncBufferedReader.readLine()) != null) {
596 if (line.startsWith("@include ")) {
597 int pos = line.indexOf(" ");
598
599 String includeFileName = line.substring(pos + 1);
600
601 File includeFile = new File(sqlDir + "/" + includeFileName);
602
603 if (!includeFile.exists()) {
604 continue;
605 }
606
607 String include = FileUtil.read(includeFile);
608
609 if (includeFileName.endsWith(".vm")) {
610 try {
611 include = evaluateVM(include);
612 }
613 catch (Exception e) {
614 _log.error(e, e);
615 }
616 }
617
618 include = convertTimestamp(include);
619 include = replaceTemplate(include, getTemplate());
620
621 sb.append(include);
622 sb.append("\n\n");
623 }
624 else {
625 sb.append(line);
626 sb.append("\n");
627 }
628 }
629
630 unsyncBufferedReader.close();
631
632 template = sb.toString();
633 }
634
635 if (fileName.equals("indexes") && (this instanceof SybaseDB)) {
636 template = removeBooleanIndexes(sqlDir, template);
637 }
638
639 return template;
640 }
641
642 protected String convertTimestamp(String data) {
643 String s = null;
644
645 if (this instanceof MySQLDB) {
646 s = StringUtil.replace(data, "SPECIFIC_TIMESTAMP_", "");
647 }
648 else {
649 Matcher matcher = _timestampPattern.matcher(data);
650
651 s = matcher.replaceAll("CURRENT_TIMESTAMP");
652 }
653
654 return s;
655 }
656
657 protected Set<String> dropIndexes(
658 Connection con, String tablesSQL, String indexesSQL,
659 String indexesProperties, List<Index> indexes)
660 throws IOException, SQLException {
661
662 if (_log.isInfoEnabled()) {
663 _log.info("Dropping stale indexes");
664 }
665
666 Set<String> validIndexNames = new HashSet<String>();
667
668 if (indexes.isEmpty()) {
669 return validIndexNames;
670 }
671
672 String tablesSQLLowerCase = StringUtil.toLowerCase(tablesSQL);
673 String indexesSQLLowerCase = StringUtil.toLowerCase(indexesSQL);
674
675 Properties indexesPropertiesObj = PropertiesUtil.load(
676 indexesProperties);
677
678 Enumeration<String> enu =
679 (Enumeration<String>)indexesPropertiesObj.propertyNames();
680
681 while (enu.hasMoreElements()) {
682 String key = enu.nextElement();
683
684 String value = indexesPropertiesObj.getProperty(key);
685
686 indexesPropertiesObj.setProperty(
687 StringUtil.toLowerCase(key), value);
688 }
689
690 for (Index index : indexes) {
691 String indexNameUpperCase = StringUtil.toUpperCase(
692 index.getIndexName());
693 String indexNameLowerCase = StringUtil.toLowerCase(
694 indexNameUpperCase);
695 String tableName = index.getTableName();
696 String tableNameLowerCase = StringUtil.toLowerCase(tableName);
697 boolean unique = index.isUnique();
698
699 validIndexNames.add(indexNameUpperCase);
700
701 if (indexesPropertiesObj.containsKey(indexNameLowerCase)) {
702 if (unique &&
703 indexesSQLLowerCase.contains(
704 "create unique index " + indexNameLowerCase + " ")) {
705
706 continue;
707 }
708
709 if (!unique &&
710 indexesSQLLowerCase.contains(
711 "create index " + indexNameLowerCase + " ")) {
712
713 continue;
714 }
715 }
716 else if (!tablesSQLLowerCase.contains(
717 "create table " + tableNameLowerCase + " (")) {
718
719 continue;
720 }
721
722 validIndexNames.remove(indexNameUpperCase);
723
724 String sql =
725 "drop index " + indexNameUpperCase + " on " + tableName;
726
727 if (_log.isInfoEnabled()) {
728 _log.info(sql);
729 }
730
731 runSQL(con, sql);
732 }
733
734 return validIndexNames;
735 }
736
737 protected String evaluateVM(String template) throws Exception {
738 Map<String, Object> variables = new HashMap<String, Object>();
739
740 variables.put("counter", new SimpleCounter());
741 variables.put("portalUUIDUtil", PortalUUIDUtil.class);
742
743 ClassLoader classLoader = ClassLoaderUtil.getContextClassLoader();
744
745 try {
746 ClassLoaderUtil.setContextClassLoader(
747 ClassLoaderUtil.getPortalClassLoader());
748
749 template = VelocityUtil.evaluate(template, variables);
750 }
751 finally {
752 ClassLoaderUtil.setContextClassLoader(classLoader);
753 }
754
755
756
757 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
758 new UnsyncStringReader(template));
759
760 StringBundler sb = new StringBundler();
761
762 String line = null;
763
764 while ((line = unsyncBufferedReader.readLine()) != null) {
765 line = line.trim();
766
767 sb.append(line);
768 sb.append("\n");
769 }
770
771 unsyncBufferedReader.close();
772
773 template = sb.toString();
774 template = StringUtil.replace(template, "\n\n\n", "\n\n");
775
776 return template;
777 }
778
779 protected String getCreateTablesContent(String sqlDir, String suffix)
780 throws IOException {
781
782 StringBundler sb = new StringBundler(8);
783
784 sb.append(sqlDir);
785
786 if (!sqlDir.endsWith("/WEB-INF/sql")) {
787 sb.append("/portal");
788 sb.append(suffix);
789 sb.append("/portal");
790 }
791 else {
792 sb.append("/tables");
793 sb.append(suffix);
794 sb.append("/tables");
795 }
796
797 sb.append(suffix);
798 sb.append(StringPool.DASH);
799 sb.append(getServerName());
800 sb.append(".sql");
801
802 return readFile(sb.toString());
803 }
804
805 protected abstract String getServerName();
806
807 protected String getSuffix(int type) {
808 if (type == BARE) {
809 return "-bare";
810 }
811 else if (type == SHARDED) {
812 return "-sharded";
813 }
814 else {
815 return StringPool.BLANK;
816 }
817 }
818
819 protected abstract String[] getTemplate();
820
821 protected void handleSQLException(String sql, SQLException sqle)
822 throws SQLException {
823
824 if (_log.isDebugEnabled()) {
825 StringBundler sb = new StringBundler(18);
826
827 sb.append("SQL: ");
828 sb.append(sql);
829 sb.append("\nSQL state: ");
830 sb.append(sqle.getSQLState());
831 sb.append("\nVendor: ");
832 sb.append(getType());
833 sb.append("\nVendor error code: ");
834 sb.append(sqle.getErrorCode());
835 sb.append("\nVendor error message: ");
836 sb.append(sqle.getMessage());
837
838 _log.debug(sb.toString());
839 }
840
841 throw sqle;
842 }
843
844 protected String readFile(String fileName) throws IOException {
845 if (FileUtil.exists(fileName)) {
846 return FileUtil.read(fileName);
847 }
848 else {
849 return StringPool.BLANK;
850 }
851 }
852
853 protected String readSQL(String fileName, String comments, String eol)
854 throws IOException {
855
856 if (!FileUtil.exists(fileName)) {
857 return StringPool.BLANK;
858 }
859
860 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
861 new FileReader(new File(fileName)));
862
863 StringBundler sb = new StringBundler();
864
865 String line = null;
866
867 while ((line = unsyncBufferedReader.readLine()) != null) {
868 if (!line.startsWith(comments)) {
869 line = StringUtil.replace(
870 line, new String[] {"\n", "\t"}, new String[] {"", ""});
871
872 if (line.endsWith(";")) {
873 sb.append(line.substring(0, line.length() - 1));
874 sb.append(eol);
875 }
876 else {
877 sb.append(line);
878 }
879 }
880 }
881
882 unsyncBufferedReader.close();
883
884 return sb.toString();
885 }
886
887 protected String removeBooleanIndexes(String sqlDir, String data)
888 throws IOException {
889
890 String portalData = readFile(sqlDir + "/portal-tables.sql");
891
892 if (Validator.isNull(portalData)) {
893 return StringPool.BLANK;
894 }
895
896 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
897 new UnsyncStringReader(data));
898
899 StringBundler sb = new StringBundler();
900
901 String line = null;
902
903 while ((line = unsyncBufferedReader.readLine()) != null) {
904 boolean append = true;
905
906 int x = line.indexOf(" on ");
907
908 if (x != -1) {
909 int y = line.indexOf(" (", x);
910
911 String table = line.substring(x + 4, y);
912
913 x = y + 2;
914 y = line.indexOf(")", x);
915
916 String[] columns = StringUtil.split(line.substring(x, y));
917
918 x = portalData.indexOf("create table " + table + " (");
919 y = portalData.indexOf(");", x);
920
921 String portalTableData = portalData.substring(x, y);
922
923 for (int i = 0; i < columns.length; i++) {
924 if (portalTableData.contains(
925 columns[i].trim() + " BOOLEAN")) {
926
927 append = false;
928
929 break;
930 }
931 }
932 }
933
934 if (append) {
935 sb.append(line);
936 sb.append("\n");
937 }
938 }
939
940 unsyncBufferedReader.close();
941
942 return sb.toString();
943 }
944
945 protected String removeInserts(String data) throws IOException {
946 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
947 new UnsyncStringReader(data));
948
949 StringBundler sb = new StringBundler();
950
951 String line = null;
952
953 while ((line = unsyncBufferedReader.readLine()) != null) {
954 if (!line.startsWith("insert into ") &&
955 !line.startsWith("update ")) {
956
957 sb.append(line);
958 sb.append("\n");
959 }
960 }
961
962 unsyncBufferedReader.close();
963
964 return sb.toString();
965 }
966
967 protected String removeLongInserts(String data) throws IOException {
968 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
969 new UnsyncStringReader(data));
970
971 StringBundler sb = new StringBundler();
972
973 String line = null;
974
975 while ((line = unsyncBufferedReader.readLine()) != null) {
976 if (!line.startsWith("insert into Image (") &&
977 !line.startsWith("insert into JournalArticle (") &&
978 !line.startsWith("insert into JournalStructure (") &&
979 !line.startsWith("insert into JournalTemplate (")) {
980
981 sb.append(line);
982 sb.append("\n");
983 }
984 }
985
986 unsyncBufferedReader.close();
987
988 return sb.toString();
989 }
990
991 protected String removeNull(String content) {
992 content = StringUtil.replace(content, " = null", " = NULL");
993 content = StringUtil.replace(content, " is null", " IS NULL");
994 content = StringUtil.replace(content, " not null", " not_null");
995 content = StringUtil.replace(content, " null", "");
996 content = StringUtil.replace(content, " not_null", " not null");
997
998 return content;
999 }
1000
1001 protected String replaceTemplate(String template, String[] actual) {
1002 if ((template == null) || (TEMPLATE == null) || (actual == null)) {
1003 return null;
1004 }
1005
1006 if (TEMPLATE.length != actual.length) {
1007 return template;
1008 }
1009
1010 StringBundler sb = null;
1011
1012 int endIndex = 0;
1013
1014 Matcher matcher = _templatePattern.matcher(template);
1015
1016 while (matcher.find()) {
1017 int startIndex = matcher.start();
1018
1019 if (sb == null) {
1020 sb = new StringBundler();
1021 }
1022
1023 sb.append(template.substring(endIndex, startIndex));
1024
1025 endIndex = matcher.end();
1026
1027 String matched = template.substring(startIndex, endIndex);
1028
1029 sb.append(_templateMap.get(matched));
1030 }
1031
1032 if (sb == null) {
1033 return template;
1034 }
1035
1036 if (template.length() > endIndex) {
1037 sb.append(template.substring(endIndex));
1038 }
1039
1040 return sb.toString();
1041 }
1042
1043 protected abstract String reword(String data) throws IOException;
1044
1045 protected static final String ALTER_COLUMN_NAME = "alter_column_name ";
1046
1047 protected static final String ALTER_COLUMN_TYPE = "alter_column_type ";
1048
1049 protected static final String ALTER_TABLE_NAME = "alter_table_name ";
1050
1051 protected static final String DROP_INDEX = "drop index";
1052
1053 protected static final String DROP_PRIMARY_KEY = "drop primary key";
1054
1055 protected static final String[] RENAME_TABLE_TEMPLATE = {
1056 "@old-table@", "@new-table@"
1057 };
1058
1059 protected static final String[] REWORD_TEMPLATE = {
1060 "@table@", "@old-column@", "@new-column@", "@type@", "@nullable@"
1061 };
1062
1063 protected static final String[] TEMPLATE = {
1064 "##", "TRUE", "FALSE", "'01/01/1970'", "CURRENT_TIMESTAMP", " BLOB",
1065 " SBLOB", " BOOLEAN", " DATE", " DOUBLE", " INTEGER", " LONG",
1066 " STRING", " TEXT", " VARCHAR", " IDENTITY", "COMMIT_TRANSACTION"
1067 };
1068
1069 private static final boolean _SUPPORTS_ALTER_COLUMN_NAME = true;
1070
1071 private static final boolean _SUPPORTS_ALTER_COLUMN_TYPE = true;
1072
1073 private static final boolean _SUPPORTS_DATE_MILLISECONDS = true;
1074
1075 private static final boolean _SUPPORTS_INLINE_DISTINCT = true;
1076
1077 private static final boolean _SUPPORTS_QUERYING_AFTER_EXCEPTION = true;
1078
1079 private static final boolean _SUPPORTS_SCROLLABLE_RESULTS = true;
1080
1081 private static final boolean _SUPPORTS_UPDATE_WITH_INNER_JOIN = true;
1082
1083 private static Log _log = LogFactoryUtil.getLog(BaseDB.class);
1084
1085 private static Pattern _templatePattern;
1086 private static Pattern _timestampPattern = Pattern.compile(
1087 "SPECIFIC_TIMESTAMP_\\d+");
1088
1089 private boolean _supportsStringCaseSensitiveQuery;
1090 private Map<String, String> _templateMap = new HashMap<String, String>();
1091 private String _type;
1092
1093 static {
1094 StringBundler sb = new StringBundler(TEMPLATE.length * 3 - 3);
1095
1096 for (int i = 0; i < TEMPLATE.length; i++) {
1097 String variable = TEMPLATE[i];
1098
1099 if (variable.equals("##") || variable.equals("'01/01/1970'")) {
1100 sb.append(variable);
1101 }
1102 else {
1103 sb.append(variable);
1104 sb.append("\\b");
1105 }
1106
1107 if (i < (TEMPLATE.length - 1)) {
1108 sb.append(StringPool.PIPE);
1109 }
1110 }
1111
1112 _templatePattern = Pattern.compile(sb.toString());
1113 }
1114
1115 }