選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

DbPrimaryKeyConstraintFinder.java 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.server.platform.db.migration.sql;
  21. import java.sql.Connection;
  22. import java.sql.PreparedStatement;
  23. import java.sql.ResultSet;
  24. import java.sql.SQLException;
  25. import java.util.Locale;
  26. import java.util.function.Supplier;
  27. import org.sonar.db.Database;
  28. import org.sonar.db.dialect.Dialect;
  29. import org.sonar.db.dialect.H2;
  30. import org.sonar.db.dialect.MsSql;
  31. import org.sonar.db.dialect.Oracle;
  32. import org.sonar.db.dialect.PostgreSql;
  33. import static java.lang.String.format;
  34. public class DbPrimaryKeyConstraintFinder {
  35. private final Database db;
  36. public DbPrimaryKeyConstraintFinder(Database db) {
  37. this.db = db;
  38. }
  39. public String findConstraintName(String tableName) throws SQLException {
  40. String constraintQuery = getDbVendorSpecificQuery(tableName);
  41. return executeQuery(constraintQuery, () -> constraintNotFoundException(tableName));
  42. }
  43. String getDbVendorSpecificQuery(String tableName) {
  44. Dialect dialect = db.getDialect();
  45. String constraintQuery;
  46. switch (dialect.getId()) {
  47. case PostgreSql.ID:
  48. constraintQuery = getPostgresSqlConstraintQuery(tableName);
  49. break;
  50. case MsSql.ID:
  51. constraintQuery = getMssqlConstraintQuery(tableName);
  52. break;
  53. case Oracle.ID:
  54. constraintQuery = getOracleConstraintQuery(tableName);
  55. break;
  56. case H2.ID:
  57. constraintQuery = getH2ConstraintQuery(tableName);
  58. break;
  59. default:
  60. throw new IllegalStateException(format("Unsupported database '%s'", dialect.getId()));
  61. }
  62. return constraintQuery;
  63. }
  64. private String executeQuery(String query, Supplier<? extends RuntimeException> exceptionSupplier) throws SQLException {
  65. try (Connection connection = db.getDataSource().getConnection();
  66. PreparedStatement pstmt = connection
  67. .prepareStatement(query);
  68. ResultSet rs = pstmt.executeQuery()) {
  69. if (rs.next()) {
  70. return rs.getString(1);
  71. }
  72. throw exceptionSupplier.get();
  73. }
  74. }
  75. private static String getPostgresSqlConstraintQuery(String tableName) {
  76. return format("SELECT conname " +
  77. "FROM pg_constraint " +
  78. "WHERE conrelid = " +
  79. " (SELECT oid " +
  80. " FROM pg_class " +
  81. " WHERE relname LIKE '%s')", tableName);
  82. }
  83. private static String getMssqlConstraintQuery(String tableName) {
  84. return format("SELECT name " +
  85. "FROM sys.key_constraints " +
  86. "WHERE type = 'PK' " +
  87. "AND OBJECT_NAME(parent_object_id) = '%s'", tableName);
  88. }
  89. private static String getOracleConstraintQuery(String tableName) {
  90. return format("SELECT constraint_name " +
  91. "FROM user_constraints " +
  92. "WHERE table_name = UPPER('%s') " +
  93. "AND constraint_type='P'", tableName);
  94. }
  95. private static String getH2ConstraintQuery(String tableName) {
  96. return format("SELECT constraint_name "
  97. + "FROM information_schema.constraints "
  98. + "WHERE table_name = '%s' and constraint_type = 'PRIMARY KEY'", tableName.toUpperCase(Locale.ENGLISH));
  99. }
  100. static IllegalStateException constraintNotFoundException(String tableName) {
  101. return new IllegalStateException(format("Cannot find constraint for table '%s'", tableName));
  102. }
  103. // FIXME:: this method should be moved somewhere else
  104. String getPostgresSqlSequence(String tableName, String columnName) throws SQLException {
  105. return executeQuery(format("SELECT pg_get_serial_sequence('%s', '%s')", tableName, columnName),
  106. () -> new IllegalStateException(format("Cannot find sequence for table '%s' on column '%s'", tableName, columnName)));
  107. }
  108. }