View Javadoc

1   package liquibase.executor;
2   
3   import java.io.IOException;
4   import java.io.Writer;
5   import java.util.ArrayList;
6   import java.util.List;
7   import java.util.Map;
8   
9   import liquibase.database.Database;
10  import liquibase.database.core.MSSQLDatabase;
11  import liquibase.database.core.SybaseASADatabase;
12  import liquibase.database.core.SybaseDatabase;
13  import liquibase.exception.DatabaseException;
14  import liquibase.servicelocator.LiquibaseService;
15  import liquibase.sql.visitor.SqlVisitor;
16  import liquibase.sqlgenerator.SqlGeneratorFactory;
17  import liquibase.statement.CallableSqlStatement;
18  import liquibase.statement.SqlStatement;
19  import liquibase.statement.core.GetNextChangeSetSequenceValueStatement;
20  import liquibase.statement.core.LockDatabaseChangeLogStatement;
21  import liquibase.statement.core.RawSqlStatement;
22  import liquibase.statement.core.SelectFromDatabaseChangeLogLockStatement;
23  import liquibase.statement.core.UnlockDatabaseChangeLogStatement;
24  import liquibase.util.StreamUtil;
25  
26  @LiquibaseService(skip = true)
27  public class LoggingExecutor extends AbstractExecutor implements Executor {
28  
29      private Writer output;
30      private Executor delegatedReadExecutor;
31  
32      public LoggingExecutor(Executor delegatedExecutor, Writer output, Database database) {
33          this.output = output;
34          this.delegatedReadExecutor = delegatedExecutor;
35          setDatabase(database);
36      }
37  
38      @Override
39      public void execute(SqlStatement sql) throws DatabaseException {
40          outputStatement(sql);
41      }
42  
43      @Override
44      public int update(SqlStatement sql) throws DatabaseException {
45          if (sql instanceof LockDatabaseChangeLogStatement) {
46              return 1;
47          } else if (sql instanceof UnlockDatabaseChangeLogStatement) {
48              return 1;
49          }
50  
51          outputStatement(sql);
52  
53          return 0;
54      }
55  
56      @Override
57      public void execute(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
58          outputStatement(sql, sqlVisitors);
59      }
60  
61      @Override
62      public int update(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
63          outputStatement(sql, sqlVisitors);
64          return 0;
65      }
66  
67      @Override
68      public Map call(CallableSqlStatement csc, List declaredParameters, List<SqlVisitor> sqlVisitors)
69              throws DatabaseException {
70          throw new DatabaseException("Do not know how to output callable statement");
71      }
72  
73      @Override
74      public void comment(String message) throws DatabaseException {
75          try {
76              output.write(database.getLineComment());
77              output.write(" ");
78              output.write(message);
79              output.write(StreamUtil.getLineSeparator());
80          } catch (IOException e) {
81              throw new DatabaseException(e);
82          }
83      }
84  
85      private void outputStatement(SqlStatement sql) throws DatabaseException {
86          outputStatement(sql, new ArrayList<SqlVisitor>());
87      }
88  
89      private void outputStatement(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
90          try {
91              if (SqlGeneratorFactory.getInstance().requiresCurrentDatabaseMetadata(sql, database)) {
92                  throw new DatabaseException(sql.getClass().getSimpleName()
93                          + " requires access to up to date database metadata which is not available in SQL output mode");
94              }
95              for (String statement : applyVisitors(sql, sqlVisitors)) {
96                  if (statement == null) {
97                      continue;
98                  }
99                  output.write(statement);
100 
101                 if (database instanceof MSSQLDatabase || database instanceof SybaseDatabase
102                         || database instanceof SybaseASADatabase) {
103                     output.write(StreamUtil.getLineSeparator());
104                     output.write("GO");
105                     // } else if (database instanceof OracleDatabase) {
106                     // output.write(StreamUtil.getLineSeparator());
107                     // output.write("/");
108                 } else {
109                     String endDelimiter = ";";
110                     if (sql instanceof RawSqlStatement) {
111                         endDelimiter = ((RawSqlStatement) sql).getEndDelimiter();
112                     }
113                     if (!statement.endsWith(endDelimiter)) {
114                         output.write(endDelimiter);
115                     }
116                 }
117                 output.write(StreamUtil.getLineSeparator());
118                 output.write(StreamUtil.getLineSeparator());
119             }
120         } catch (IOException e) {
121             throw new DatabaseException(e);
122         }
123     }
124 
125     @Override
126     public Object queryForObject(SqlStatement sql, Class requiredType) throws DatabaseException {
127         if (sql instanceof SelectFromDatabaseChangeLogLockStatement) {
128             return false;
129         }
130         return delegatedReadExecutor.queryForObject(sql, requiredType);
131     }
132 
133     @Override
134     public Object queryForObject(SqlStatement sql, Class requiredType, List<SqlVisitor> sqlVisitors)
135             throws DatabaseException {
136         return delegatedReadExecutor.queryForObject(sql, requiredType, sqlVisitors);
137     }
138 
139     @Override
140     public long queryForLong(SqlStatement sql) throws DatabaseException {
141         return delegatedReadExecutor.queryForLong(sql);
142     }
143 
144     @Override
145     public long queryForLong(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
146         return delegatedReadExecutor.queryForLong(sql, sqlVisitors);
147     }
148 
149     @Override
150     public int queryForInt(SqlStatement sql) throws DatabaseException {
151         try {
152             return delegatedReadExecutor.queryForInt(sql);
153         } catch (DatabaseException e) {
154             if (sql instanceof GetNextChangeSetSequenceValueStatement) { // table probably does not exist
155                 return 0;
156             }
157             throw e;
158         }
159     }
160 
161     @Override
162     public int queryForInt(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
163         return delegatedReadExecutor.queryForInt(sql, sqlVisitors);
164     }
165 
166     @Override
167     public List queryForList(SqlStatement sql, Class elementType) throws DatabaseException {
168         return delegatedReadExecutor.queryForList(sql, elementType);
169     }
170 
171     @Override
172     public List queryForList(SqlStatement sql, Class elementType, List<SqlVisitor> sqlVisitors)
173             throws DatabaseException {
174         return delegatedReadExecutor.queryForList(sql, elementType, sqlVisitors);
175     }
176 
177     @Override
178     public List<Map> queryForList(SqlStatement sql) throws DatabaseException {
179         return delegatedReadExecutor.queryForList(sql);
180     }
181 
182     @Override
183     public List<Map> queryForList(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
184         return delegatedReadExecutor.queryForList(sql, sqlVisitors);
185     }
186 
187     @Override
188     public boolean updatesDatabase() {
189         return false;
190     }
191 }