]> source.dussan.org Git - sonarqube.git/blob
833db36471f1a345fbc657361bf3f0a3493d6b2a
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2021 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
22 import java.sql.Connection;
23 import java.sql.PreparedStatement;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.util.Locale;
27 import java.util.Optional;
28 import org.sonar.db.Database;
29 import org.sonar.db.dialect.Dialect;
30 import org.sonar.db.dialect.H2;
31 import org.sonar.db.dialect.MsSql;
32 import org.sonar.db.dialect.Oracle;
33 import org.sonar.db.dialect.PostgreSql;
34
35 import static java.lang.String.format;
36
37 public class DbPrimaryKeyConstraintFinder {
38
39   private final Database db;
40
41   public DbPrimaryKeyConstraintFinder(Database db) {
42     this.db = db;
43   }
44
45   public String findConstraintName(String tableName) throws SQLException {
46     String constraintQuery = getDbVendorSpecificQuery(tableName);
47     return executeQuery(constraintQuery)
48       .orElseThrow(() -> constraintNotFoundException(tableName));
49   }
50
51   String getDbVendorSpecificQuery(String tableName) {
52     Dialect dialect = db.getDialect();
53     String constraintQuery;
54     switch (dialect.getId()) {
55       case PostgreSql.ID:
56         constraintQuery = getPostgresSqlConstraintQuery(tableName);
57         break;
58       case MsSql.ID:
59         constraintQuery = getMssqlConstraintQuery(tableName);
60         break;
61       case Oracle.ID:
62         constraintQuery = getOracleConstraintQuery(tableName);
63         break;
64       case H2.ID:
65         constraintQuery = getH2ConstraintQuery(tableName);
66         break;
67       default:
68         throw new IllegalStateException(format("Unsupported database '%s'", dialect.getId()));
69     }
70     return constraintQuery;
71   }
72
73   private Optional<String> executeQuery(String query) throws SQLException {
74     try (Connection connection = db.getDataSource().getConnection();
75       PreparedStatement pstmt = connection
76         .prepareStatement(query);
77       ResultSet rs = pstmt.executeQuery()) {
78       if (rs.next()) {
79         return Optional.ofNullable(rs.getString(1));
80       }
81       return Optional.empty();
82     }
83   }
84
85   private String getPostgresSqlConstraintQuery(String tableName) {
86     try (Connection connection = db.getDataSource().getConnection()) {
87       return format("SELECT conname " +
88         "FROM pg_constraint c " +
89         "JOIN pg_namespace n on c.connamespace = n.oid " +
90         "JOIN pg_class cls on c.conrelid = cls.oid " +
91         "WHERE cls.relname = '%s' AND n.nspname = '%s'", tableName, connection.getSchema());
92     } catch (SQLException throwables) {
93       throw new IllegalStateException("Can not get database connection");
94     }
95   }
96
97   private static String getMssqlConstraintQuery(String tableName) {
98     return format("SELECT name " +
99       "FROM sys.key_constraints " +
100       "WHERE type = 'PK' " +
101       "AND OBJECT_NAME(parent_object_id) = '%s'", tableName);
102   }
103
104   private static String getOracleConstraintQuery(String tableName) {
105     return format("SELECT constraint_name " +
106       "FROM user_constraints " +
107       "WHERE table_name = UPPER('%s') " +
108       "AND constraint_type='P'", tableName);
109   }
110
111   private static String getH2ConstraintQuery(String tableName) {
112     return format("SELECT constraint_name "
113       + "FROM information_schema.constraints "
114       + "WHERE table_name = '%s' and constraint_type = 'PRIMARY KEY'", tableName.toUpperCase(Locale.ENGLISH));
115   }
116
117   static IllegalStateException constraintNotFoundException(String tableName) {
118     return new IllegalStateException(format("Cannot find constraint for table '%s'", tableName));
119   }
120
121   // FIXME:: this method should be moved somewhere else
122   String getPostgresSqlSequence(String tableName, String columnName) throws SQLException {
123     try (Connection connection = db.getDataSource().getConnection();
124       PreparedStatement pstmt = connection.prepareStatement(format("SELECT pg_get_serial_sequence('%s', '%s')", tableName, columnName));
125       ResultSet rs = pstmt.executeQuery()) {
126       if (rs.next()) {
127         return rs.getString(1);
128       }
129       throw new IllegalStateException(format("Cannot find sequence for table '%s' on column '%s'", tableName, columnName));
130     }
131   }
132
133 }