001package ca.uhn.fhir.jpa.migrate.dao; 002 003/*- 004 * #%L 005 * HAPI FHIR Server - SQL Migration 006 * %% 007 * Copyright (C) 2014 - 2023 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; 024import ca.uhn.fhir.jpa.migrate.entity.HapiMigrationEntity; 025import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum; 026import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeToDriverTypeToSqlType; 027import com.healthmarketscience.sqlbuilder.BinaryCondition; 028import com.healthmarketscience.sqlbuilder.CreateIndexQuery; 029import com.healthmarketscience.sqlbuilder.CreateTableQuery; 030import com.healthmarketscience.sqlbuilder.DeleteQuery; 031import com.healthmarketscience.sqlbuilder.FunctionCall; 032import com.healthmarketscience.sqlbuilder.InsertQuery; 033import com.healthmarketscience.sqlbuilder.SelectQuery; 034import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn; 035import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSchema; 036import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSpec; 037import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041import java.sql.Types; 042 043public class MigrationQueryBuilder { 044 private static final Logger ourLog = LoggerFactory.getLogger(MigrationQueryBuilder.class); 045 046 private final DbSpec mySpec; 047 private final DbSchema mySchema; 048 private final DbTable myTable; 049 private final DbColumn myVersionCol; 050 private final DbColumn myInstalledRankCol; 051 private final DbColumn myDescriptionCol; 052 private final DbColumn myTypeCol; 053 private final DbColumn myScriptCol; 054 private final DbColumn myChecksumCol; 055 private final DbColumn myInstalledByCol; 056 private final DbColumn myInstalledOnCol; 057 private final DbColumn myExecutionTimeCol; 058 private final DbColumn mySuccessCol; 059 private final String myDeleteAll; 060 private final String myHighestKeyQuery; 061 private final DriverTypeEnum myDriverType; 062 private final String myMigrationTablename; 063 private final String myBooleanType; 064 065 public MigrationQueryBuilder(DriverTypeEnum theDriverType, String theMigrationTablename) { 066 myDriverType = theDriverType; 067 myMigrationTablename = theMigrationTablename; 068 069 mySpec = new DbSpec(); 070 mySchema = mySpec.addDefaultSchema(); 071 myTable = mySchema.addTable("\"" + theMigrationTablename + "\""); 072 073 myInstalledRankCol = myTable.addColumn("\"installed_rank\"", Types.INTEGER, null); 074 myInstalledRankCol.notNull(); 075 076 myVersionCol = myTable.addColumn("\"version\"", Types.VARCHAR, HapiMigrationEntity.VERSION_MAX_SIZE); 077 078 myDescriptionCol = 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 = myTable.addColumn("\"installed_by\"", Types.VARCHAR, HapiMigrationEntity.INSTALLED_BY_MAX_SIZE); 090 myInstalledByCol.notNull(); 091 092 myInstalledOnCol = myTable.addColumn("\"installed_on\"", Types.DATE, null); 093 myInstalledOnCol.notNull(); 094 095 myExecutionTimeCol = myTable.addColumn("\"execution_time\"", Types.INTEGER, null); 096 myExecutionTimeCol.notNull(); 097 098 myBooleanType = ColumnTypeToDriverTypeToSqlType.getColumnTypeToDriverTypeToSqlType().get(ColumnTypeEnum.BOOLEAN).get(theDriverType); 099 mySuccessCol = myTable.addColumn("\"success\"", myBooleanType, null); 100 mySuccessCol.notNull(); 101 102 myDeleteAll = new DeleteQuery(myTable).toString(); 103 myHighestKeyQuery = buildHighestKeyQuery(); 104 } 105 106 public String deleteAll() { 107 return myDeleteAll; 108 } 109 110 public String getHighestKeyQuery() { 111 return myHighestKeyQuery; 112 } 113 114 private String buildHighestKeyQuery() { 115 return new SelectQuery() 116 .addCustomColumns(FunctionCall.max().addColumnParams(myInstalledRankCol)) 117 .validate() 118 .toString(); 119 } 120 121 public String insertPreparedStatement() { 122 return new InsertQuery(myTable) 123 .addPreparedColumns(myInstalledRankCol, 124 myVersionCol, 125 myDescriptionCol, 126 myTypeCol, 127 myScriptCol, 128 myChecksumCol, 129 myInstalledByCol, 130 myInstalledOnCol, 131 myExecutionTimeCol, 132 mySuccessCol) 133 .validate() 134 .toString(); 135 } 136 137 public String createTableStatement() { 138 return new CreateTableQuery(myTable, true) 139 .validate() 140 .toString(); 141 } 142 143 public String createIndexStatement() { 144 return new CreateIndexQuery(myTable, myMigrationTablename.toUpperCase() + "_PK_INDEX") 145 .setIndexType(CreateIndexQuery.IndexType.UNIQUE) 146 .addColumns(myInstalledRankCol) 147 .validate() 148 .toString(); 149 } 150 151 public String findAllQuery() { 152 return new SelectQuery() 153 .addFromTable(myTable) 154 .addCondition(BinaryCondition.notEqualTo(myInstalledRankCol, HapiMigrationEntity.CREATE_TABLE_PID)) 155 .addAllColumns() 156 .validate() 157 .toString(); 158 } 159 160 public String deleteLockRecordStatement(Integer theLockPid, String theLockDescription) { 161 return new DeleteQuery(myTable) 162 .addCondition(BinaryCondition.equalTo(myInstalledRankCol, theLockPid)) 163 .addCondition(BinaryCondition.equalTo(myDescriptionCol, theLockDescription)) 164 .validate() 165 .toString(); 166 } 167 168 public String findByPidAndNotDescriptionQuery(Integer theLockPid, String theLockDescription) { 169 return new SelectQuery() 170 .addFromTable(myTable) 171 .addCondition(BinaryCondition.equalTo(myInstalledRankCol, theLockPid)) 172 .addCondition(BinaryCondition.notEqualTo(myDescriptionCol, theLockDescription)) 173 .addAllColumns() 174 .validate() 175 .toString(); 176 } 177}