Coverage Report - liquibase.sqlgenerator.core.InsertOrUpdateGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
InsertOrUpdateGenerator
75%
48/64
57%
15/26
2.667
 
 1  
 package liquibase.sqlgenerator.core;
 2  
 
 3  
 import java.util.Arrays;
 4  
 import liquibase.database.Database;
 5  
 import liquibase.database.typeconversion.TypeConverterFactory;
 6  
 import liquibase.exception.LiquibaseException;
 7  
 import liquibase.exception.ValidationErrors;
 8  
 import liquibase.sqlgenerator.SqlGeneratorChain;
 9  
 import liquibase.statement.core.InsertOrUpdateStatement;
 10  
 import liquibase.statement.core.UpdateStatement;
 11  
 import liquibase.sql.Sql;
 12  
 import liquibase.sql.UnparsedSql;
 13  
 
 14  
 import java.util.Date;
 15  
 import java.util.HashSet;
 16  
 
 17  55
 public abstract class InsertOrUpdateGenerator extends AbstractSqlGenerator<InsertOrUpdateStatement> {
 18  
 
 19  
     protected abstract String getRecordCheck(InsertOrUpdateStatement insertOrUpdateStatement, Database database,
 20  
             String whereClause);
 21  
 
 22  
     protected abstract String getElse(Database database);
 23  
 
 24  
     protected String getPostUpdateStatements() {
 25  0
         return "";
 26  
     }
 27  
 
 28  
     @Override
 29  
     public int getPriority() {
 30  5
         return PRIORITY_DATABASE;
 31  
     }
 32  
 
 33  
     public ValidationErrors validate(InsertOrUpdateStatement statement, Database database,
 34  
             SqlGeneratorChain sqlGeneratorChain) {
 35  0
         ValidationErrors validationErrors = new ValidationErrors();
 36  0
         validationErrors.checkRequiredField("tableName", statement.getTableName());
 37  0
         validationErrors.checkRequiredField("columns", statement.getColumnValues());
 38  0
         validationErrors.checkRequiredField("primaryKey", statement.getPrimaryKey());
 39  
 
 40  0
         return validationErrors;
 41  
     }
 42  
 
 43  
     protected String getWhereClause(InsertOrUpdateStatement insertOrUpdateStatement, Database database) {
 44  1
         StringBuffer where = new StringBuffer();
 45  
 
 46  1
         String[] pkColumns = insertOrUpdateStatement.getPrimaryKey().split(",");
 47  
 
 48  2
         for (String thisPkColumn : pkColumns) {
 49  1
             where.append(
 50  
                     database.escapeColumnName(insertOrUpdateStatement.getSchemaName(),
 51  
                             insertOrUpdateStatement.getTableName(), thisPkColumn)).append(" = ");
 52  1
             Object newValue = insertOrUpdateStatement.getColumnValues().get(thisPkColumn);
 53  1
             if (newValue == null || newValue.toString().equals("NULL")) {
 54  0
                 where.append("NULL");
 55  1
             } else if (newValue instanceof String && database.shouldQuoteValue(((String) newValue))) {
 56  1
                 where.append("'").append(database.escapeStringForDatabase((String) newValue)).append("'");
 57  0
             } else if (newValue instanceof Date) {
 58  0
                 where.append(database.getDateLiteral(((Date) newValue)));
 59  0
             } else if (newValue instanceof Boolean) {
 60  0
                 if (((Boolean) newValue)) {
 61  0
                     where.append(TypeConverterFactory.getInstance().findTypeConverter(database).getBooleanType()
 62  
                             .getTrueBooleanValue());
 63  
                 } else {
 64  0
                     where.append(TypeConverterFactory.getInstance().findTypeConverter(database).getBooleanType()
 65  
                             .getFalseBooleanValue());
 66  
                 }
 67  
             } else {
 68  0
                 where.append(newValue);
 69  
             }
 70  
 
 71  1
             where.append(" AND ");
 72  
         }
 73  
 
 74  1
         where.delete(where.lastIndexOf(" AND "), where.lastIndexOf(" AND ") + " AND ".length());
 75  1
         return where.toString();
 76  
     }
 77  
 
 78  
     protected String getInsertStatement(InsertOrUpdateStatement insertOrUpdateStatement, Database database,
 79  
             SqlGeneratorChain sqlGeneratorChain) {
 80  2
         StringBuffer insertBuffer = new StringBuffer();
 81  2
         InsertGenerator insert = new InsertGenerator();
 82  2
         Sql[] insertSql = insert.generateSql(insertOrUpdateStatement, database, sqlGeneratorChain);
 83  
 
 84  4
         for (Sql s : insertSql) {
 85  2
             insertBuffer.append(s.toSql());
 86  2
             insertBuffer.append(";");
 87  
         }
 88  
 
 89  2
         insertBuffer.append("\n");
 90  
 
 91  2
         return insertBuffer.toString();
 92  
     }
 93  
 
 94  
     /**
 95  
      * 
 96  
      * @param insertOrUpdateStatement
 97  
      * @param database
 98  
      * @param whereClause
 99  
      * @param sqlGeneratorChain
 100  
      * @return the update statement, if there is nothing to update return null
 101  
      */
 102  
     protected String getUpdateStatement(InsertOrUpdateStatement insertOrUpdateStatement, Database database,
 103  
             String whereClause, SqlGeneratorChain sqlGeneratorChain) throws LiquibaseException {
 104  
 
 105  2
         StringBuffer updateSqlString = new StringBuffer();
 106  
 
 107  2
         UpdateGenerator update = new UpdateGenerator();
 108  2
         UpdateStatement updateStatement = new UpdateStatement(insertOrUpdateStatement.getSchemaName(),
 109  
                 insertOrUpdateStatement.getTableName());
 110  2
         updateStatement.setWhereClause(whereClause + ";\n");
 111  
 
 112  2
         String[] pkFields = insertOrUpdateStatement.getPrimaryKey().split(",");
 113  2
         HashSet<String> hashPkFields = new HashSet<String>(Arrays.asList(pkFields));
 114  2
         for (String columnKey : insertOrUpdateStatement.getColumnValues().keySet()) {
 115  3
             if (!hashPkFields.contains(columnKey)) {
 116  2
                 updateStatement.addNewColumnValue(columnKey, insertOrUpdateStatement.getColumnValue(columnKey));
 117  
             }
 118  
         }
 119  
         // this isn't very elegant but the code fails above without any columns to update
 120  2
         if (updateStatement.getNewColumnValues().isEmpty()) {
 121  0
             throw new LiquibaseException("No fields to update in set clause");
 122  
         }
 123  
 
 124  2
         Sql[] updateSql = update.generateSql(updateStatement, database, sqlGeneratorChain);
 125  
 
 126  4
         for (Sql s : updateSql) {
 127  2
             updateSqlString.append(s.toSql());
 128  2
             updateSqlString.append(";");
 129  
         }
 130  
 
 131  2
         updateSqlString.deleteCharAt(updateSqlString.lastIndexOf(";"));
 132  2
         updateSqlString.append("\n");
 133  
 
 134  2
         return updateSqlString.toString();
 135  
 
 136  
     }
 137  
 
 138  
     public Sql[] generateSql(InsertOrUpdateStatement insertOrUpdateStatement, Database database,
 139  
             SqlGeneratorChain sqlGeneratorChain) {
 140  1
         StringBuffer completeSql = new StringBuffer();
 141  1
         String whereClause = getWhereClause(insertOrUpdateStatement, database);
 142  
 
 143  1
         completeSql.append(getRecordCheck(insertOrUpdateStatement, database, whereClause));
 144  
 
 145  1
         completeSql.append(getInsertStatement(insertOrUpdateStatement, database, sqlGeneratorChain));
 146  
 
 147  
         try {
 148  
 
 149  1
             String updateStatement = getUpdateStatement(insertOrUpdateStatement, database, whereClause,
 150  
                     sqlGeneratorChain);
 151  
 
 152  1
             completeSql.append(getElse(database));
 153  
 
 154  1
             completeSql.append(updateStatement);
 155  
 
 156  0
         } catch (LiquibaseException e) {
 157  1
         }
 158  
 
 159  1
         completeSql.append(getPostUpdateStatements());
 160  
 
 161  1
         return new Sql[] { new UnparsedSql(completeSql.toString()) };
 162  
     }
 163  
 }