001/*
002 * Copyright 2002-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.test.context.jdbc;
018
019import java.lang.annotation.Documented;
020import java.lang.annotation.ElementType;
021import java.lang.annotation.Inherited;
022import java.lang.annotation.Retention;
023import java.lang.annotation.RetentionPolicy;
024import java.lang.annotation.Target;
025
026/**
027 * {@code @SqlConfig} defines metadata that is used to determine how to parse
028 * and execute SQL scripts configured via the {@link Sql @Sql} annotation.
029 *
030 * <h3>Configuration Scope</h3>
031 * <p>When declared as a class-level annotation on an integration test class,
032 * {@code @SqlConfig} serves as <strong><em>global</em></strong> configuration
033 * for all SQL scripts within the test class hierarchy. When declared directly
034 * via the {@link Sql#config config} attribute of the {@code @Sql} annotation,
035 * {@code @SqlConfig} serves as <strong><em>local</em></strong> configuration
036 * for the SQL scripts declared within the enclosing {@code @Sql} annotation.
037 *
038 * <h3>Default Values</h3>
039 * <p>Every attribute in {@code @SqlConfig} has an <em>implicit</em> default value
040 * which is documented in the javadocs of the corresponding attribute. Due to the
041 * rules defined for annotation attributes in the Java Language Specification, it
042 * is unfortunately not possible to assign a value of {@code null} to an annotation
043 * attribute. Thus, in order to support overrides of <em>inherited</em> global
044 * configuration, {@code @SqlConfig} attributes have an <em>explicit</em>
045 * {@code default} value of either {@code ""} for Strings, <code>{}</code> for
046 * arrays, or {@code DEFAULT} for Enums. This approach allows local declarations
047 * of {@code @SqlConfig} to selectively override individual attributes from global
048 * declarations of {@code @SqlConfig} by providing a value other than {@code ""},
049 * <code>{}</code>, or {@code DEFAULT}.
050 *
051 * <h3>Inheritance and Overrides</h3>
052 * <p>Global {@code @SqlConfig} attributes are <em>inherited</em> whenever local
053 * {@code @SqlConfig} attributes do not supply an explicit value other than
054 * {@code ""}, <code>{}</code>, or {@code DEFAULT}. Explicit local configuration
055 * therefore <em>overrides</em> global configuration.
056 *
057 * @author Sam Brannen
058 * @author Tadaya Tsuyukubo
059 * @since 4.1
060 * @see Sql
061 */
062@Target(ElementType.TYPE)
063@Retention(RetentionPolicy.RUNTIME)
064@Documented
065@Inherited
066public @interface SqlConfig {
067
068        /**
069         * The bean name of the {@link javax.sql.DataSource} against which the
070         * scripts should be executed.
071         * <p>The name is only required if there is more than one bean of type
072         * {@code DataSource} in the test's {@code ApplicationContext}. If there
073         * is only one such bean, it is not necessary to specify a bean name.
074         * <p>Defaults to an empty string, requiring that one of the following is
075         * true:
076         * <ol>
077         * <li>An explicit bean name is defined in a global declaration of
078         * {@code @SqlConfig}.
079         * <li>The data source can be retrieved from the transaction manager
080         * by using reflection to invoke a public method named
081         * {@code getDataSource()} on the transaction manager.
082         * <li>There is only one bean of type {@code DataSource} in the test's
083         * {@code ApplicationContext}.</li>
084         * <li>The {@code DataSource} to use is named {@code "dataSource"}.</li>
085         * </ol>
086         * @see org.springframework.test.context.transaction.TestContextTransactionUtils#retrieveDataSource
087         */
088        String dataSource() default "";
089
090        /**
091         * The bean name of the {@link org.springframework.transaction.PlatformTransactionManager
092         * PlatformTransactionManager} that should be used to drive transactions.
093         * <p>The name is only used if there is more than one bean of type
094         * {@code PlatformTransactionManager} in the test's {@code ApplicationContext}.
095         * If there is only one such bean, it is not necessary to specify a bean name.
096         * <p>Defaults to an empty string, requiring that one of the following is
097         * true:
098         * <ol>
099         * <li>An explicit bean name is defined in a global declaration of
100         * {@code @SqlConfig}.
101         * <li>There is only one bean of type {@code PlatformTransactionManager} in
102         * the test's {@code ApplicationContext}.</li>
103         * <li>{@link org.springframework.transaction.annotation.TransactionManagementConfigurer
104         * TransactionManagementConfigurer} has been implemented to specify which
105         * {@code PlatformTransactionManager} bean should be used for annotation-driven
106         * transaction management.</li>
107         * <li>The {@code PlatformTransactionManager} to use is named
108         * {@code "transactionManager"}.</li>
109         * </ol>
110         * @see org.springframework.test.context.transaction.TestContextTransactionUtils#retrieveTransactionManager
111         */
112        String transactionManager() default "";
113
114        /**
115         * The <em>mode</em> to use when determining whether SQL scripts should be
116         * executed within a transaction.
117         * <p>Defaults to {@link TransactionMode#DEFAULT DEFAULT}.
118         * <p>Can be set to {@link TransactionMode#ISOLATED} to ensure that the SQL
119         * scripts are executed in a new, isolated transaction that will be immediately
120         * committed.
121         * @see TransactionMode
122         */
123        TransactionMode transactionMode() default TransactionMode.DEFAULT;
124
125        /**
126         * The encoding for the supplied SQL scripts, if different from the platform
127         * encoding.
128         * <p>An empty string denotes that the platform encoding should be used.
129         */
130        String encoding() default "";
131
132        /**
133         * The character string used to separate individual statements within the
134         * SQL scripts.
135         * <p>Implicitly defaults to {@code ";"} if not specified and falls back to
136         * {@code "\n"} as a last resort.
137         * <p>May be set to
138         * {@link org.springframework.jdbc.datasource.init.ScriptUtils#EOF_STATEMENT_SEPARATOR}
139         * to signal that each script contains a single statement without a
140         * separator.
141         * @see org.springframework.jdbc.datasource.init.ScriptUtils#DEFAULT_STATEMENT_SEPARATOR
142         * @see org.springframework.jdbc.datasource.init.ScriptUtils#EOF_STATEMENT_SEPARATOR
143         */
144        String separator() default "";
145
146        /**
147         * The prefix that identifies single-line comments within the SQL scripts.
148         * <p>Implicitly defaults to {@code "--"}.
149         * <p>This attribute may <strong>not</strong> be used in conjunction with
150         * {@link #commentPrefixes commentPrefixes}, but it may be used instead of
151         * {@link #commentPrefixes commentPrefixes}.
152         * @see org.springframework.jdbc.datasource.init.ScriptUtils#DEFAULT_COMMENT_PREFIX
153         * @see #commentPrefixes
154         */
155        String commentPrefix() default "";
156
157        /**
158         * The prefixes that identify single-line comments within the SQL scripts.
159         * <p>Implicitly defaults to {@code ["--"]}.
160         * <p>This attribute may <strong>not</strong> be used in conjunction with
161         * {@link #commentPrefix commentPrefix}, but it may be used instead of
162         * {@link #commentPrefix commentPrefix}.
163         * @see org.springframework.jdbc.datasource.init.ScriptUtils#DEFAULT_COMMENT_PREFIXES
164         * @see #commentPrefix
165         * @since 5.2
166         */
167        String[] commentPrefixes() default {};
168
169        /**
170         * The start delimiter that identifies block comments within the SQL scripts.
171         * <p>Implicitly defaults to {@code "/*"}.
172         * @see #blockCommentEndDelimiter
173         * @see org.springframework.jdbc.datasource.init.ScriptUtils#DEFAULT_BLOCK_COMMENT_START_DELIMITER
174         */
175        String blockCommentStartDelimiter() default "";
176
177        /**
178         * The end delimiter that identifies block comments within the SQL scripts.
179         * <p>Implicitly defaults to <code>"*&#47;"</code>.
180         * @see #blockCommentStartDelimiter
181         * @see org.springframework.jdbc.datasource.init.ScriptUtils#DEFAULT_BLOCK_COMMENT_END_DELIMITER
182         */
183        String blockCommentEndDelimiter() default "";
184
185        /**
186         * The <em>mode</em> to use when an error is encountered while executing an
187         * SQL statement.
188         * <p>Defaults to {@link ErrorMode#DEFAULT DEFAULT}.
189         * @see ErrorMode
190         */
191        ErrorMode errorMode() default ErrorMode.DEFAULT;
192
193
194        /**
195         * Enumeration of <em>modes</em> that dictate whether SQL scripts should be
196         * executed within a transaction and what the transaction propagation behavior
197         * should be.
198         */
199        enum TransactionMode {
200
201                /**
202                 * Indicates that the <em>default</em> transaction mode should be used.
203                 * <p>The meaning of <em>default</em> depends on the context in which
204                 * {@code @SqlConfig} is declared:
205                 * <ul>
206                 * <li>If {@code @SqlConfig} is declared <strong>only</strong> locally,
207                 * the default transaction mode is {@link #INFERRED}.</li>
208                 * <li>If {@code @SqlConfig} is declared globally, the default transaction
209                 * mode is {@link #INFERRED}.</li>
210                 * <li>If {@code @SqlConfig} is declared globally <strong>and</strong>
211                 * locally, the default transaction mode for the local declaration is
212                 * inherited from the global declaration.</li>
213                 * </ul>
214                 */
215                DEFAULT,
216
217                /**
218                 * Indicates that the transaction mode to use when executing SQL
219                 * scripts should be <em>inferred</em> using the rules listed below.
220                 * In the context of these rules, the term "<em>available</em>"
221                 * means that the bean for the data source or transaction manager
222                 * is either explicitly specified via a corresponding annotation
223                 * attribute in {@code @SqlConfig} or discoverable via conventions. See
224                 * {@link org.springframework.test.context.transaction.TestContextTransactionUtils TestContextTransactionUtils}
225                 * for details on the conventions used to discover such beans in
226                 * the {@code ApplicationContext}.
227                 *
228                 * <h4>Inference Rules</h4>
229                 * <ol>
230                 * <li>If neither a transaction manager nor a data source is
231                 * available, an exception will be thrown.
232                 * <li>If a transaction manager is not available but a data source
233                 * is available, SQL scripts will be executed directly against the
234                 * data source without a transaction.
235                 * <li>If a transaction manager is available:
236                 * <ul>
237                 * <li>If a data source is not available, an attempt will be made
238                 * to retrieve it from the transaction manager by using reflection
239                 * to invoke a public method named {@code getDataSource()} on the
240                 * transaction manager. If the attempt fails, an exception will be
241                 * thrown.
242                 * <li>Using the resolved transaction manager and data source, SQL
243                 * scripts will be executed within an existing transaction if
244                 * present; otherwise, scripts will be executed in a new transaction
245                 * that will be immediately committed. An <em>existing</em>
246                 * transaction will typically be managed by the
247                 * {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener TransactionalTestExecutionListener}.
248                 * </ul>
249                 * </ol>
250                 * @see #ISOLATED
251                 * @see org.springframework.test.context.transaction.TestContextTransactionUtils#retrieveDataSource
252                 * @see org.springframework.test.context.transaction.TestContextTransactionUtils#retrieveTransactionManager
253                 */
254                INFERRED,
255
256                /**
257                 * Indicates that SQL scripts should always be executed in a new,
258                 * <em>isolated</em> transaction that will be immediately committed.
259                 * <p>In contrast to {@link #INFERRED}, this mode requires the
260                 * presence of a transaction manager <strong>and</strong> a data
261                 * source.
262                 */
263                ISOLATED
264        }
265
266
267        /**
268         * Enumeration of <em>modes</em> that dictate how errors are handled while
269         * executing SQL statements.
270         */
271        enum ErrorMode {
272
273                /**
274                 * Indicates that the <em>default</em> error mode should be used.
275                 * <p>The meaning of <em>default</em> depends on the context in which
276                 * {@code @SqlConfig} is declared:
277                 * <ul>
278                 * <li>If {@code @SqlConfig} is declared <strong>only</strong> locally,
279                 * the default error mode is {@link #FAIL_ON_ERROR}.</li>
280                 * <li>If {@code @SqlConfig} is declared globally, the default error
281                 * mode is {@link #FAIL_ON_ERROR}.</li>
282                 * <li>If {@code @SqlConfig} is declared globally <strong>and</strong>
283                 * locally, the default error mode for the local declaration is
284                 * inherited from the global declaration.</li>
285                 * </rceLineNo">286                 */
287                DEFAULT,
288
289                /**
290                 * Indicates that script execution will fail if an error is encountered.
291                 * In other words, no errors should be ignored.
292                 * <p>This is effectively the default error mode so that if a script
293                 * is accidentally executed, it will fail fast if any SQL statement in
294                 * the script results in an error.
295                 * @see #CONTINUE_ON_ERROR
296                 */
297                FAIL_ON_ERROR,
298
299                /**
300                 * Indicates that all errors in SQL scripts should be logged but not
301                 * propagated as exceptions.
302                 * <p>{@code CONTINUE_ON_ERROR} is the logical <em>opposite</em> of
303                 * {@code FAIL_ON_ERROR} and a <em>superset</em> of {@code IGNORE_FAILED_DROPS}.
304                 * @see #FAIL_ON_ERROR
305                 * @see #IGNORE_FAILED_DROPS
306                 */
307                CONTINUE_ON_ERROR,
308
309                /**
310                 * Indicates that failed SQL {@code DROP} statements can be ignored.
311                 * <p>This is useful for a non-embedded database whose SQL dialect does
312                 * not support an {@code IF EXISTS} clause in a {@code DROP} statement.
313                 * @see #CONTINUE_ON_ERROR
314                 */
315                IGNORE_FAILED_DROPS
316        }
317
318}