001/*- 002 * #%L 003 * HAPI FHIR Server - SQL Migration 004 * %% 005 * Copyright (C) 2014 - 2023 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.dao; 021 022import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; 023import ca.uhn.fhir.jpa.migrate.entity.HapiMigrationEntity; 024import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum; 025import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeToDriverTypeToSqlType; 026import com.healthmarketscience.sqlbuilder.BinaryCondition; 027import com.healthmarketscience.sqlbuilder.CreateIndexQuery; 028import com.healthmarketscience.sqlbuilder.CreateTableQuery; 029import com.healthmarketscience.sqlbuilder.DeleteQuery; 030import com.healthmarketscience.sqlbuilder.FunctionCall; 031import com.healthmarketscience.sqlbuilder.InsertQuery; 032import com.healthmarketscience.sqlbuilder.SelectQuery; 033import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn; 034import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSchema; 035import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSpec; 036import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040import java.sql.Types; 041 042public class MigrationQueryBuilder { 043 private static final Logger ourLog = LoggerFactory.getLogger(MigrationQueryBuilder.class); 044 045 private final DbSpec mySpec; 046 private final DbSchema mySchema; 047 private final DbTable myTable; 048 private final DbColumn myVersionCol; 049 private final DbColumn myInstalledRankCol; 050 private final DbColumn myDescriptionCol; 051 private final DbColumn myTypeCol; 052 private final DbColumn myScriptCol; 053 private final DbColumn myChecksumCol; 054 private final DbColumn myInstalledByCol; 055 private final DbColumn myInstalledOnCol; 056 private final DbColumn myExecutionTimeCol; 057 private final DbColumn mySuccessCol; 058 private final String myDeleteAll; 059 private final String myHighestKeyQuery; 060 private final DriverTypeEnum myDriverType; 061 private final String myMigrationTablename; 062 private final String myBooleanType; 063 064 public MigrationQueryBuilder(DriverTypeEnum theDriverType, String theMigrationTablename) { 065 myDriverType = theDriverType; 066 myMigrationTablename = theMigrationTablename; 067 068 mySpec = new DbSpec(); 069 mySchema = mySpec.addDefaultSchema(); 070 myTable = mySchema.addTable("\"" + theMigrationTablename + "\""); 071 072 myInstalledRankCol = myTable.addColumn("\"installed_rank\"", Types.INTEGER, null); 073 myInstalledRankCol.notNull(); 074 075 myVersionCol = myTable.addColumn("\"version\"", Types.VARCHAR, HapiMigrationEntity.VERSION_MAX_SIZE); 076 077 myDescriptionCol = 078 myTable.addColumn("\"description\"", Types.VARCHAR, HapiMigrationEntity.DESCRIPTION_MAX_SIZE); 079 myDescriptionCol.notNull(); 080 081 myTypeCol = myTable.addColumn("\"type\"", Types.VARCHAR, HapiMigrationEntity.TYPE_MAX_SIZE); 082 myTypeCol.notNull(); 083 084 myScriptCol = myTable.addColumn("\"script\"", Types.VARCHAR, HapiMigrationEntity.SCRIPT_MAX_SIZE); 085 myScriptCol.notNull(); 086 087 myChecksumCol = myTable.addColumn("\"checksum\"", Types.INTEGER, null); 088 089 myInstalledByCol = 090 myTable.addColumn("\"installed_by\"", Types.VARCHAR, HapiMigrationEntity.INSTALLED_BY_MAX_SIZE); 091 myInstalledByCol.notNull(); 092 093 myInstalledOnCol = myTable.addColumn("\"installed_on\"", Types.DATE, null); 094 myInstalledOnCol.notNull(); 095 096 myExecutionTimeCol = myTable.addColumn("\"execution_time\"", Types.INTEGER, null); 097 myExecutionTimeCol.notNull(); 098 099 myBooleanType = ColumnTypeToDriverTypeToSqlType.getColumnTypeToDriverTypeToSqlType() 100 .get(ColumnTypeEnum.BOOLEAN) 101 .get(theDriverType); 102 mySuccessCol = myTable.addColumn("\"success\"", myBooleanType, null); 103 mySuccessCol.notNull(); 104 105 myDeleteAll = new DeleteQuery(myTable).toString(); 106 myHighestKeyQuery = buildHighestKeyQuery(); 107 } 108 109 public String deleteAll() { 110 return myDeleteAll; 111 } 112 113 public String getHighestKeyQuery() { 114 return myHighestKeyQuery; 115 } 116 117 private String buildHighestKeyQuery() { 118 return new SelectQuery() 119 .addCustomColumns(FunctionCall.max().addColumnParams(myInstalledRankCol)) 120 .validate() 121 .toString(); 122 } 123 124 public String insertPreparedStatement() { 125 return new InsertQuery(myTable) 126 .addPreparedColumns( 127 myInstalledRankCol, 128 myVersionCol, 129 myDescriptionCol, 130 myTypeCol, 131 myScriptCol, 132 myChecksumCol, 133 myInstalledByCol, 134 myInstalledOnCol, 135 myExecutionTimeCol, 136 mySuccessCol) 137 .validate() 138 .toString(); 139 } 140 141 public String createTableStatement() { 142 return new CreateTableQuery(myTable, true).validate().toString(); 143 } 144 145 public String createIndexStatement() { 146 return new CreateIndexQuery(myTable, myMigrationTablename.toUpperCase() + "_PK_INDEX") 147 .setIndexType(CreateIndexQuery.IndexType.UNIQUE) 148 .addColumns(myInstalledRankCol) 149 .validate() 150 .toString(); 151 } 152 153 public String findAllQuery() { 154 return new SelectQuery() 155 .addFromTable(myTable) 156 .addCondition(BinaryCondition.notEqualTo(myInstalledRankCol, HapiMigrationEntity.CREATE_TABLE_PID)) 157 .addAllColumns() 158 .validate() 159 .toString(); 160 } 161 162 public String deleteLockRecordStatement(Integer theLockPid, String theLockDescription) { 163 return new DeleteQuery(myTable) 164 .addCondition(BinaryCondition.equalTo(myInstalledRankCol, theLockPid)) 165 .addCondition(BinaryCondition.equalTo(myDescriptionCol, theLockDescription)) 166 .validate() 167 .toString(); 168 } 169 170 public String findByPidAndNotDescriptionQuery(Integer theLockPid, String theLockDescription) { 171 return new SelectQuery() 172 .addFromTable(myTable) 173 .addCondition(BinaryCondition.equalTo(myInstalledRankCol, theLockPid)) 174 .addCondition(BinaryCondition.notEqualTo(myDescriptionCol, theLockDescription)) 175 .addAllColumns() 176 .validate() 177 .toString(); 178 } 179}