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 = myTable.addColumn("\"description\"", Types.VARCHAR, HapiMigrationEntity.DESCRIPTION_MAX_SIZE); 078 myDescriptionCol.notNull(); 079 080 myTypeCol = myTable.addColumn("\"type\"", Types.VARCHAR, HapiMigrationEntity.TYPE_MAX_SIZE); 081 myTypeCol.notNull(); 082 083 myScriptCol = myTable.addColumn("\"script\"", Types.VARCHAR, HapiMigrationEntity.SCRIPT_MAX_SIZE); 084 myScriptCol.notNull(); 085 086 myChecksumCol = myTable.addColumn("\"checksum\"", Types.INTEGER, null); 087 088 myInstalledByCol = myTable.addColumn("\"installed_by\"", Types.VARCHAR, HapiMigrationEntity.INSTALLED_BY_MAX_SIZE); 089 myInstalledByCol.notNull(); 090 091 myInstalledOnCol = myTable.addColumn("\"installed_on\"", Types.DATE, null); 092 myInstalledOnCol.notNull(); 093 094 myExecutionTimeCol = myTable.addColumn("\"execution_time\"", Types.INTEGER, null); 095 myExecutionTimeCol.notNull(); 096 097 myBooleanType = ColumnTypeToDriverTypeToSqlType.getColumnTypeToDriverTypeToSqlType().get(ColumnTypeEnum.BOOLEAN).get(theDriverType); 098 mySuccessCol = myTable.addColumn("\"success\"", myBooleanType, null); 099 mySuccessCol.notNull(); 100 101 myDeleteAll = new DeleteQuery(myTable).toString(); 102 myHighestKeyQuery = buildHighestKeyQuery(); 103 } 104 105 public String deleteAll() { 106 return myDeleteAll; 107 } 108 109 public String getHighestKeyQuery() { 110 return myHighestKeyQuery; 111 } 112 113 private String buildHighestKeyQuery() { 114 return new SelectQuery() 115 .addCustomColumns(FunctionCall.max().addColumnParams(myInstalledRankCol)) 116 .validate() 117 .toString(); 118 } 119 120 public String insertPreparedStatement() { 121 return new InsertQuery(myTable) 122 .addPreparedColumns(myInstalledRankCol, 123 myVersionCol, 124 myDescriptionCol, 125 myTypeCol, 126 myScriptCol, 127 myChecksumCol, 128 myInstalledByCol, 129 myInstalledOnCol, 130 myExecutionTimeCol, 131 mySuccessCol) 132 .validate() 133 .toString(); 134 } 135 136 public String createTableStatement() { 137 return new CreateTableQuery(myTable, true) 138 .validate() 139 .toString(); 140 } 141 142 public String createIndexStatement() { 143 return new CreateIndexQuery(myTable, myMigrationTablename.toUpperCase() + "_PK_INDEX") 144 .setIndexType(CreateIndexQuery.IndexType.UNIQUE) 145 .addColumns(myInstalledRankCol) 146 .validate() 147 .toString(); 148 } 149 150 public String findAllQuery() { 151 return new SelectQuery() 152 .addFromTable(myTable) 153 .addCondition(BinaryCondition.notEqualTo(myInstalledRankCol, HapiMigrationEntity.CREATE_TABLE_PID)) 154 .addAllColumns() 155 .validate() 156 .toString(); 157 } 158 159 public String deleteLockRecordStatement(Integer theLockPid, String theLockDescription) { 160 return new DeleteQuery(myTable) 161 .addCondition(BinaryCondition.equalTo(myInstalledRankCol, theLockPid)) 162 .addCondition(BinaryCondition.equalTo(myDescriptionCol, theLockDescription)) 163 .validate() 164 .toString(); 165 } 166 167 public String findByPidAndNotDescriptionQuery(Integer theLockPid, String theLockDescription) { 168 return new SelectQuery() 169 .addFromTable(myTable) 170 .addCondition(BinaryCondition.equalTo(myInstalledRankCol, theLockPid)) 171 .addCondition(BinaryCondition.notEqualTo(myDescriptionCol, theLockDescription)) 172 .addAllColumns() 173 .validate() 174 .toString(); 175 } 176}