001package ca.uhn.fhir.jpa.migrate.dao;
002
003/*-
004 * #%L
005 * HAPI FHIR Server - SQL Migration
006 * %%
007 * Copyright (C) 2014 - 2022 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}