001/*- 002 * #%L 003 * HAPI FHIR Server - SQL Migration 004 * %% 005 * Copyright (C) 2014 - 2025 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.migrate.taskdef; 021 022import ca.uhn.fhir.i18n.Msg; 023import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; 024 025/** 026 * Helper to extract database information about supported migrations. 027 */ 028public class MetadataSource { 029 030 /** 031 * Does this database support index operations without write-locking the table? 032 */ 033 public boolean isOnlineIndexSupported(DriverTypeEnum.ConnectionProperties theConnectionProperties) { 034 035 // todo: delete this once we figure out how run Oracle try-catch as well. 036 switch (theConnectionProperties.getDriverType()) { 037 case POSTGRES_9_4: 038 case COCKROACHDB_21_1: 039 return true; 040 case MSSQL_2012: 041 // use a deny-list instead of allow list, so we have a better failure mode for new/unknown versions. 042 // Better to fail in dev than run with a table lock in production. 043 String mssqlEdition = getEdition(theConnectionProperties); 044 return mssqlEdition == null // some weird version without an edition? 045 || 046 // these versions don't support ONLINE index creation 047 !mssqlEdition.startsWith("Standard Edition"); 048 case ORACLE_12C: 049 String oracleEdition = getEdition(theConnectionProperties); 050 return oracleEdition == null // weird unknown version - try, and maybe fail. 051 || oracleEdition.contains("Enterprise"); 052 default: 053 return false; 054 } 055 } 056 057 /** 058 * Get the MS Sql Server or Oracle Server edition. Other databases are not supported yet. 059 * 060 * @param theConnectionProperties the database to inspect 061 * @return the edition string (e.g. Standard, Enterprise, Developer, etc.) 062 */ 063 private String getEdition(DriverTypeEnum.ConnectionProperties theConnectionProperties) { 064 final String result; 065 if (theConnectionProperties.getDriverType() == DriverTypeEnum.MSSQL_2012) { 066 result = theConnectionProperties 067 .newJdbcTemplate() 068 .queryForObject("SELECT SERVERPROPERTY ('edition')", String.class); 069 } else if (theConnectionProperties.getDriverType() == DriverTypeEnum.ORACLE_12C) { 070 result = theConnectionProperties 071 .newJdbcTemplate() 072 .queryForObject("SELECT BANNER FROM v$version WHERE banner LIKE 'Oracle%'", String.class); 073 } else { 074 throw new UnsupportedOperationException(Msg.code(2084) + "We only know about MSSQL editions."); 075 } 076 return result; 077 } 078}