├── .gitignore
├── .gitreview
├── CHANGES
├── HACKING
├── LICENSE
├── README
├── README.md
├── build.sbt
├── project
├── build.properties
└── plugins.sbt
└── src
├── main
└── scala
│ └── com
│ └── imageworks
│ └── migration
│ ├── CharacterSetName.scala
│ ├── ColumnDefinition.scala
│ ├── CommitBehavior.scala
│ ├── ConnectionBuilder.scala
│ ├── DatabaseAdapter.scala
│ ├── DerbyDatabaseAdapter.scala
│ ├── ForeignKeyConstraintAction.scala
│ ├── JavaDatabaseAdapter.scala
│ ├── JavaMigrator.scala
│ ├── Migration.scala
│ ├── MigrationDirection.scala
│ ├── MigrationException.scala
│ ├── MigrationStatuses.scala
│ ├── Migrator.scala
│ ├── MigratorOperation.scala
│ ├── MysqlDatabaseAdapter.scala
│ ├── Options.scala
│ ├── OracleDatabaseAdapter.scala
│ ├── PostgresqlDatabaseAdapter.scala
│ ├── RichConnection.scala
│ ├── SqlType.scala
│ ├── TableColumnDefinition.scala
│ ├── TableDefinition.scala
│ ├── UnquotedNameConverter.scala
│ ├── User.scala
│ ├── Vendor.scala
│ └── With.scala
└── test
├── resources
└── log4j.properties
└── scala
└── com
└── imageworks
└── migration
└── tests
├── DatabaseAdapterTests.scala
├── JavaMigratorTests.scala
├── MigrationTests.scala
├── OptionsTests.scala
├── TestDatabase.scala
├── VendorTests.scala
├── WithTests.scala
├── alter_column
├── Migrate_20110214054347_CreateTable.scala
└── Migrate_20110214060042_AlterColumn.scala
├── auto_increment
└── Migrate_20121226170550_CreateTableWithAutoIncrementingColumn.scala
├── duplicate_descriptions
├── Migrate_20081118191214_FooBar.scala
└── Migrate_20081118191215_FooBar.scala
├── duplicate_versions
├── Migrate_20081118191214_Bar.scala
└── Migrate_20081118191214_Foo.scala
├── grant_and_revoke
├── Migrate_200811241940_CreateUser.scala
├── Migrate_200811261513_Grants.scala
└── Migrate_20121013072344_EmptyPrivilegeList.scala
├── no_migrations
└── Stamp.scala
├── scale_without_precision
└── Migrate_200812041647_Foo.scala
├── types
└── Migrate_20081212213908_CreateTypetestTable.scala
├── up_and_down
├── Migrate_20081118201000_CreateLocationTable.scala
└── Migrate_20081118201742_CreatePeopleTable.scala
└── vendor
└── Migrate_20121104011043_CheckVendor.scala
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .idea_modules/
3 | target/
4 |
--------------------------------------------------------------------------------
/.gitreview:
--------------------------------------------------------------------------------
1 | [gerrit]
2 | host=gerrit.orcaware.com
3 | port=29418
4 | project=scala-migrations.git
5 | defaultbranch=master
6 | defaultremote=origin
7 |
--------------------------------------------------------------------------------
/CHANGES:
--------------------------------------------------------------------------------
1 | Version 1.1.1 - January 1st, 2013
2 |
3 | * Use slf4j-api as a library dependency and slf4j-log4j12 as a unit
4 | testing dependency. Using slf4j-log4j12 as a library dependency
5 | required that dependent libraries and applications load
6 | slf4j-log4j12 which defeats the purpose of SLF4J. Closes
7 | https://github.com/blair/scala-migrations/issues/1 .
8 |
9 | * Enable unit testing on PostgreSQL when the Java
10 | "scala-migrations.db.vendor" property is set to "postgresql".
11 |
12 | Patches by Alan LaMielle.
13 |
14 | Version 1.1.0 - December 28th, 2012
15 | * Migration adds #databaseVendor to get the database vendor which
16 | can be used for pattern matching for database specific code.
17 |
18 | * Add an AutoIncrement column option which is supported on Derby,
19 | MySQL and PostgreSQL for the SMALLINT, INTEGER and BIGINT column
20 | data types. It instructs the database to provide an
21 | auto-incrementing default value if the application does not
22 | provide one when inserting a new row to the table.
23 |
24 | Derby:
25 | Only supported on SMALLINT, INT and BIGINT data types using
26 | Derby's GENERATED BY DEFAULT AS IDENTITY. The alternate setting
27 | GENERATED ALWAYS AS IDENTITY is not used as it is not consistent
28 | with MySQL and PostgreSQL which permits the application to
29 | explicitly specify the column's value.
30 |
31 | http://db.apache.org/derby/docs/10.9/ref/rrefsqlj37836.html
32 |
33 | MySQL:
34 | Only supported on SMALLINT, INT and BIGINT data types using
35 | MySQL's AUTO_INCREMENT keyword.
36 |
37 | http://dev.mysql.com/doc/refman/5.5/en/create-table.html
38 | http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html
39 |
40 | PostgreSQL:
41 | Only supported on SMALLINT, INT and BIGINT data types by
42 | replacing the data type name with SMALLSERIAL, SERIAL and
43 | BIGSERIAL, respectively. Support for SMALLSERIAL is only
44 | available in PostgreSQL 9.2 and greater.
45 |
46 | http://www.postgresql.org/docs/9.2/static/datatype-numeric.html#DATATYPE-SERIAL
47 |
48 | Oracle:
49 | No support is provided in this commit as it appears that
50 | equivalent functionality can only be provided by using triggers.
51 |
52 | * Add support for MySQL:
53 | - MySQL database adapter used if the JDBC driver class is named
54 | com.mysql.jdbc.Driver.
55 | - For grant and revoke operations, generalize the concept of a
56 | user to support MySQL style accounts, e.g. `username`@`hostname`.
57 |
58 | An abstract User base class with two concrete subclasses,
59 | PlainUser and MysqlUser, was added. String usernames,
60 | e.g. "foobar", used on MySQL are converted to the same user from
61 | localhost, e.g. `foobar`@`localhost`, as this is the most secure
62 | default. If database specific usernames are required, pattern
63 | match on the database vendor:
64 |
65 | def up() {
66 | val user = databaseVendor match {
67 | case Mysql => MysqlUser("foobar", "%")
68 | case _ => PlainUser("foobar")
69 | }
70 | ...
71 | ...
72 | }
73 | - Generalize the SQL that drops a drop foreign key constraint.
74 | - Generalize the character used to quote an identifier; MySQL uses '`'.
75 | - Generalize for databases which do not have table and column
76 | constraints, e.g. MySQL.
77 | - Add support for character sets having a collation.
78 | - The Unicode case object specifies the "utf8" character set with
79 | the "utf8_unicode_ci" collation. For an explanation why this
80 | slower collation is used instead the "utf8_general_ci"
81 | collation, which is MySQL's default collation for the "utf8"
82 | character set, see http://stackoverflow.com/questions/766809/ .
83 | - Unit tests run on MySQL.
84 |
85 | * On Derby:
86 | - A limit on the BLOB data type is now reflected in the generated
87 | SQL passed to Derby.
88 | - A limit on a TIMESTAMP is now not passed to Derby since Derby
89 | does not support it.
90 | - Unit tests now use an in memory database for faster turnaround.
91 |
92 | * On PostgreSQL:
93 | - Default values on the BLOB and VARBINARY data types are now
94 | reflected in the generated SQL passed to PostgreSQL.
95 |
96 | * To support PostgreSQL's ability to grant and revoke privileges on
97 | schemas and its USAGE privilege, the following was done:
98 |
99 | - Add a new sealed base Privilege trait that is the super-trait to
100 | all privileges.
101 | - Add a new sealed SchemaPrivilege trait that extends Privilege.
102 | - Add a new UsagePrivilege case object that extends SchemaPrivilege.
103 | - The existing GrantPrivilegeType trait now also extends Privilege.
104 | - The existing AllPrivileges case object now also extends SchemaPrivilege.
105 | - Migration adds #grantSchemaPrivilege() and #revokeSchemaPrivilege()
106 | to add or remove privileges from a schema.
107 |
108 | Patches by Alan LaMielle.
109 |
110 | * The With.*() methods properly handle the closure argument and/or
111 | close() throwing exceptions; functionality inspired by Java 7's
112 | try-with-resources where an exception thrown by closer is not
113 | suppressed if the body did not throw an exception. This ensures
114 | that the caller always is thrown an exception if one occurred.
115 |
116 | http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3
117 |
118 | * Scala 2.10.0:
119 | - Add support for 2.10.0.
120 | - Explicitly type exception classes in exception catching pattern
121 | matches. When catching Throwable always log it or rethrow it.
122 | - Fix minor bugs caught by Scala 2.10.0 compiler.
123 |
124 | * Code style cleanups to better match the Scala style guide:
125 | http://docs.scala-lang.org/style/scaladoc.html
126 |
127 | Version 1.0.3 - September 21st, 2012
128 | * Make log4jdbc optional by checking for it at runtime and using it
129 | if it is available. This is to workaround log4jdbc not present in
130 | any public Maven repositories, to make it easier for developers
131 | using build tools with automatic dependency resolution so they do
132 | not have to download log4jdbc themselves:
133 | http://code.google.com/p/log4jdbc/wiki/FAQ
134 | http://code.google.com/p/log4jdbc/issues/detail?id=19
135 |
136 | * For Scala 2.8.0 and greater, switch from ant/ivy to sbt to build
137 | the project. In addition to reducing the number of files checked
138 | into source control to build the project, it also supports easy
139 | publishing to Sonatype's open-source repository.
140 |
141 | Version 1.0.2 - November 8th, 2011
142 | * Issue #22: use java.lang.ClassLoader#getResources() instead of
143 | #getResource() in case there are multiple resources with the same
144 | package name. Now all resources providing the package name are
145 | searched.
146 |
147 | * Issue #23: fix a bug by URL decoding resource URLs so that
148 | resources in directories containing one or more space characters
149 | can be found.
150 |
151 | Version 1.0.1 - February 14th, 2010
152 | * New method Migration#alterColumn() which allows column definitions
153 | to be altered.
154 |
155 | * Initial support for building with Maven. It only builds jars for
156 | JDBC 4/JDK 1.6, not for JDBC 3/JDK 1.5. Build with ant to build
157 | JDBC 3/JDK 1.5 jars.
158 |
159 | * Usernames for Migration#grant() and #revoke() are now converted
160 | into the database's canonical case, e.g. lowercase or uppercase,
161 | and then quoted.
162 |
163 | * Refactor the unit tests to allow for testing with databases other
164 | than Derby.
165 |
166 | * The table names in the unit tests have been renamed to all start
167 | with "scala_migrations_". This makes it easier to unit test the
168 | project in an existing schema. The only table that doesn't start
169 | with "scala_migrations_" is "schema_migrations".
170 |
171 | * Lots of internal refactoring and code cleanup.
172 |
173 | Version 1.0.0 - February 11th, 2010
174 | * Provide Scala 2.8.0.Beta1 support. Code modifications that work
175 | under both Scala 2.7.x and 2.8.x were applied to the default
176 | (2.7.x) branch and merged to the scala-2.8 branch to minimize the
177 | differences between the branches.
178 |
179 | * Fix a bug in dropping indices in Oracle.
180 |
181 | * Index names are now quoted and potentially case converted in the
182 | same manner as column names.
183 |
184 | * Provide a addingForeignKeyConstraintCreatesIndex method in
185 | Migration and DatabaseAdaper that returns true if the database
186 | implicitly adds an index on the column that has a foreign key
187 | constraint added to it. This can be used to dynamically add an
188 | index for those databases that don't implicitly add an index on
189 | foreign key columns.
190 |
191 | * Switch to using scaladoc instead of vscaladoc when compiling with
192 | Scala 2.7.x to be consistent with compilation with Scala 2.8.x.
193 |
194 | * Update the test suite to run against Derby 10.5.3 instead of
195 | 10.5.1.1.
196 |
197 | * Switch code style to be more compliant with standard Scala code,
198 | specifically, remove the space before a : in type annotations.
199 |
200 | Version 0.9.2 - November 2nd, 2009
201 | * Build with Scala 2.7.7.
202 |
203 | Version 0.9.1 - September 2nd, 2009
204 | * Add the ability to add and drop columns in existing tables. The
205 | new methods are addColumn() and removeColumn() in the Migration
206 | class.
207 |
208 | Version 0.9.0 - August 1st, 2009
209 | * First public release.
210 |
--------------------------------------------------------------------------------
/HACKING:
--------------------------------------------------------------------------------
1 | ### Original Commit
2 |
3 | Please do original work on `master`. The `master` branch is for the
4 | latest stable branch of Scala, e.g. 2.9.Z where Z is the patch version
5 | number. Your commit should work with all Scala patch versions.
6 |
7 | ### Merge Commit For Older Scala Versions
8 |
9 | We maintain `scala-X.Y` branches for older stable Scala versions.
10 |
11 | At all times we support the current stable and previous stable Scala
12 | branches, e.g. 2.9.Z and 2.8.Z, so at a minimum merge your change from
13 | `master` to the branch for the previous stable Scala branch.
14 |
15 | We do this as a benefit for the community to add features for older
16 | Scala versions. Additionally, Sony Pictures Imageworks doesn't have
17 | the cycles to immediately upgrade to the latest Scala version, so for
18 | selfish reasons, we would like it merged back ;)
19 |
20 | ### Test Before Submitting Pull Request
21 |
22 | ##### Testing On a Branch Using sbt
23 |
24 | If you are on a branch that uses sbt, please run the unit tests on all
25 | the Scala versions that the branch supports by using `sbt "+ test"`.
26 | For example, the `scala-2.8` branch supports 2.8.0, 2.8.1 and 2.8.2,
27 | so all three versions would need to be tested.
28 |
29 | We request this since sometimes changes are made to Scala that break
30 | the build on a specific patch version. If the build does break then
31 | the pull request will not be accepted because we do a separate release
32 | for each Scala patch version.
33 |
34 | ##### Testing On a Branch Using ant
35 |
36 | For the `scala-2.7` branch, testing with Scala 2.7.7 is sufficient.
37 |
38 | ### Build and Test Commands
39 |
40 | ##### Scala 2.8 and Above
41 |
42 | The `master` and `scala-X.Y` branches for X.Y >= 2.8 use sbt to build,
43 | run unit tests, and package Scala Migrations. Find sbt at
44 | http://www.scala-sbt.org/ .
45 |
46 | * Install sbt
47 | * http://www.scala-sbt.org/release/docs/Getting-Started/Setup.html
48 | * To build: sbt compile
49 | * To test with the highest Scala version supported by the branch: sbt test
50 | * To test with all Scala versions supported by the branch: sbt "+ test"
51 | * To package all versions (instead of just one): sbt "+ package"
52 | * To generate IntelliJ project: sbt gen-idea
53 |
54 | ##### Scala 2.7
55 |
56 | The `scala-2.7` branch uses ant to build, run unit tests and package
57 | Scala Migrations.
58 |
59 | * Install ant
60 | * To build: ant compile
61 | * To test: ant test
62 | * To package: ant
63 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008,2009,2010 Sony Pictures Imageworks Inc.
2 |
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions
7 | are met:
8 |
9 | Redistributions of source code must retain the above copyright
10 | notice, this list of conditions and the following disclaimer.
11 | Redistributions in binary form must reproduce the above copyright
12 | notice, this list of conditions and the following disclaimer in the
13 | documentation and/or other materials provided with the
14 | distribution. Neither the name of Sony Pictures Imageworks nor the
15 | names of its contributors may be used to endorse or promote
16 | products derived from this software without specific prior written
17 | permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 | OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | import scalariform.formatter.preferences._
2 |
3 | name := "scala-migrations"
4 |
5 | description := "Database migrations written in Scala."
6 |
7 | homepage := Some(url("http://opensource.imageworks.com/?p=scalamigrations"))
8 |
9 | startYear := Some(2008)
10 |
11 | organization := "com.imageworks.scala-migrations"
12 |
13 | organizationName := "Sony Pictures Imageworks"
14 |
15 | organizationHomepage := Some(url("http://www.imageworks.com/"))
16 |
17 | licenses += "New BSD License" -> url("http://opensource.org/licenses/BSD-3-Clause")
18 |
19 | version := "1.1.2-SNAPSHOT"
20 |
21 | scalaVersion := "2.11.12"
22 |
23 | // For a single major Scala release, e.g. 2.x.y, include at most one
24 | // Scala release candidate in crossScalaVersions, e.g. "2.x.y-RC3".
25 | // When the Scala final release has been published, then replace the
26 | // release candidate with the Scala final release.
27 | crossScalaVersions := Seq("2.9.0", "2.9.0-1",
28 | "2.9.1", "2.9.1-1",
29 | "2.9.2", "2.9.3",
30 | "2.10.4",
31 | "2.11.4")
32 |
33 | // Increase warnings generated by the Scala compiler.
34 | //
35 | // For Scala 2.10 and greater, pass "-feature" to scalac to enable
36 | // warnings for use of features that should be explicitly imported,
37 | // e.g. "import scala.language.implicitConversions" to enable implicit
38 | // conversions. However, since Scala Migrations uses implicit
39 | // conversions and to maintain source compatibility so that separate
40 | // branches are not needed, pass "-language:implicitConversions" so
41 | // that "-feature" can be used without generating spurious warnings.
42 | scalacOptions <++= scalaVersion map { v: String =>
43 | val options1 = "-deprecation" :: "-unchecked" :: Nil
44 | if (v.startsWith("2.9.0")) {
45 | options1
46 | }
47 | else {
48 | val options2 = "-Xlint" :: options1
49 | if (v.startsWith("2.9"))
50 | options2
51 | else
52 | "-feature" :: "-language:implicitConversions" :: options2
53 | }
54 | }
55 |
56 | libraryDependencies ++= Seq(
57 | "com.google.code.findbugs" % "jsr305" % "2.0.3",
58 | "com.novocode" % "junit-interface" % "0.10-M4" % "test",
59 | "log4jdbc" % "log4jdbc" % "1.1" from "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/log4jdbc/log4jdbc4-1.1.jar",
60 | "mysql" % "mysql-connector-java" % "[5.1.0,5.2)" % "test",
61 | "org.apache.derby" % "derby" % "[10.5.3.0,10.12)" % "test",
62 | "org.hamcrest" % "hamcrest-core" % "1.3" % "test",
63 | "org.jmock" % "jmock-junit4" % "[2.8.0,3.0)" % "test",
64 | "org.slf4j" % "slf4j-api" % "[1.5.8,2.0)",
65 | "org.slf4j" % "slf4j-log4j12" % "[1.5.8,2.0)" % "test",
66 | "postgresql" % "postgresql" % "9.1-901.jdbc4" % "test")
67 |
68 | // Run unit tests serially otherwise races can occur between two
69 | // threads checking if the 'schema_migrations' table exists and
70 | // trying to create it.
71 | parallelExecution in Test := false
72 |
73 | testOptions += Tests.Argument(TestFrameworks.JUnit, "-v")
74 |
75 | scalariformSettings
76 |
77 | ScalariformKeys.preferences := FormattingPreferences().
78 | setPreference(AlignParameters, true).
79 | setPreference(CompactControlReadability, true).
80 | setPreference(DoubleIndentClassDeclaration, true)
81 |
82 | publishMavenStyle := true
83 |
84 | publishArtifact in Test := false
85 |
86 | pomIncludeRepository := { _ => false }
87 |
88 | pomExtra :=
89 |
90 |
91 | blair
92 | Blair Zajac
93 | blair@orcaware.com
94 |
95 |
96 | jrray
97 | J. Robert Ray
98 | jrobertray@gmail.com
99 |
100 |
101 |
102 | scm:git:git@github.com:imageworks/scala-migrations.git
103 | scm:git:git@github.com:imageworks/scala-migrations.git
104 | git@github.com:imageworks/scala-migrations.git
105 |
106 |
107 | // Do not include log4jdbc as a dependency.
108 | pomPostProcess := { (node: scala.xml.Node) =>
109 | val rewriteRule =
110 | new scala.xml.transform.RewriteRule {
111 | override def transform(n: scala.xml.Node): scala.xml.NodeSeq = {
112 | val name = n.nameToString(new StringBuilder).toString
113 | if ( (name == "dependency")
114 | && ((n \ "groupId").text == "log4jdbc")
115 | && ((n \ "artifactId").text == "log4jdbc")) {
116 | scala.xml.NodeSeq.Empty
117 | }
118 | else {
119 | n
120 | }
121 | }
122 | }
123 | val transformer = new scala.xml.transform.RuleTransformer(rewriteRule)
124 | transformer.transform(node)(0)
125 | }
126 |
127 | publishTo := {
128 | val nexus = "https://oss.sonatype.org/"
129 | if (version.value.trim.endsWith("SNAPSHOT"))
130 | Some("snapshots" at nexus + "content/repositories/snapshots")
131 | else
132 | Some("releases" at nexus + "service/local/staging/deploy/maven2")
133 | }
134 |
135 | useGpg := true
136 |
137 | useGpgAgent := true
138 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.18
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1")
2 |
3 | addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1")
4 |
5 | addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.0")
6 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/CharacterSetName.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * The base trait for all character set names.
37 | */
38 | sealed trait CharacterSetName
39 |
40 | /**
41 | * The character data types should be encoded using Unicode.
42 | *
43 | * On Derby, character data types are encoded using Unicode by
44 | * default so specifying this does not change the encoding.
45 | *
46 | * On MySQL, this case object specifies the "utf8" character set. If
47 | * the collation is not specified then the "utf8_unicode_ci" collation
48 | * is used. See http://stackoverflow.com/questions/766809/ why this
49 | * slower collation is used instead the "utf8_general_ci" collation,
50 | * which is MySQL's default collation for the "utf8" character set.
51 | *
52 | * On Oracle, this specifies that NCHAR is used for CharType and
53 | * NVARCHAR2 for VarcharType.
54 | *
55 | * On PostgreSQL, this case object is ignored as the character set
56 | * encoding can only be specified when the database is created; using
57 | * it generates a runtime warning.
58 | */
59 | case object Unicode
60 | extends CharacterSetName
61 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/CommitBehavior.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * This sealed trait's specifies the commit behavior on a database
37 | * connection and its subobjects are used as arguments to the
38 | * Migrator#with*Connection() methods. The subobjects specify if a
39 | * new connection's auto-commit mode should be left on or disabled.
40 | * For connections with auto-commit mode disabled it specifies if the
41 | * current transaction should be rolled back or committed if the
42 | * closure passed to Migrator#with*Connection() throws an exception.
43 | */
44 | private sealed trait CommitBehavior
45 |
46 | /**
47 | * The new database connection's auto-commit mode is left on. Because
48 | * the connection is in auto-commit mode the
49 | * Migrator#with*Connection() methods do not commit nor roll back the
50 | * transaction any before returning the result of the
51 | * Migrator#with*Connection()'s closure or rethrowing its exception.
52 | */
53 | private case object AutoCommit
54 | extends CommitBehavior
55 |
56 | /**
57 | * The new database connection's auto-commit mode is turned off.
58 | * Regardless if the closure passed to Migrator#with*Connection()
59 | * returns or throws an exception the transaction is committed.
60 | */
61 | private case object CommitUponReturnOrException
62 | extends CommitBehavior
63 |
64 | /**
65 | * The new database connection's auto-commit mode is turned off. If
66 | * the closure passed to the Migrator#with*Connection() returns
67 | * normally then transaction is committed; if it throws an exception
68 | * then the transaction is rolled back.
69 | */
70 | private case object CommitUponReturnOrRollbackUponException
71 | extends CommitBehavior
72 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/ConnectionBuilder.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | import java.sql.{
36 | Connection,
37 | DriverManager
38 | }
39 | import javax.sql.DataSource
40 |
41 | /**
42 | * Adapter class for getting a Connection from either the
43 | * DriverManager or a DataSource.
44 | */
45 | class ConnectionBuilder private (either: Either[DataSource, String],
46 | loginOpt: Option[(String, String)]) {
47 | /**
48 | * Construct a connection builder for a database that does not need
49 | * a username and password.
50 | *
51 | * @param url the JDBC URL to connect to the database
52 | */
53 | def this(url: String) {
54 | this(Right(url), None)
55 | }
56 |
57 | /**
58 | * Construct a connection builder for a database that needs a
59 | * username and password.
60 | *
61 | * @param url the JDBC URL to connect to the database
62 | * @param username the username to log into the database
63 | * @param password the password associated with the database
64 | * username
65 | */
66 | def this(url: String,
67 | username: String,
68 | password: String) {
69 | this(Right(url), Some((username, password)))
70 | }
71 |
72 | /**
73 | * Construct a connection builder with a DataSource for a database
74 | * that does not need a username and password.
75 | *
76 | * @param datasource the JDBC DataSource to connect to the
77 | * database
78 | */
79 | def this(datasource: DataSource) {
80 | this(Left(datasource), None)
81 | }
82 |
83 | /**
84 | * Construct a connection builder with a DataSource and override the
85 | * default username and password.
86 | *
87 | * @param datasource the JDBC DataSource to connect to the database
88 | * @param username the username to log into the database
89 | * @param password the password associated with the database
90 | * username
91 | */
92 | def this(datasource: DataSource,
93 | username: String,
94 | password: String) {
95 | this(Left(datasource), Some((username, password)))
96 | }
97 |
98 | def withConnection[R](commitBehavior: CommitBehavior)(f: Function[Connection, R]): R = {
99 | val connection =
100 | (either, loginOpt) match {
101 | case (Left(datasource), Some((username, password))) =>
102 | datasource.getConnection(username, password)
103 | case (Left(datasource), None) =>
104 | datasource.getConnection
105 | case (Right(url), Some((username, password))) =>
106 | DriverManager.getConnection(url, username, password)
107 | case (Right(url), None) =>
108 | DriverManager.getConnection(url)
109 | }
110 |
111 | With.autoClosingConnection(connection) { c =>
112 | With.autoCommittingConnection(c, commitBehavior)(f)
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/DerbyDatabaseAdapter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | trait DerbyAutoIncrementingColumnDefinitionMixin
36 | extends ColumnDefinition
37 | with ColumnSupportsAutoIncrement {
38 | override protected abstract def sql: String = {
39 | if (isAutoIncrement) super.sql + " GENERATED BY DEFAULT AS IDENTITY"
40 | else super.sql
41 | }
42 | }
43 |
44 | // Derby 10.2 and greater support an optional limit on the BLOB's
45 | // size.
46 | class DerbyBlobColumnDefinition
47 | extends DefaultBlobColumnDefinition
48 | with ColumnSupportsLimit
49 |
50 | class DerbyBigintColumnDefinition
51 | extends DefaultBigintColumnDefinition
52 | with DerbyAutoIncrementingColumnDefinitionMixin
53 |
54 | class DerbyIntegerColumnDefinition
55 | extends DefaultIntegerColumnDefinition
56 | with DerbyAutoIncrementingColumnDefinitionMixin
57 |
58 | class DerbySmallintColumnDefinition
59 | extends DefaultSmallintColumnDefinition
60 | with DerbyAutoIncrementingColumnDefinitionMixin
61 |
62 | // Derby does not support size specifiers for the TIMESTAMP data type.
63 | class DerbyTimestampColumnDefinition
64 | extends ColumnDefinition
65 | with ColumnSupportsDefault {
66 | override protected def sql = "TIMESTAMP"
67 | }
68 |
69 | class DerbyVarbinaryColumnDefinition
70 | extends DefaultVarbinaryColumnDefinition {
71 | override protected def sql = {
72 | optionallyAddLimitToDataType("VARCHAR") + " FOR BIT DATA"
73 | }
74 | }
75 |
76 | class DerbyDatabaseAdapter(override val schemaNameOpt: Option[String])
77 | extends DatabaseAdapter(schemaNameOpt) {
78 | override val vendor = Derby
79 |
80 | override val quoteCharacter = '"'
81 |
82 | override val unquotedNameConverter = UppercaseUnquotedNameConverter
83 |
84 | override val userFactory = PlainUserFactory
85 |
86 | override val alterTableDropForeignKeyConstraintPhrase = "CONSTRAINT"
87 |
88 | override val addingForeignKeyConstraintCreatesIndex = true
89 |
90 | override val supportsCheckConstraints = true
91 |
92 | override def columnDefinitionFactory(columnType: SqlType,
93 | characterSetOpt: Option[CharacterSet]): ColumnDefinition = {
94 | characterSetOpt match {
95 | case None =>
96 | case Some(CharacterSet(Unicode, None)) =>
97 | case Some(charset @ CharacterSet(Unicode, Some(collation))) =>
98 | logger.warn("Ignoring collation '{}' in '{}' as Derby only " +
99 | "supports setting the collation when the database " +
100 | "is created.",
101 | Array[AnyRef](collation, charset): _*)
102 | case Some(charset @ CharacterSet(_, _)) =>
103 | logger.warn("Ignoring '{}' as Derby uses Unicode sequences to " +
104 | "represent character data types.",
105 | charset)
106 | }
107 |
108 | columnType match {
109 | case BigintType =>
110 | new DerbyBigintColumnDefinition
111 | case BlobType =>
112 | new DerbyBlobColumnDefinition
113 | case BooleanType => {
114 | val message = "Derby 10.6 and older do not support BOOLEAN as a " +
115 | "legal data type, you must choose a mapping yourself."
116 | throw new UnsupportedColumnTypeException(message)
117 | }
118 | case CharType =>
119 | new DefaultCharColumnDefinition
120 | case DecimalType =>
121 | new DefaultDecimalColumnDefinition
122 | case IntegerType =>
123 | new DerbyIntegerColumnDefinition
124 | case SmallintType =>
125 | new DerbySmallintColumnDefinition
126 | case TimestampType =>
127 | new DerbyTimestampColumnDefinition
128 | case VarbinaryType =>
129 | new DerbyVarbinaryColumnDefinition
130 | case VarcharType =>
131 | new DefaultVarcharColumnDefinition
132 | }
133 | }
134 |
135 | override protected def alterColumnSql(schemaNameOpt: Option[String],
136 | columnDefinition: ColumnDefinition): String = {
137 | new java.lang.StringBuilder(512)
138 | .append("ALTER TABLE ")
139 | .append(quoteTableName(schemaNameOpt, columnDefinition.getTableName))
140 | .append(" ALTER ")
141 | .append(quoteColumnName(columnDefinition.getColumnName))
142 | .append(" SET DATA TYPE ")
143 | .append(columnDefinition.toSql)
144 | .toString
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/ForeignKeyConstraintAction.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * The base trait for all foreign key actions upon delete or update.
37 | */
38 | sealed trait ForeignKeyConstraintAction {
39 | val sql: String
40 | }
41 |
42 | /**
43 | * Delete any rows in the referencing table that refer to rows deleted
44 | * in the referenced table, or update the row's value to the new value
45 | * in the referenced row if it was updated.
46 | */
47 | case object Cascade
48 | extends ForeignKeyConstraintAction {
49 | override val sql = "CASCADE"
50 | }
51 |
52 | /**
53 | * Generate an error that updating or deleting the row would cause a
54 | * foreign key constraint violation. In some databases, NO ACTION
55 | * implies a deferred check, after all deletes have been performed.
56 | */
57 | case object NoAction
58 | extends ForeignKeyConstraintAction {
59 | override val sql = "NO ACTION"
60 | }
61 |
62 | /**
63 | * Generate an error that updating or deleting the row would cause a
64 | * foreign key constraint violation. This is the same as NoAction,
65 | * except that any checks are not deferred.
66 | */
67 | case object Restrict
68 | extends ForeignKeyConstraintAction {
69 | override val sql = "RESTRICT"
70 | }
71 |
72 | /**
73 | * Set any rows in the referencing table to their default value when
74 | * the referenced rows are deleted or updated. Not all databases
75 | * support SET DEFAULT for ON UPDATE.
76 | */
77 | case object SetDefault
78 | extends ForeignKeyConstraintAction {
79 | override val sql = "SET DEFAULT"
80 | }
81 |
82 | /**
83 | * Set any rows in the referencing table to NULL when the referenced
84 | * rows are deleted or updated. Not all databases support SET DEFAULT
85 | * for ON UPDATE.
86 | */
87 | case object SetNull
88 | extends ForeignKeyConstraintAction {
89 | override val sql = "SET NULL"
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/JavaDatabaseAdapter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * The Scala Database Adapter classes uses Scala case classes in their public
37 | * constructors and public methods which makes it difficult to use from a pure
38 | * Java environment. This class provides Java-friendly factory functions to
39 | * create adapters.
40 | */
41 | object JavaDatabaseAdapter {
42 | /**
43 | * Create a Derby Database Adapter.
44 | *
45 | * @return newly constructed DerbyDatabaseAdapter
46 | */
47 | def getDerbyDatabaseAdapter: DerbyDatabaseAdapter = {
48 | new DerbyDatabaseAdapter(None)
49 | }
50 |
51 | /**
52 | * Create a Derby Database Adapter.
53 | *
54 | * @param schemaName the default schema name in the adapter
55 | * @return newly constructed DerbyDatabaseAdapter
56 | */
57 | def getDerbyDatabaseAdapter(schemaName: String): DerbyDatabaseAdapter = {
58 | new DerbyDatabaseAdapter(Some(schemaName))
59 | }
60 |
61 | /**
62 | * Create a MySQL Database Adapter.
63 | *
64 | * @return newly constructed MysqlDatabaseAdapter
65 | */
66 | def getMysqlDatabaseAdapter: MysqlDatabaseAdapter = {
67 | new MysqlDatabaseAdapter(None)
68 | }
69 |
70 | /**
71 | * Create a MySQL Database Adapter.
72 | *
73 | * @param schemaName the default schema name in the adapter
74 | * @return newly constructed MysqlDatabaseAdapter
75 | */
76 | def getMysqlDatabaseAdapter(schemaName: String): MysqlDatabaseAdapter = {
77 | new MysqlDatabaseAdapter(Some(schemaName))
78 | }
79 |
80 | /**
81 | * Create an Oracle Database Adapter.
82 | *
83 | * @return newly constructed OracleDatabaseAdapter
84 | */
85 | def getOracleDatabaseAdapter: OracleDatabaseAdapter = {
86 | new OracleDatabaseAdapter(None)
87 | }
88 |
89 | /**
90 | * Create an Oracle Database Adapter.
91 | *
92 | * @param schemaName the default schema name in the adapter
93 | * @return newly constructed OracleDatabaseAdapter
94 | */
95 | def getOracleDatabaseAdapter(schemaName: String): OracleDatabaseAdapter = {
96 | new OracleDatabaseAdapter(Some(schemaName))
97 | }
98 |
99 | /**
100 | * Create a PostgreSQL Database Adapter.
101 | *
102 | * @return newly constructed PostgresqlDatabaseAdapter
103 | */
104 | def getPostgresqlDatabaseAdapter: PostgresqlDatabaseAdapter = {
105 | new PostgresqlDatabaseAdapter(None)
106 | }
107 |
108 | /**
109 | * Create a PostgreSQL Database Adapter.
110 | *
111 | * @param schemaName the default schema name in the adapter
112 | * @return newly constructed PostgresqlDatabaseAdapter
113 | */
114 | def getPostgresqlDatabaseAdapter(schemaName: String): PostgresqlDatabaseAdapter = {
115 | new PostgresqlDatabaseAdapter(Some(schemaName))
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/JavaMigrator.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * The Scala Migrator class uses Scala case classes in its public
37 | * constructors and public methods which makes it difficult to use
38 | * from a pure Java environment. This class exposes a Java-style
39 | * interface and delegates to the Scala Migrator class.
40 | */
41 | class JavaMigrator private (migrator: Migrator) {
42 | /**
43 | * JavaMigrator constructor.
44 | *
45 | * @param connectionBuilder a builder of connections to the
46 | * database
47 | * @param adapter a concrete DatabaseAdapter that the migrator uses
48 | * to handle database specific features
49 | */
50 | def this(connectionBuilder: ConnectionBuilder,
51 | adapter: DatabaseAdapter) {
52 | this(new Migrator(connectionBuilder, adapter))
53 | }
54 |
55 | /**
56 | * JavaMigrator constructor.
57 | *
58 | * @param jdbcUrl the JDBC URL to connect to the database
59 | * @param adapter a concrete DatabaseAdapter that the migrator uses
60 | * to handle database specific features
61 | */
62 | def this(jdbcUrl: String,
63 | adapter: DatabaseAdapter) {
64 | this(new ConnectionBuilder(jdbcUrl), adapter)
65 | }
66 |
67 | /**
68 | * JavaMigrator constructor.
69 | *
70 | * @param jdbcUrl the JDBC URL to connect to the database
71 | * @param jdbcUsername the username to log into the database
72 | * @param jdbcPassword the password associated with the database
73 | * username
74 | * @param adapter a concrete DatabaseAdapter that the migrator uses
75 | * to handle database specific features
76 | */
77 | def this(jdbcUrl: String,
78 | jdbcUsername: String,
79 | jdbcPassword: String,
80 | adapter: DatabaseAdapter) {
81 | this(new ConnectionBuilder(jdbcUrl, jdbcUsername, jdbcPassword),
82 | adapter)
83 | }
84 |
85 | /**
86 | * Get a list of table names. If the database adapter was given a
87 | * schema name then only the tables in that schema are returned.
88 | *
89 | * @return a set of table names; no modifications of the case of
90 | * table names is done
91 | */
92 | def getTableNames: java.util.Set[String] = {
93 | val tableNames = migrator.getTableNames
94 |
95 | val set = new java.util.HashSet[String](tableNames.size)
96 |
97 | for (tableName <- tableNames)
98 | set.add(tableName)
99 |
100 | set
101 | }
102 |
103 | /**
104 | * Install all available migrations into the database.
105 | *
106 | * @param packageName the package name that the Migration subclasses
107 | * should be searched for
108 | * @param searchSubPackages true if sub-packages of packageName
109 | * should be searched
110 | */
111 | def installAllMigrations(packageName: String,
112 | searchSubPackages: Boolean) {
113 | migrator.migrate(InstallAllMigrations, packageName, searchSubPackages)
114 | }
115 |
116 | /**
117 | * Remove all installed migrations from the database.
118 | *
119 | * @param packageName the package name that the Migration subclasses
120 | * should be searched for
121 | * @param searchSubPackages true if sub-packages of packageName
122 | * should be searched
123 | */
124 | def removeAllMigrations(packageName: String,
125 | searchSubPackages: Boolean) {
126 | migrator.migrate(RemoveAllMigrations, packageName, searchSubPackages)
127 | }
128 |
129 | /**
130 | * Migrate the database to the given version.
131 | *
132 | * @param version the version number the database should be migrated
133 | * to
134 | * @param packageName the package name that the Migration subclasses
135 | * should be searched for
136 | * @param searchSubPackages true if sub-packages of packageName
137 | * should be searched
138 | */
139 | def migrateTo(version: Long,
140 | packageName: String,
141 | searchSubPackages: Boolean) {
142 | migrator.migrate(MigrateToVersion(version), packageName, searchSubPackages)
143 | }
144 |
145 | /**
146 | * Rollback a given number of migrations in the database.
147 | *
148 | * @param count the number of migrations to rollback
149 | * to
150 | * @param packageName the package name that the Migration subclasses
151 | * should be searched for
152 | * @param searchSubPackages true if sub-packages of packageName
153 | * should be searched
154 | */
155 | def rollback(count: Int,
156 | packageName: String,
157 | searchSubPackages: Boolean) {
158 | migrator.migrate(RollbackMigration(count),
159 | packageName,
160 | searchSubPackages)
161 | }
162 |
163 | /**
164 | * Determine if the database has all available migrations installed
165 | * in it and no migrations installed that do not have a
166 | * corresponding concrete Migration subclass; that is, the database
167 | * must have only those migrations installed that are found by
168 | * searching the package name for concrete Migration subclasses.
169 | *
170 | * Running this method does not modify the database in any way. The
171 | * schema migrations table is not created.
172 | *
173 | * @param packageName the Java package name to search for Migration
174 | * subclasses
175 | * @param searchSubPackages true if sub-packages of packageName
176 | * should be searched
177 | * @return null if all available migrations are installed and all
178 | * installed migrations have a corresponding Migration
179 | * subclass; a non-null message suitable for logging with
180 | * the not-installed migrations and the installed migrations
181 | * that do not have a matching Migration subclass
182 | */
183 | def whyNotMigrated(packageName: String,
184 | searchSubPackages: Boolean): String = {
185 | migrator.whyNotMigrated(packageName, searchSubPackages) match {
186 | case Some(message) => message
187 | case None => null
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/MigrationDirection.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Sealed abstract class that defines the direction to run a
37 | * migration.
38 | */
39 | sealed abstract class MigrationDirection {
40 | /**
41 | * A human readable string representing the migration direction.
42 | */
43 | val str: String
44 | }
45 |
46 | /**
47 | * Case object used to indicate that a migration should be installed.
48 | */
49 | case object Up
50 | extends MigrationDirection {
51 | override val str = "up"
52 | }
53 |
54 | /**
55 | * Case object used to indicate that a migration should be removed.
56 | */
57 | case object Down
58 | extends MigrationDirection {
59 | override val str = "down"
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/MigrationException.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | class MigrationException(message: String)
36 | extends Exception(message)
37 |
38 | class DuplicateMigrationDescriptionException(message: String)
39 | extends MigrationException(message)
40 |
41 | class DuplicateMigrationVersionException(message: String)
42 | extends MigrationException(message)
43 |
44 | class IrreversibleMigrationException
45 | extends MigrationException("This migration is irreversible.")
46 |
47 | class MissingMigrationClass(message: String)
48 | extends MigrationException(message)
49 |
50 | class UnsupportedColumnTypeException(message: String)
51 | extends MigrationException(message)
52 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/MigrationStatuses.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Container for the state of all the available and installed
37 | * migrations.
38 | *
39 | * @param notInstalled a sorted map of migration version numbers to
40 | * Migration subclasses that are not installed in the database
41 | * @param installedWithAvailableImplementation a sorted map of
42 | * migration version numbers to Migration subclasses that are
43 | * currently installed in the database that have a matching a
44 | * Migration subclass
45 | * @param installedWithoutAvailableImplementation a sorted set of
46 | * migration version numbers that are currently installed in
47 | * the database but do not have a matching a Migration subclass
48 | */
49 | case class MigrationStatuses(notInstalled: scala.collection.SortedMap[Long, Class[_ <: Migration]],
50 | installedWithAvailableImplementation: scala.collection.SortedMap[Long, Class[_ <: Migration]],
51 | installedWithoutAvailableImplementation: scala.collection.SortedSet[Long])
52 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/MigratorOperation.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * The set of migrator operations that can be performed.
37 | */
38 | sealed abstract class MigratorOperation
39 |
40 | /**
41 | * Install all available migrations.
42 | */
43 | case object InstallAllMigrations
44 | extends MigratorOperation
45 |
46 | /**
47 | * Remove all installed migrations. This should effectively return
48 | * the database to a pristine state, except if any migration throws a
49 | * IrreversibleMigrationException.
50 | */
51 | case object RemoveAllMigrations
52 | extends MigratorOperation
53 |
54 | /**
55 | * Remove all migrations with versions greater than the given version
56 | * and install all migrations less then or equal to the given version.
57 | */
58 | case class MigrateToVersion(version: Long)
59 | extends MigratorOperation
60 |
61 | /**
62 | * Rollback 'count' migrations in the database. This is different
63 | * than using MigrateToVersion to migrate to the same version, as
64 | * MigrateToVersion will also install any missing migration with a
65 | * version less then the target version. This rollback operation only
66 | * removes migrations from the database.
67 | */
68 | case class RollbackMigration(count: Int)
69 | extends MigratorOperation {
70 | if (count < 1) {
71 | val message = "The number of migrations to rollback must be greater " +
72 | "than zero."
73 | throw new IllegalArgumentException(message)
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/MysqlDatabaseAdapter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Map Unicode to the "utf8" UTF-8 character set. If Unicode is
37 | * specified without a collation then use the "utf8_unicode_ci"
38 | * collation. If a non-Unicode character set is specified then let
39 | * MySQL pick its default collation for the character set. See
40 | * http://dev.mysql.com/doc/refman/5.5/en/charset-charsets.html for
41 | * more information.
42 | */
43 | trait MysqlAppendCharacterSetToColumnDefinitionMixin {
44 | /**
45 | * If a character set is specified, then append MySQL specific SQL
46 | * to the column definition.
47 | *
48 | * If Unicode is specified without a collation, then use the
49 | * utf8_unicode_ci collation. While utf8_general_ci is MySQL's
50 | * default utf8 collation (at least for 5.5), and is faster, it is
51 | * also incorrect; see http://stackoverflow.com/questions/766809/ .
52 | *
53 | * @param dataTypeSql the SQL for the data type
54 | * @param characterSetOpt an optional character set
55 | */
56 | protected def sql(dataTypeSql: String,
57 | characterSetOpt: Option[CharacterSet]): String = {
58 | characterSetOpt match {
59 | case Some(charset) => {
60 | val sb = new java.lang.StringBuilder(64)
61 | sb.append(dataTypeSql)
62 | .append(" CHARACTER SET ")
63 |
64 | charset.name match {
65 | case Unicode => {
66 | sb.append("utf8 COLLATE ")
67 | .append(charset.collationOpt.getOrElse("utf8_unicode_ci"))
68 | }
69 | case name => {
70 | sb.append(name.toString)
71 | charset.collationOpt match {
72 | case Some(collation) =>
73 | sb.append(" COLLATE ")
74 | .append(collation)
75 | case None =>
76 | }
77 | }
78 | }
79 | sb.toString
80 | }
81 | case None => dataTypeSql
82 | }
83 | }
84 | }
85 |
86 | trait MysqlAutoIncrementingColumnDefinitionMixin
87 | extends ColumnDefinition
88 | with ColumnSupportsAutoIncrement {
89 | override protected abstract def sql: String = {
90 | if (isAutoIncrement) super.sql + " AUTO_INCREMENT"
91 | else super.sql
92 | }
93 | }
94 |
95 | class MysqlBigintColumnDefinition
96 | extends DefaultBigintColumnDefinition
97 | with MysqlAutoIncrementingColumnDefinitionMixin
98 |
99 | /**
100 | * Map BlobType to MySQL's LONGBLOB data type.
101 | *
102 | * MySQL supports four different BlobType data types with the
103 | * following properties:
104 | *
105 | * +------------+--------------------+------------------------------+
106 | * | Data Type | Max Length (bytes) | Storage Requirements (bytes) |
107 | * +------------+--------------------+------------------------------+
108 | * | TINYBLOB | 255 | length + 1 |
109 | * | BLOB | 65,535 | length + 2 |
110 | * | MEDIUMBLOB | 16,777,215 | length + 3 |
111 | * | LONGBLOB | 4,294,967,295 | length + 4 |
112 | * +------------+--------------------+------------------------------+
113 | *
114 | * Since the intention of BlobType is to store large amounts of data
115 | * and the additional overhead from TINYBLOB to LONGBLOB is three
116 | * bytes, LONGBLOB is used.
117 | */
118 | class MysqlBlobColumnDefinition
119 | extends DefaultBlobColumnDefinition {
120 | override val sql = "LONGBLOB"
121 | }
122 |
123 | class MysqlCharColumnDefinition(characterSetOpt: Option[CharacterSet])
124 | extends DefaultCharColumnDefinition
125 | with MysqlAppendCharacterSetToColumnDefinitionMixin {
126 | override protected def sql: String = sql(super.sql, characterSetOpt)
127 | }
128 |
129 | class MysqlIntegerColumnDefinition
130 | extends DefaultIntegerColumnDefinition
131 | with MysqlAutoIncrementingColumnDefinitionMixin
132 |
133 | class MysqlSmallintColumnDefinition
134 | extends DefaultSmallintColumnDefinition
135 | with MysqlAutoIncrementingColumnDefinitionMixin
136 |
137 | // MySQL does not support size specifiers for the TIMESTAMP data type.
138 | class MysqlTimestampColumnDefinition
139 | extends ColumnDefinition
140 | with ColumnSupportsDefault {
141 | override val sql = "TIMESTAMP"
142 | }
143 |
144 | class MysqlVarcharColumnDefinition(characterSetOpt: Option[CharacterSet])
145 | extends DefaultVarcharColumnDefinition
146 | with MysqlAppendCharacterSetToColumnDefinitionMixin {
147 | override protected def sql: String = sql(super.sql, characterSetOpt)
148 | }
149 |
150 | class MysqlDatabaseAdapter(override val schemaNameOpt: Option[String])
151 | extends DatabaseAdapter(schemaNameOpt) {
152 | override val vendor = Mysql
153 |
154 | // https://dev.mysql.com/doc/refman/5.5/en/identifiers.html
155 | override val quoteCharacter = '`'
156 |
157 | // mysql> create table PaReNt (pk INT PRIMARY KEY);
158 | // Query OK, 0 rows affected (0.14 sec)
159 | //
160 | // mysql> show tables;
161 | // +----------------+
162 | // | Tables_in_test |
163 | // +----------------+
164 | // | PaReNt |
165 | // +----------------+
166 | // 1 row in set (0.00 sec)
167 | //
168 | // mysql> select * from parent;
169 | // ERROR 1146 (42S02): Table 'test.parent' doesn't exist
170 | // mysql> select * from PARENT;
171 | // ERROR 1146 (42S02): Table 'test.PARENT' doesn't exist
172 | // mysql> select * from PaReNt;
173 | // Empty set (0.00 sec)
174 | override val unquotedNameConverter = CasePreservingUnquotedNameConverter
175 |
176 | override val userFactory = MysqlUserFactory
177 |
178 | // https://dev.mysql.com/doc/refman/5.5/en/alter-table.html
179 | override val alterTableDropForeignKeyConstraintPhrase = "FOREIGN KEY"
180 |
181 | // mysql> CREATE TABLE parent (pk INT PRIMARY KEY);
182 | // Query OK, 0 rows affected (0.13 sec)
183 | //
184 | // mysql> CREATE TABLE child (pk INT PRIMARY KEY, pk_parent INT NOT NULL);
185 | // Query OK, 0 rows affected (0.10 sec)
186 | //
187 | // mysql> ALTER TABLE child
188 | // -> ADD CONSTRAINT idx_child_pk_parent FOREIGN KEY (pk_parent)
189 | // -> REFERENCES parent (pk);
190 | // Query OK, 0 rows affected (0.22 sec)
191 | // Records: 0 Duplicates: 0 Warnings: 0
192 | //
193 | // mysql> SHOW CREATE TABLE child;
194 | // | Table | Create Table
195 | // | child | CREATE TABLE `child` (
196 | // `pk` int(11) NOT NULL,
197 | // `pk_parent` int(11) NOT NULL,
198 | // PRIMARY KEY (`pk`),
199 | // KEY `idx_child_pk_parent` (`pk_parent`),
200 | // CONSTRAINT `idx_child_pk_parent` FOREIGN KEY (`pk_parent`) REFERENCES `parent` (`pk`)
201 | // ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
202 | // 1 row in set (0.00 sec)
203 | //
204 | // mysql> CREATE INDEX idx_child_pk_parent ON child (pk_parent);
205 | // ERROR 1280 (42000): Incorrect index name 'idx_child_pk_parent'
206 | override val addingForeignKeyConstraintCreatesIndex = true
207 |
208 | // https://dev.mysql.com/doc/refman/5.5/en/alter-table.html
209 | override val supportsCheckConstraints = false
210 |
211 | override def columnDefinitionFactory(columnType: SqlType,
212 | characterSetOpt: Option[CharacterSet]): ColumnDefinition = {
213 | columnType match {
214 | case BigintType =>
215 | new MysqlBigintColumnDefinition
216 | case BlobType =>
217 | new MysqlBlobColumnDefinition
218 | case BooleanType =>
219 | new DefaultBooleanColumnDefinition
220 | case CharType =>
221 | new MysqlCharColumnDefinition(characterSetOpt)
222 | case DecimalType =>
223 | new DefaultDecimalColumnDefinition
224 | case IntegerType =>
225 | new MysqlIntegerColumnDefinition
226 | case SmallintType =>
227 | new MysqlSmallintColumnDefinition
228 | case TimestampType =>
229 | new MysqlTimestampColumnDefinition
230 | case VarbinaryType =>
231 | new DefaultVarbinaryColumnDefinition
232 | case VarcharType =>
233 | new MysqlVarcharColumnDefinition(characterSetOpt)
234 | }
235 | }
236 |
237 | override def lockTableSql(schemaNameOpt: Option[String],
238 | tableName: String): String = {
239 | val sb = new java.lang.StringBuilder(64)
240 | sb.append("LOCK TABLES ")
241 | .append(quoteTableName(schemaNameOpt, tableName))
242 | .append(" WRITE")
243 | .toString
244 | }
245 |
246 | override protected def alterColumnSql(schemaNameOpt: Option[String],
247 | columnDefinition: ColumnDefinition): String = {
248 | new java.lang.StringBuilder(512)
249 | .append("ALTER TABLE ")
250 | .append(quoteTableName(schemaNameOpt, columnDefinition.getTableName))
251 | .append(" MODIFY COLUMN ")
252 | .append(quoteColumnName(columnDefinition.getColumnName))
253 | .append(columnDefinition.toSql)
254 | .toString
255 | }
256 |
257 | override def removeIndexSql(schemaNameOpt: Option[String],
258 | tableName: String,
259 | indexName: String): String = {
260 | new java.lang.StringBuilder(128)
261 | .append("ALTER TABLE ")
262 | .append(quoteTableName(schemaNameOpt, tableName))
263 | .append(" DROP INDEX ")
264 | .append(quoteIndexName(None, indexName))
265 | .toString
266 | }
267 | }
268 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/Options.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * This file contains all the case classes and case objects that act
37 | * as options to customize the SQL generated by the Migration methods.
38 | *
39 | * The design uses the Scala compiler to only allow valid options to
40 | * be passed to a Migration method. Some case classes may be used by
41 | * multiple methods and since the base trait for the method's option
42 | * type may be sealed, they all need to be defined in a single source
43 | * file.
44 | */
45 |
46 | /**
47 | * The base trait for all column options. This is not a sealed class
48 | * so database specific column options can be defined.
49 | */
50 | trait ColumnOption
51 |
52 | /**
53 | * The base trait for all foreign key options.
54 | */
55 | sealed trait ForeignKeyOption
56 |
57 | /**
58 | * The base trait for all privileges.
59 | */
60 | sealed trait Privilege
61 |
62 | /**
63 | * The base trait for all schema privileges.
64 | */
65 | sealed trait SchemaPrivilege
66 | extends Privilege
67 |
68 | /**
69 | * The base trait for all table privileges.
70 | *
71 | * TODO: when an ABI breaking change is made to Scala Migrations,
72 | * rename GrantPrivilegeType to TablePrivilege.
73 | */
74 | sealed trait GrantPrivilegeType
75 | extends Privilege
76 |
77 | /**
78 | * The base trait for all index options.
79 | */
80 | sealed trait IndexOption
81 |
82 | /**
83 | * The base trait for all check options.
84 | */
85 | sealed trait CheckOption
86 |
87 | /**
88 | * The base trait for all table options.
89 | */
90 | sealed trait TableOption
91 |
92 | object CharacterSet {
93 | /**
94 | * Construct a CharacterSet with the given character set name and
95 | * collation name.
96 | *
97 | * @param name the name of the character set
98 | * @param collation the name of the collation
99 | */
100 | def apply(name: CharacterSetName,
101 | collation: String): CharacterSet = {
102 | new CharacterSet(name, collation)
103 | }
104 |
105 | /**
106 | * Construct a CharacterSet with the given character set name and
107 | * leave the collation unspecified, thereby letting the database
108 | * choose the collation.
109 | *
110 | * @param name the name of the character set
111 | */
112 | def apply(name: CharacterSetName): CharacterSet = {
113 | new CharacterSet(name)
114 | }
115 | }
116 |
117 | /**
118 | * A character set consists of a character set name and an optional
119 | * collation. A collation is a set of rules to compare characters in
120 | * a character set [1]. If the collation is unspecified then the
121 | * database will choose a default collation, which depending upon the
122 | * database vendor, can vary upon the given character set.
123 | *
124 | * [1] http://dev.mysql.com/doc/refman/5.5/en/charset-general.html
125 | *
126 | * @param name the name of the character set
127 | * @param collationOpt an optional collation for the character set
128 | */
129 | case class CharacterSet(name: CharacterSetName,
130 | collationOpt: Option[String])
131 | extends ColumnOption {
132 | /**
133 | * Construct a CharacterSet with the given character set name and
134 | * collation name.
135 | *
136 | * @param name the name of the character set
137 | * @param collation the name of the collation
138 | */
139 | def this(name: CharacterSetName,
140 | collation: String) {
141 | this(name, Some(collation))
142 | }
143 |
144 | /**
145 | * Construct a CharacterSet with no specified collation.
146 | *
147 | * @param name the name of the character set
148 | */
149 | def this(name: CharacterSetName) {
150 | this(name, None)
151 | }
152 | }
153 |
154 | /**
155 | * A default value for a column.
156 | */
157 | case class Default(value: String)
158 | extends ColumnOption
159 |
160 | /**
161 | * Default companion object allowing Defaults to be constructed with
162 | * integer values.
163 | */
164 | object Default {
165 | def apply(i: Int): Default = {
166 | Default(i.toString)
167 | }
168 |
169 | def apply(i: Long): Default = {
170 | Default(i.toString)
171 | }
172 | }
173 |
174 | /**
175 | * A limit on the size of a column type.
176 | *
177 | * @throws IllegalArgumentException if the limit is less than zero;
178 | * zero is permitted for a limit on TIMESTAMP precision
179 | */
180 | case class Limit(expr: String)
181 | extends ColumnOption {
182 | try {
183 | val length = Integer.parseInt(expr)
184 | if (length < 0) {
185 | val message = "The limit in " +
186 | this +
187 | " must be greater than or equal to zero."
188 | throw new IllegalArgumentException(message)
189 | }
190 | }
191 | catch {
192 | case _: NumberFormatException =>
193 | }
194 | }
195 |
196 | /**
197 | * Limit companion object allowing Limits to be constructed with
198 | * integer values.
199 | */
200 | object Limit {
201 | def apply(i: Int): Limit = {
202 | Limit(i.toString)
203 | }
204 | }
205 |
206 | /**
207 | * A name overriding the default index or foreign key constraint name
208 | * generated by Migration.
209 | */
210 | case class Name(name: String)
211 | extends CheckOption
212 | with ForeignKeyOption
213 | with IndexOption {
214 | if (name eq null) {
215 | throw new IllegalArgumentException("The name cannot be null.")
216 | }
217 |
218 | if (name.isEmpty) {
219 | throw new IllegalArgumentException("The name cannot be empty.")
220 | }
221 | }
222 |
223 | /**
224 | * Specify a check constraint on a column.
225 | */
226 | case class Check(expr: String)
227 | extends ColumnOption
228 |
229 | /**
230 | * Specify a named check constraint on a column.
231 | */
232 | case class NamedCheck(name: String, expr: String)
233 | extends ColumnOption
234 | // NamedCheck cannot inherit from Check, it causes a compiler error.
235 | // http://lampsvn.epfl.ch/trac/scala/ticket/425
236 | // & http://lampsvn.epfl.ch/trac/scala/ticket/816
237 |
238 | /**
239 | * Specify that the column's values must not be NULL.
240 | */
241 | case object NotNull
242 | extends ColumnOption
243 |
244 | /**
245 | * Specify that the column's values may be NULL.
246 | */
247 | case object Nullable
248 | extends ColumnOption
249 |
250 | /**
251 | * Specify the action that occurs when a value referenced in a foreign
252 | * key constraint is deleted.
253 | */
254 | case class OnDelete(action: ForeignKeyConstraintAction)
255 | extends ForeignKeyOption
256 |
257 | /**
258 | * Specify the action that occurs when a value referenced in a foreign
259 | * key constraint is updated.
260 | */
261 | case class OnUpdate(action: ForeignKeyConstraintAction)
262 | extends ForeignKeyOption
263 |
264 | /**
265 | * Specify the precision for a DECIMAL column.
266 | */
267 | case class Precision(value: Int)
268 | extends ColumnOption {
269 | if (value < 1) {
270 | val message = "The precision cannot be less than one."
271 | throw new IllegalArgumentException(message)
272 | }
273 | }
274 |
275 | /**
276 | * Specify that the column is a primary key.
277 | */
278 | case object PrimaryKey
279 | extends ColumnOption
280 |
281 | /**
282 | * Specify the scale for a DECIMAL column.
283 | */
284 | case class Scale(value: Int)
285 | extends ColumnOption {
286 | if (value < 0) {
287 | val message = "The scale cannot be less than zero."
288 | throw new IllegalArgumentException(message)
289 | }
290 | }
291 |
292 | /**
293 | * Specify that the index on the requires that all the values indexed
294 | * are unique.
295 | */
296 | case object Unique
297 | extends ColumnOption
298 | with IndexOption
299 |
300 | /**
301 | * Specify that the default value for the column for a new row in the
302 | * table is provided by a sequence. Use of AutoIncrement does not
303 | * create an index on the column. If uniqueness needs to be
304 | * guaranteed then a PRIMARY KEY or UNIQUE constraint can be added on
305 | * the column.
306 | *
307 | * For Derby databases this uses GENERATED BY DEFAULT AS IDENTITY.
308 | * The alternate setting GENERATED ALWAYS AS IDENTITY is not used as
309 | * it is not consistent with MySQL and PostgreSQL which permits the
310 | * application to explicitly specify the column's value. See
311 | * http://db.apache.org/derby/docs/10.4/ref/rrefsqlj37836.html .
312 | *
313 | * For MySQL databases this uses the AUTO_INCREMENT attribute; see
314 | * http://dev.mysql.com/doc/refman/5.5/en/create-table.html and
315 | * http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html .
316 | *
317 | * For PostgreSQL databases this replaces the SMALLINT data type with
318 | * SMALLSERIAL, INTEGER with SERIAL and BIGINT with BIGSERIAL; see
319 | * http://www.postgresql.org/docs/9.2/static/datatype-numeric.html#DATATYPE-SERIAL .
320 | * Support for SMALLSERIAL is only available in PostgreSQL 9.2 and
321 | * greater.
322 | */
323 | case object AutoIncrement
324 | extends ColumnOption
325 |
326 | /**
327 | * Maps to GRANT ALL PRIVILEGES.
328 | *
329 | * Since PostgreSQL supports ALL PRIVILEGES on all object types [1],
330 | * AllPrivileges extends all sealed traits that represent privileges
331 | * on database object types, e.g. tables and schemas.
332 | *
333 | * [1] http://www.postgresql.org/docs/9.1/static/sql-grant.html .
334 | */
335 | case object AllPrivileges
336 | extends GrantPrivilegeType
337 | with SchemaPrivilege
338 |
339 | /**
340 | * Maps to GRANT DELETE.
341 | */
342 | case object DeletePrivilege
343 | extends GrantPrivilegeType
344 |
345 | /**
346 | * Maps to GRANT INSERT.
347 | */
348 | case object InsertPrivilege
349 | extends GrantPrivilegeType
350 |
351 | /**
352 | * Maps to GRANT TRIGGER.
353 | */
354 | case object TriggerPrivilege
355 | extends GrantPrivilegeType
356 |
357 | /**
358 | * Scala 2.8 deprecates case classes extending other case classes.
359 | * Instead of implementing PrivilegeWithColumns as a case class to get
360 | * an extractor for the column names implement it as a non-case class
361 | * with an explicit extractor.
362 | */
363 | object PrivilegeWithColumns {
364 | /**
365 | * An extractor to return a sequence of column names.
366 | *
367 | * @param a any object
368 | * @return an optional sequence of column names
369 | */
370 | def unapply(a: Any): Option[Seq[String]] = {
371 | a match {
372 | case p: PrivilegeWithColumns => Some(p.columns)
373 | case _ => None
374 | }
375 | }
376 | }
377 |
378 | /**
379 | * A base class for all privileges that take a list of columns to affect.
380 | */
381 | sealed abstract class PrivilegeWithColumns
382 | extends GrantPrivilegeType {
383 | val columns: Seq[String]
384 | }
385 |
386 | /**
387 | * Maps to GRANT REFERENCES.
388 | */
389 | case class ReferencesPrivilege(override val columns: Seq[String])
390 | extends PrivilegeWithColumns
391 |
392 | /**
393 | * Maps to GRANT SELECT.
394 | */
395 | case class SelectPrivilege(override val columns: Seq[String])
396 | extends PrivilegeWithColumns
397 |
398 | /**
399 | * Maps to GRANT UPDATE.
400 | */
401 | case class UpdatePrivilege(override val columns: Seq[String])
402 | extends PrivilegeWithColumns
403 |
404 | // These next three are here as case objects to allow
405 | // a no-parameters form in user code
406 | case object ReferencesPrivilege
407 | extends GrantPrivilegeType
408 |
409 | case object SelectPrivilege
410 | extends GrantPrivilegeType
411 |
412 | case object UpdatePrivilege
413 | extends GrantPrivilegeType
414 |
415 | /**
416 | * Maps to GRANT USAGE.
417 | */
418 | case object UsagePrivilege
419 | extends SchemaPrivilege
420 |
421 | /**
422 | * This class is defined to prevent ant from recompiling this source
423 | * file.
424 | */
425 | private class Options
426 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/OracleDatabaseAdapter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Map the BIGINT SQL type to a NUMBER(19, 0).
37 | *
38 | * A few other databases, such as Derby, MySQL and PostgreSQL, treat
39 | * BIGINT as a 8-byte signed integer type. On Oracle a NUMBER(19, 0)
40 | * is large enough to store any integers from -9223372036854775808 to
41 | * 9223372036854775807 but not any integers with more digits. A
42 | * NUMBER(19, 0) does allow a larger range of values than the other
43 | * databases, from -9999999999999999999 to 9999999999999999999, but
44 | * this seems like an acceptable solution without using a CHECK
45 | * constraint.
46 | *
47 | * This behavior is different than Oracle's default. If a column is
48 | * defined using "INTEGER" and not a "NUMBER", Oracle uses a
49 | * NUMBER(38) to store it:
50 | *
51 | * http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#sthref218
52 | *
53 | * Using a NUMBER(19, 0) helps ensure the compatibility of any code
54 | * running against an Oracle database so that is does not assume it
55 | * can use 38-digit integer values in case the data needs to be
56 | * exported to another database or if the code needs to work with
57 | * other databases. Columns wishing to use a NUMBER(38) should use a
58 | * DecimalType column.
59 | */
60 | class OracleBigintColumnDefinition
61 | extends DefaultBigintColumnDefinition {
62 | override protected def sql = "NUMBER(19, 0)"
63 | }
64 |
65 | class OracleCharColumnDefinition(useNcharType: Boolean)
66 | extends DefaultCharColumnDefinition {
67 | override protected def sql = {
68 | optionallyAddLimitToDataType(if (useNcharType) "NCHAR" else "CHAR")
69 | }
70 | }
71 |
72 | class OracleDecimalColumnDefinition
73 | extends AbstractDecimalColumnDefinition {
74 | override val decimalSqlName = "NUMBER"
75 | }
76 |
77 | /**
78 | * Map the INTEGER SQL type to a NUMBER(10, 0).
79 | *
80 | * A few other databases, such as Derby, MySQL and PostgreSQL, treat
81 | * INTEGER as a 4-byte signed integer type. On Oracle a NUMBER(10, 0)
82 | * is large enough to store any integers from -2147483648 to
83 | * 2147483647 but not any integers with more digits. A NUMBER(10, 0)
84 | * does allow a larger range of values than the other databases, from
85 | * -9999999999 to 9999999999, but this seems like an acceptable
86 | * solution without using a CHECK constraint.
87 | *
88 | * This behavior is different than Oracle's default. If a column is
89 | * defined using "INTEGER" and not a "NUMBER", Oracle uses a
90 | * NUMBER(38) to store it:
91 | *
92 | * http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#sthref218
93 | *
94 | * Using a NUMBER(10, 0) helps ensure the compatibility of any code
95 | * running against an Oracle database so that is does not assume it
96 | * can use 38-digit integer values in case the data needs to be
97 | * exported to another database or if the code needs to work with
98 | * other databases. Columns wishing to use a NUMBER(38) should use a
99 | * DecimalType column.
100 | */
101 | class OracleIntegerColumnDefinition
102 | extends DefaultIntegerColumnDefinition {
103 | override protected def sql = "NUMBER(10, 0)"
104 | }
105 |
106 | /**
107 | * Map the SMALLINT SQL type to a NUMBER(5, 0).
108 | *
109 | * A few other databases, such as Derby, MySQL and PostgreSQL, treat
110 | * SMALLINT as a 2-byte signed integer type. On Oracle a NUMBER(5, 0)
111 | * is large enough to store any integers from -32768 to 32767 but not
112 | * any integers with more digits. A NUMBER(5, 0) does allow a larger
113 | * range of values than the other databases, from -99999 to 99999, but
114 | * this seems like an acceptable solution without using a CHECK
115 | * constraint.
116 | *
117 | * This behavior is different than Oracle's default. If a column is
118 | * defined using "INTEGER" and not a "NUMBER", Oracle uses a
119 | * NUMBER(38) to store it:
120 | *
121 | * http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements001.htm#sthref218
122 | *
123 | * Using a NUMBER(5, 0) helps ensure the compatibility of any code
124 | * running against an Oracle database so that is does not assume it
125 | * can use 38-digit integer values in case the data needs to be
126 | * exported to another database or if the code needs to work with
127 | * other databases. Columns wishing to use a NUMBER(38) should use a
128 | * DecimalType column.
129 | */
130 | class OracleSmallintColumnDefinition
131 | extends DefaultSmallintColumnDefinition {
132 | override protected def sql = "NUMBER(5, 0)"
133 | }
134 |
135 | class OracleVarbinaryColumnDefinition
136 | extends DefaultVarbinaryColumnDefinition {
137 | override protected def sql = {
138 | if (!limit.isDefined) {
139 | val message = "In Oracle, a RAW column must always specify its size."
140 | throw new IllegalArgumentException(message)
141 | }
142 |
143 | optionallyAddLimitToDataType("RAW")
144 | }
145 | }
146 |
147 | class OracleVarcharColumnDefinition(useNcharType: Boolean)
148 | extends DefaultVarcharColumnDefinition {
149 | override protected def sql = {
150 | optionallyAddLimitToDataType(if (useNcharType) "NVARCHAR2" else "VARCHAR2")
151 | }
152 | }
153 |
154 | class OracleDatabaseAdapter(override val schemaNameOpt: Option[String])
155 | extends DatabaseAdapter(schemaNameOpt) {
156 | override val vendor = Oracle
157 |
158 | override val quoteCharacter = '"'
159 |
160 | override val unquotedNameConverter = UppercaseUnquotedNameConverter
161 |
162 | override val userFactory = PlainUserFactory
163 |
164 | override val alterTableDropForeignKeyConstraintPhrase = "CONSTRAINT"
165 |
166 | override val addingForeignKeyConstraintCreatesIndex = false
167 |
168 | override val supportsCheckConstraints = true
169 |
170 | override def columnDefinitionFactory(columnType: SqlType,
171 | characterSetOpt: Option[CharacterSet]): ColumnDefinition = {
172 | val useNcharType =
173 | characterSetOpt match {
174 | case None => {
175 | false
176 | }
177 | case Some(CharacterSet(Unicode, None)) => {
178 | true
179 | }
180 | case Some(charset @ CharacterSet(Unicode, Some(collation))) => {
181 | logger.warn("Ignoring collation '{}' in '{}' as Oracle only " +
182 | "supports setting the collation using the NLS_SORT " +
183 | "session parameter.",
184 | Array[AnyRef](collation, charset): _*)
185 | true
186 | }
187 | case Some(charset @ CharacterSet(_, _)) => {
188 | logger.warn("Ignoring '{}' as Oracle only supports specifying no " +
189 | "explicit character set encoding, which defaults the " +
190 | "column to use the database's character set, or " +
191 | "Unicode.",
192 | charset)
193 | false
194 | }
195 | }
196 |
197 | columnType match {
198 | case BigintType =>
199 | new OracleBigintColumnDefinition
200 | case BlobType =>
201 | new DefaultBlobColumnDefinition
202 | case BooleanType => {
203 | val message = "Oracle does not support a boolean type, you must " +
204 | "choose a mapping your self."
205 | throw new UnsupportedColumnTypeException(message)
206 | }
207 | case CharType =>
208 | new OracleCharColumnDefinition(useNcharType)
209 | case DecimalType =>
210 | new OracleDecimalColumnDefinition
211 | case IntegerType =>
212 | new OracleIntegerColumnDefinition
213 | case SmallintType =>
214 | new OracleSmallintColumnDefinition
215 | case TimestampType =>
216 | new DefaultTimestampColumnDefinition
217 | case VarbinaryType =>
218 | new OracleVarbinaryColumnDefinition
219 | case VarcharType =>
220 | new OracleVarcharColumnDefinition(useNcharType)
221 | }
222 | }
223 |
224 | override protected def alterColumnSql(schemaNameOpt: Option[String],
225 | columnDefinition: ColumnDefinition): String = {
226 | new java.lang.StringBuilder(512)
227 | .append("ALTER TABLE ")
228 | .append(quoteTableName(schemaNameOpt, columnDefinition.getTableName))
229 | .append(" MODIFY (")
230 | .append(quoteColumnName(columnDefinition.getColumnName))
231 | .append(' ')
232 | .append(columnDefinition.toSql)
233 | .append(')')
234 | .toString
235 | }
236 |
237 | override def removeColumnSql(schemaNameOpt: Option[String],
238 | tableName: String,
239 | columnName: String): String = {
240 | // Oracle requires COLUMN keyword.
241 | new java.lang.StringBuilder(512)
242 | .append("ALTER TABLE ")
243 | .append(quoteTableName(schemaNameOpt, tableName))
244 | .append(" DROP COLUMN ")
245 | .append(quoteColumnName(columnName))
246 | .toString
247 | }
248 |
249 | override def grantOnTableSql(schemaNameOpt: Option[String],
250 | tableName: String,
251 | grantees: Array[User],
252 | privileges: GrantPrivilegeType*): String = {
253 | // Check that no columns are defined for any SELECT privs
254 | for {
255 | SelectPrivilege(columns) <- privileges
256 | if !columns.isEmpty
257 | } {
258 | val message = "Oracle does not support granting select to " +
259 | "individual columns"
260 | throw new IllegalArgumentException(message)
261 | }
262 |
263 | super.grantOnTableSql(schemaNameOpt, tableName, grantees, privileges: _*)
264 | }
265 |
266 | override def revokeOnTableSql(schemaNameOpt: Option[String],
267 | tableName: String,
268 | grantees: Array[User],
269 | privileges: GrantPrivilegeType*): String = {
270 | // Check that no columns are defined for any privs with columns
271 | for {
272 | PrivilegeWithColumns(columns) <- privileges
273 | if !columns.isEmpty
274 | } {
275 | val message = "Oracle does not support revoking permissions from " +
276 | "individual columns"
277 | throw new IllegalArgumentException(message)
278 | }
279 |
280 | super.revokeOnTableSql(schemaNameOpt, tableName, grantees, privileges: _*)
281 | }
282 |
283 | /**
284 | * Return the SQL text for the ON DELETE clause for a foreign key
285 | * relationship.
286 | *
287 | * Oracle rejects adding a foreign key relationship containing the
288 | * "ON DELETE RESTRICT" text, so do not generate any SQL text for
289 | * it. The behavior is the same though. Let any other unsupported
290 | * options pass through, such as "ON DELETE NO ACTION", in case
291 | * Oracle ever does support that clause, which it does not in 10g.
292 | *
293 | * @param onDeleteOpt an Option[OnDelete]
294 | * @return the SQL text to append to the SQL to create a foreign key
295 | * relationship
296 | */
297 | override def onDeleteSql(onDeleteOpt: Option[OnDelete]): String = {
298 | onDeleteOpt match {
299 | case Some(OnDelete(Restrict)) => ""
300 | case opt => super.onDeleteSql(opt)
301 | }
302 | }
303 | }
304 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/PostgresqlDatabaseAdapter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | class PostgresqlBigintColumnDefinition
36 | extends DefaultBigintColumnDefinition
37 | with ColumnSupportsAutoIncrement {
38 | override protected def sql: String = {
39 | if (isAutoIncrement) "BIGSERIAL"
40 | else super.sql
41 | }
42 | }
43 |
44 | class PostgresqlByteaColumnDefinition
45 | extends DefaultBlobColumnDefinition
46 | with ColumnSupportsDefault {
47 | override protected def sql = "BYTEA"
48 | }
49 |
50 | class PostgresqlIntegerColumnDefinition
51 | extends DefaultIntegerColumnDefinition
52 | with ColumnSupportsAutoIncrement {
53 | override protected def sql: String = {
54 | if (isAutoIncrement) "SERIAL"
55 | else super.sql
56 | }
57 | }
58 |
59 | class PostgresqlSmallintColumnDefinition
60 | extends DefaultSmallintColumnDefinition
61 | with ColumnSupportsAutoIncrement {
62 | override protected def sql: String = {
63 | if (isAutoIncrement) "SMALLSERIAL"
64 | else super.sql
65 | }
66 | }
67 |
68 | class PostgresqlDatabaseAdapter(override val schemaNameOpt: Option[String])
69 | extends DatabaseAdapter(schemaNameOpt) {
70 | override val vendor = Postgresql
71 |
72 | override val quoteCharacter = '"'
73 |
74 | override val unquotedNameConverter = LowercaseUnquotedNameConverter
75 |
76 | override val userFactory = PlainUserFactory
77 |
78 | override val alterTableDropForeignKeyConstraintPhrase = "CONSTRAINT"
79 |
80 | override val addingForeignKeyConstraintCreatesIndex = false
81 |
82 | override val supportsCheckConstraints = true
83 |
84 | override def columnDefinitionFactory(columnType: SqlType,
85 | characterSetOpt: Option[CharacterSet]): ColumnDefinition = {
86 | characterSetOpt match {
87 | case None =>
88 | case Some(charset @ CharacterSet(_, _)) =>
89 | logger.warn("Ignoring '{}' as the character set encoding can only " +
90 | "be specified in PostgreSQL when the database is created.",
91 | charset)
92 | }
93 |
94 | columnType match {
95 | case BigintType =>
96 | new PostgresqlBigintColumnDefinition
97 | case BlobType =>
98 | new PostgresqlByteaColumnDefinition
99 | case BooleanType =>
100 | new DefaultBooleanColumnDefinition
101 | case CharType =>
102 | new DefaultCharColumnDefinition
103 | case DecimalType =>
104 | new DefaultDecimalColumnDefinition
105 | case IntegerType =>
106 | new PostgresqlIntegerColumnDefinition
107 | case SmallintType =>
108 | new PostgresqlSmallintColumnDefinition
109 | case TimestampType =>
110 | new DefaultTimestampColumnDefinition
111 | case VarbinaryType =>
112 | new PostgresqlByteaColumnDefinition
113 | case VarcharType =>
114 | new DefaultVarcharColumnDefinition
115 | }
116 | }
117 |
118 | override protected def alterColumnSql(schemaNameOpt: Option[String],
119 | columnDefinition: ColumnDefinition): String = {
120 | new java.lang.StringBuilder(512)
121 | .append("ALTER TABLE ")
122 | .append(quoteTableName(schemaNameOpt, columnDefinition.getTableName))
123 | .append(" ALTER COLUMN ")
124 | .append(quoteColumnName(columnDefinition.getColumnName))
125 | .append(" TYPE ")
126 | .append(columnDefinition.toSql)
127 | .toString
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/RichConnection.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | import java.sql.{
36 | Connection,
37 | PreparedStatement
38 | }
39 |
40 | object RichConnection {
41 | implicit def connectionToRichConnection(c: Connection): RichConnection = {
42 | new RichConnection(c)
43 | }
44 | }
45 |
46 | /**
47 | * A rich Connection class that provides a withPreparedStatement()
48 | * method.
49 | */
50 | class RichConnection(self: Connection) {
51 | def withPreparedStatement[T](sql: String)(f: PreparedStatement => T): T = {
52 | With.autoClosingStatement(self.prepareStatement(sql))(f)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/SqlType.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Sealed abstract base class for the case objects that represent the
37 | * supported SQL types.
38 | */
39 | sealed abstract class SqlType
40 |
41 | case object BigintType extends SqlType
42 | case object BlobType extends SqlType
43 | case object BooleanType extends SqlType
44 | case object CharType extends SqlType
45 | case object DecimalType extends SqlType
46 | case object IntegerType extends SqlType
47 | case object SmallintType extends SqlType
48 | case object TimestampType extends SqlType
49 | case object VarbinaryType extends SqlType
50 | case object VarcharType extends SqlType
51 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/TableColumnDefinition.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * A two-tuple containing a table name and a list of column names.
37 | */
38 | class TableColumnDefinition(val tableName: String,
39 | val columnNames: Array[String])
40 |
41 | /**
42 | * A container class for storing the table and column names a foreign
43 | * key reference is on.
44 | */
45 | class On(definition: TableColumnDefinition) {
46 | val tableName = definition.tableName
47 | val columnNames = definition.columnNames
48 | }
49 |
50 | /**
51 | * A container class for storing the table and column names a foreign
52 | * key reference references.
53 | */
54 | class References(definition: TableColumnDefinition) {
55 | val tableName = definition.tableName
56 | val columnNames = definition.columnNames
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/TableDefinition.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | import scala.collection.mutable
36 |
37 | /**
38 | * A builder to define a table. Its methods add the specified type of
39 | * column to the table's definition.
40 | */
41 | class TableDefinition(adapter: DatabaseAdapter,
42 | tableName: String) {
43 | private val columnDefinitions = new mutable.ListBuffer[ColumnDefinition]
44 |
45 | /**
46 | * Generate a SQL string representation of the columns in the table.
47 | *
48 | * @return the SQL text that defines the columns in the table
49 | */
50 | final def toSql: String = {
51 | val sb = new java.lang.StringBuilder(512)
52 | var firstColumn = true
53 | for (columnDefinition <- columnDefinitions) {
54 | if (firstColumn) {
55 | firstColumn = false
56 | }
57 | else {
58 | sb.append(", ")
59 | }
60 | sb.append(columnDefinition.getColumnName)
61 | .append(' ')
62 | .append(columnDefinition.toSql)
63 | }
64 | sb.toString
65 | }
66 |
67 | /**
68 | * Add any known column type to the table. The actual SQL text used
69 | * to create the column is chosen by the database adapter and may be
70 | * different than the name of the columnType argument.
71 | *
72 | * @param name the column's name
73 | * @param columnType the type of column being added
74 | * @param options a possibly empty array of column options to customize the
75 | * column
76 | * @return the same instance
77 | */
78 | final def column(name: String,
79 | columnType: SqlType,
80 | options: ColumnOption*): TableDefinition = {
81 | val columnDefinition = adapter.newColumnDefinition(tableName,
82 | name,
83 | columnType,
84 | options: _*)
85 | columnDefinitions += columnDefinition
86 | this
87 | }
88 |
89 | /**
90 | * Add a BIGINT column type to the table. The actual SQL text used
91 | * to create the column is chosen by the database adapter and may be
92 | * different than the name of the columnType argument.
93 | *
94 | * @param name the column's name
95 | * @param options a possibly empty array of column options to customize the
96 | * column
97 | * @return the same instance
98 | */
99 | final def bigint(name: String,
100 | options: ColumnOption*): TableDefinition = {
101 | column(name, BigintType, options: _*)
102 | }
103 |
104 | /**
105 | * Add a BLOB column type to the table. The actual SQL text used to
106 | * create the column is chosen by the database adapter and may be
107 | * different than the name of the columnType argument.
108 | *
109 | * @param name the column's name
110 | * @param options a possibly empty array of column options to customize the
111 | * column
112 | * @return the same instance
113 | */
114 | final def blob(name: String,
115 | options: ColumnOption*): TableDefinition = {
116 | column(name, BlobType, options: _*)
117 | }
118 |
119 | /**
120 | * Add a BOOLEAN column type to the table. The actual SQL text used
121 | * to create the column is chosen by the database adapter and may be
122 | * different than the name of the columnType argument.
123 | *
124 | * @param name the column's name
125 | * @param options a possibly empty array of column options to customize the
126 | * column
127 | * @return the same instance
128 | */
129 | final def boolean(name: String,
130 | options: ColumnOption*): TableDefinition = {
131 | column(name, BooleanType, options: _*)
132 | }
133 |
134 | /**
135 | * Add a CHAR column type to the table. The actual SQL text used to
136 | * create the column is chosen by the database adapter and may be
137 | * different than the name of the columnType argument.
138 | *
139 | * @param name the column's name
140 | * @param options a possibly empty array of column options to customize the
141 | * column
142 | * @return the same instance
143 | */
144 | final def char(name: String,
145 | options: ColumnOption*): TableDefinition = {
146 | column(name, CharType, options: _*)
147 | }
148 |
149 | /**
150 | * Add a DECIMAL column type to the table. The actual SQL text used
151 | * to create the column is chosen by the database adapter and may be
152 | * different than the name of the columnType argument.
153 | *
154 | * @param name the column's name
155 | * @param options a possibly empty array of column options to customize the
156 | * column
157 | * @return the same instance
158 | */
159 | final def decimal(name: String,
160 | options: ColumnOption*): TableDefinition = {
161 | column(name, DecimalType, options: _*)
162 | }
163 |
164 | /**
165 | * Add a INTEGER column type to the table. The actual SQL text used
166 | * to create the column is chosen by the database adapter and may be
167 | * different than the name of the columnType argument.
168 | *
169 | * @param name the column's name
170 | * @param options a possibly empty array of column options to customize the
171 | * column
172 | * @return the same instance
173 | */
174 | final def integer(name: String,
175 | options: ColumnOption*): TableDefinition = {
176 | column(name, IntegerType, options: _*)
177 | }
178 |
179 | /**
180 | * Add a SMALLINT column type to the table. The actual SQL text
181 | * used to create the column is chosen by the database adapter and
182 | * may be different than the name of the columnType argument.
183 | *
184 | * @param name the column's name
185 | * @param options a possibly empty array of column options to customize the
186 | * column
187 | * @return the same instance
188 | */
189 | final def smallint(name: String,
190 | options: ColumnOption*): TableDefinition = {
191 | column(name, SmallintType, options: _*)
192 | }
193 |
194 | /**
195 | * Add a TIMESTAMP column type to the table. The actual SQL text
196 | * used to create the column is chosen by the database adapter and
197 | * may be different than the name of the columnType argument.
198 | *
199 | * @param name the column's name
200 | * @param options a possibly empty array of column options to customize the
201 | * column
202 | * @return the same instance
203 | */
204 | final def timestamp(name: String,
205 | options: ColumnOption*): TableDefinition = {
206 | column(name, TimestampType, options: _*)
207 | }
208 |
209 | /**
210 | * Add a VARBINARY column type to the table. The actual SQL text
211 | * used to create the column is chosen by the database adapter and
212 | * may be different than the name of the columnType argument.
213 | *
214 | * @param name the column's name
215 | * @param options a possibly empty array of column options to customize the
216 | * column
217 | * @return the same instance
218 | */
219 | final def varbinary(name: String,
220 | options: ColumnOption*): TableDefinition = {
221 | column(name, VarbinaryType, options: _*)
222 | }
223 |
224 | /**
225 | * Add a VARCHAR column type to the table. The actual SQL text used
226 | * to create the column is chosen by the database adapter and may be
227 | * different than the name of the columnType argument.
228 | *
229 | * @param name the column's name
230 | * @param options a possibly empty array of column options to customize the
231 | * column
232 | * @return the same instance
233 | */
234 | final def varchar(name: String,
235 | options: ColumnOption*): TableDefinition = {
236 | column(name, VarcharType, options: _*)
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/UnquotedNameConverter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Sealed trait that specifies how the database treats unquoted names
37 | * and has a method that performs the same conversion.
38 | */
39 | sealed trait UnquotedNameConverter {
40 | /**
41 | * Apply the same conversion to the unquoted name that the database
42 | * does.
43 | *
44 | * @param name the name to convert
45 | * @return the converted name
46 | */
47 | def apply(name: String): String
48 | }
49 |
50 | /**
51 | * The database does not modify the case of unquoted names.
52 | */
53 | case object CasePreservingUnquotedNameConverter
54 | extends UnquotedNameConverter {
55 | def apply(name: String): String = {
56 | name
57 | }
58 | }
59 |
60 | /**
61 | * Unquoted names are implicitly converted into their lowercase
62 | * variant.
63 | */
64 | case object LowercaseUnquotedNameConverter
65 | extends UnquotedNameConverter {
66 | def apply(name: String): String = {
67 | name.toLowerCase
68 | }
69 | }
70 |
71 | /**
72 | * Unquoted names are implicitly converted into their uppercase
73 | * variant.
74 | */
75 | case object UppercaseUnquotedNameConverter
76 | extends UnquotedNameConverter {
77 | def apply(name: String): String = {
78 | name.toUpperCase
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/User.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Representation of a SQL user. It provides a single #quoted()
37 | * method that returns the user properly quoted for inclusion in a SQL
38 | * statement.
39 | */
40 | sealed abstract class User {
41 | /**
42 | * The user quoted for a SQL statement.
43 | *
44 | * @param unquotedNameConverter the unquoted name converter for the
45 | * database
46 | * @return the user quoted for a SQL statement
47 | */
48 | def quoted(unquotedNameConverter: UnquotedNameConverter): String
49 | }
50 |
51 | /**
52 | * A user consisting only of a user name. Uses double quotation marks
53 | * to quote the user name.
54 | *
55 | * @param userName the user name
56 | */
57 | class PlainUser(userName: String)
58 | extends User {
59 | override def quoted(unquotedNameConverter: UnquotedNameConverter): String = {
60 | '"' + unquotedNameConverter(userName) + '"'
61 | }
62 | }
63 |
64 | /**
65 | * Object to create PlainUser instances with a user name with a nice
66 | * syntax, e.g. User('foobar').
67 | */
68 | object User {
69 | /**
70 | * Given a user name, return a PlainUser instance.
71 | *
72 | * @param userName a user name
73 | * @return a PlainUser with the given name
74 | */
75 | def apply(userName: String): PlainUser = new PlainUser(userName)
76 | }
77 |
78 | object MysqlUser {
79 | /**
80 | * Given a user name and a host name return a User appropriate for a
81 | * MySQL database, see
82 | * http://dev.mysql.com/doc/refman/5.5/en/account-names.html .
83 | *
84 | * @param userName a user name
85 | * @param hostName a host name
86 | */
87 | def apply(userName: String,
88 | hostName: String): MysqlUser = {
89 | new MysqlUser(userName, hostName)
90 | }
91 | }
92 |
93 | /**
94 | * Representation of a SQL user for MySQL which consists of a user
95 | * name and a host name; see
96 | * http://dev.mysql.com/doc/refman/5.5/en/account-names.html .
97 | *
98 | * @param userName the user name
99 | * @param hostName the host name
100 | */
101 | class MysqlUser(userName: String,
102 | hostName: String)
103 | extends User {
104 | override def quoted(unquotedNameConverter: UnquotedNameConverter): String = {
105 | val sb = new java.lang.StringBuilder(64)
106 | sb.append('\'')
107 | .append(unquotedNameConverter(userName))
108 | .append("'@'")
109 | .append(unquotedNameConverter(hostName))
110 | .append('\'')
111 | .toString
112 | }
113 | }
114 |
115 | /**
116 | * A factory for User instances that are built from a user name.
117 | */
118 | abstract class UserFactory[T <: User] {
119 | /**
120 | * Given a user name, return a User instance.
121 | *
122 | * @param userName a user name
123 | * @return a User with the given name
124 | */
125 | def nameToUser(userName: String): T
126 | }
127 |
128 | /**
129 | * Singleton UserFactory that creates PlainUser instances.
130 | */
131 | object PlainUserFactory
132 | extends UserFactory[PlainUser] {
133 | override def nameToUser(userName: String) = User(userName)
134 | }
135 |
136 | /**
137 | * A singleton user factory to create MysqlUser instances. This
138 | * factory uses the input user name and defaults the host name to
139 | * "localhost".
140 | */
141 | object MysqlUserFactory
142 | extends UserFactory[MysqlUser] {
143 | override def nameToUser(userName: String): MysqlUser = {
144 | new MysqlUser(userName, "localhost")
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/Vendor.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | /**
36 | * Base sealed trait for the objects that refer to different
37 | * databases.
38 | */
39 | sealed trait Vendor
40 |
41 | case object Derby
42 | extends Vendor
43 | case object Mysql
44 | extends Vendor
45 | case object Oracle
46 | extends Vendor
47 | case object Postgresql
48 | extends Vendor
49 |
50 | object Vendor {
51 | /**
52 | * Return the database vendor for the given database driver class
53 | * name.
54 | *
55 | * @param driverClassName the class name of the JDBC database driver
56 | * @return the corresponding Vendor object for the database
57 | * @throws IllegalArgumentException if the argument is null,
58 | * scala.MatchError if an appropriate vendor cannot be found
59 | */
60 | def forDriver(driverClassName: String): Vendor = {
61 | driverClassName match {
62 | case "com.mysql.jdbc.Driver" =>
63 | Mysql
64 |
65 | case "oracle.jdbc.driver.OracleDriver" =>
66 | Oracle
67 |
68 | case "oracle.jdbc.OracleDriver" =>
69 | Oracle
70 |
71 | case "org.apache.derby.jdbc.EmbeddedDriver" =>
72 | Derby
73 |
74 | case "org.apache.derby.jdbc.ClientDriver" =>
75 | Derby
76 |
77 | case "org.postgresql.Driver" =>
78 | Postgresql
79 |
80 | case null =>
81 | throw new IllegalArgumentException("Must pass a non-null JDBC " +
82 | "driver class name to this " +
83 | "function.")
84 |
85 | case _ =>
86 | throw new scala.MatchError("No vendor can be found for the JDBC " +
87 | "driver class '" +
88 | driverClassName +
89 | "'.'")
90 | }
91 | }
92 |
93 | /**
94 | * Return the database vendor for the given database driver class.
95 | *
96 | * @param driverClass the class of the JDBC database driver
97 | * @return the corresponding Vendor object for the database
98 | * @throws IllegalArgumentException if the argument is null,
99 | * scala.MatchError if an appropriate vendor cannot be found
100 | */
101 | def forDriver(driverClass: Class[_]): Vendor = {
102 | if (driverClass eq null) {
103 | val message = "Must pass a non-null JDBC driver class to this function."
104 | throw new IllegalArgumentException(message)
105 | }
106 | else {
107 | forDriver(driverClass.getName)
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/scala/com/imageworks/migration/With.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration
34 |
35 | import org.slf4j.LoggerFactory
36 |
37 | import java.sql.{
38 | Connection,
39 | ResultSet,
40 | Statement
41 | }
42 | import java.util.jar.JarFile
43 |
44 | /**
45 | * Utility object that contains functions that ensure a resource is
46 | * released once it has been used. Each function takes resource
47 | * object that has a method to release the resource, such as close(),
48 | * and a closure to that operates on the resource. After the closure
49 | * has completed, either normally via a return or by throwing an
50 | * exception, the resource is released.
51 | */
52 | object With {
53 | private final val logger = LoggerFactory.getLogger(this.getClass)
54 |
55 | /**
56 | * Given a resource and two functions, the first, a closer function
57 | * that closes or releases the resource, and the second, a body
58 | * function that uses the resource, invoke the body function on the
59 | * resource and then ensure that the closer function closes the
60 | * resource, regardless if the body function returns normally or
61 | * throws an exception.
62 | *
63 | * @param resource a resource to use and then close
64 | * @param closerDescription a textual description of what the closer
65 | * does; used to log any exception thrown by closer when the
66 | * body also throws an exception since in that case the
67 | * closer's exception will be suppressed and not thrown to
68 | * the caller
69 | * @param closer the function that closes the resource
70 | * @param body the function that uses the resource
71 | * @return the result of invoking body on the resource
72 | * @throws any exception that invoking body on the resource throws
73 | */
74 | def resource[A, B](resource: A, closerDescription: String)(closer: A => Unit)(body: A => B): B = {
75 | var primaryException: Throwable = null
76 | try {
77 | body(resource)
78 | }
79 | catch {
80 | case e: Throwable => {
81 | primaryException = e
82 | throw e
83 | }
84 | }
85 | finally {
86 | if (primaryException eq null) {
87 | closer(resource)
88 | }
89 | else {
90 | try {
91 | closer(resource)
92 | }
93 | catch {
94 | case e: Throwable =>
95 | logger.warn("Suppressing exception when " +
96 | closerDescription +
97 | ':',
98 | e)
99 | }
100 | }
101 | }
102 | }
103 |
104 | /**
105 | * Take a SQL connection, pass it to a closure and ensure that the
106 | * connection is closed after the closure returns, either normally
107 | * or by an exception. If the closure returns normally, return its
108 | * result.
109 | *
110 | * @param connection a SQL connection
111 | * @param f a Function1[C <: Connection,R] that operates on the
112 | * connection
113 | * @return the result of f
114 | */
115 | def autoClosingConnection[C <: Connection, R](connection: C)(f: C => R): R = {
116 | resource(connection, "closing connection")(_.close())(f)
117 | }
118 |
119 | /**
120 | * Take a SQL connection, save its current auto-commit mode, put the
121 | * connection into the requested auto-commit mode, pass the
122 | * connection to a closure and ensure that the connection's
123 | * auto-commit mode is restored after the closure returns, either
124 | * normally or by an exception. If the closure returns normally,
125 | * return its result.
126 | *
127 | * The connection's auto-commit mode is always set, even if it is
128 | * the same as the requested mode. This is done to ensure any work
129 | * the database would normally do when setting the auto-commit mode
130 | * is always done.
131 | *
132 | * @param connection a SQL connection
133 | * @param mode the auto-commit mode the connection's state should be
134 | * put in
135 | * @param f a Function1[C <: Connection,R] that operates on the
136 | * connection
137 | * @return the result of f
138 | */
139 | def autoRestoringConnection[C <: Connection, R](connection: C,
140 | mode: Boolean)(f: C => R): R = {
141 | val currentMode = connection.getAutoCommit
142 | With.resource(connection, "restoring connection auto-commit")(_.setAutoCommit(currentMode)) { c =>
143 | c.setAutoCommit(mode)
144 | f(c)
145 | }
146 | }
147 |
148 | /**
149 | * Take a SQL connection, pass it to a closure and ensure that any
150 | * work done on the connection after the closure returns is either
151 | * left alone, committed or rolled back depending upon the given
152 | * setting. If the closure returns normally, return its result.
153 | * The connection's auto-commit mode will be set and restored.
154 | *
155 | * @param connection a SQL connection
156 | * @param commitBehavior the operation to implement on the
157 | * connection after f returns normally or via throwing an
158 | * exception
159 | * @param f a Function1[C <: Connection,R] that operates on the
160 | * connection
161 | * @return the result of f
162 | */
163 | def autoCommittingConnection[C <: Connection, R](connection: C,
164 | commitBehavior: CommitBehavior)(f: C => R): R = {
165 | val newCommitBehavior =
166 | commitBehavior match {
167 | case AutoCommit => true
168 | case CommitUponReturnOrException => false
169 | case CommitUponReturnOrRollbackUponException => false
170 | }
171 |
172 | With.autoRestoringConnection(connection, newCommitBehavior) { c =>
173 | commitBehavior match {
174 | case AutoCommit => {
175 | f(connection)
176 | }
177 |
178 | case CommitUponReturnOrException => {
179 | With.resource(connection, "committing transaction")(_.commit())(f)
180 | }
181 |
182 | case CommitUponReturnOrRollbackUponException => {
183 | val result =
184 | try {
185 | f(connection)
186 | }
187 | catch {
188 | case e1: Throwable => {
189 | try {
190 | connection.rollback()
191 | }
192 | catch {
193 | case e2: Throwable =>
194 | logger.warn("Suppressing exception when rolling back" +
195 | "transaction:", e2)
196 | }
197 | throw e1
198 | }
199 | }
200 |
201 | connection.commit()
202 |
203 | result
204 | }
205 | }
206 | }
207 | }
208 |
209 | /**
210 | * Take a SQL statement, pass it to a closure and ensure that the
211 | * statement is closed after the closure returns, either normally or
212 | * by an exception. If the closure returns normally, return its
213 | * result.
214 | *
215 | * @param statement a SQL statement
216 | * @param f a Function1[S <: Statement,R] that operates on the
217 | * statement
218 | * @return the result of f
219 | */
220 | def autoClosingStatement[S <: Statement, R](statement: S)(f: S => R): R = {
221 | resource(statement, "closing statement")(_.close())(f)
222 | }
223 |
224 | /**
225 | * Take a SQL result set, pass it to a closure and ensure that the
226 | * result set is closed after the closure returns, either normally
227 | * or by an exception. If the closure returns normally, return its
228 | * result.
229 | *
230 | * @param resultSet a SQL result set
231 | * @param f a Function1[RS <: ResultSet,R] that operates on the
232 | * result set
233 | * @return the result of f
234 | */
235 | def autoClosingResultSet[RS <: ResultSet, R](resultSet: RS)(f: RS => R): R = {
236 | resource(resultSet, "closing result set")(_.close())(f)
237 | }
238 |
239 | /**
240 | * Take a jar file, pass it to a closure and ensure that the jar
241 | * file is closed after the closure returns, either normally or by
242 | * an exception. If the closure returns normally, return its
243 | * result.
244 | *
245 | * @param jarFile a jar file
246 | * @param f a Function1[J <: JarFile,R] that operates on the jar
247 | * file
248 | * @return the result of f
249 | */
250 | def jarFile[J <: JarFile, R](jarFile: J)(f: J => R): R = {
251 | resource(jarFile, "closing jar file")(_.close())(f)
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/test/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # This file is used to make the test suite generate no output. If the
2 | # test suite fails, then increase the logging level. There are some
3 | # expected failures generated during the test suite.
4 |
5 | log4j.rootLogger = FATAL,STDOUT
6 |
7 | # Keep the audit, resultset, and sqltiming loggers turned off by default.
8 | # See the log4jdbc docs for more information about these loggers.
9 | log4j.logger.jdbc.audit = FATAL,STDOUT
10 | log4j.logger.jdbc.resultset = FATAL,STDOUT
11 | log4j.logger.jdbc.sqltiming = FATAL,STDOUT
12 |
13 | log4j.appender.STDOUT = org.apache.log4j.ConsoleAppender
14 | log4j.appender.STDOUT.layout = org.apache.log4j.PatternLayout
15 | log4j.appender.STDOUT.layout.ConversionPattern = %d %p [%t] %C{1} - %m%n
16 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/DatabaseAdapterTests.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests
34 |
35 | import com.imageworks.migration.{
36 | DatabaseAdapter,
37 | Derby,
38 | DerbyDatabaseAdapter,
39 | Mysql,
40 | MysqlDatabaseAdapter,
41 | Oracle,
42 | OracleDatabaseAdapter,
43 | Postgresql,
44 | PostgresqlDatabaseAdapter
45 | }
46 |
47 | import org.junit.Assert._
48 | import org.junit.Test
49 |
50 | class DatabaseAdapterTests {
51 | @Test
52 | def forVendor() {
53 | assertEquals(classOf[DerbyDatabaseAdapter],
54 | DatabaseAdapter.forVendor(Derby, None).getClass)
55 |
56 | assertEquals(classOf[MysqlDatabaseAdapter],
57 | DatabaseAdapter.forVendor(Mysql, None).getClass)
58 |
59 | assertEquals(classOf[OracleDatabaseAdapter],
60 | DatabaseAdapter.forVendor(Oracle, None).getClass)
61 |
62 | assertEquals(classOf[PostgresqlDatabaseAdapter],
63 | DatabaseAdapter.forVendor(Postgresql, None).getClass)
64 | }
65 |
66 | @Test(expected = classOf[IllegalArgumentException])
67 | def forNullDriverClassThrows() {
68 | DatabaseAdapter.forVendor(null, None)
69 | }
70 |
71 | @Test
72 | def roundTrip() {
73 | for (vendor <- List(Derby, Mysql, Postgresql, Oracle)) {
74 | val adapter = DatabaseAdapter.forVendor(vendor, None)
75 | assertSame(vendor, adapter.vendor)
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/JavaMigratorTests.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests
34 |
35 | import com.imageworks.migration.{
36 | AutoCommit,
37 | DuplicateMigrationDescriptionException,
38 | DuplicateMigrationVersionException,
39 | JavaMigrator,
40 | With
41 | }
42 |
43 | import org.junit.Assert._
44 | import org.junit.{
45 | Before,
46 | Test
47 | }
48 |
49 | class JavaMigratorTests {
50 | private var javaMigrator: JavaMigrator = _
51 |
52 | @Before
53 | def setUp() {
54 | val connectionBuilder = TestDatabase.getAdminConnectionBuilder
55 | val databaseAdapter = TestDatabase.getDatabaseAdapter
56 |
57 | javaMigrator = new JavaMigrator(connectionBuilder, databaseAdapter)
58 |
59 | connectionBuilder.withConnection(AutoCommit) { c =>
60 | val tableNames = javaMigrator.getTableNames
61 | val iter = tableNames.iterator
62 | while (iter.hasNext) {
63 | val tableName = iter.next()
64 | val tn = tableName.toLowerCase
65 | if (tn == "schema_migrations" || tn.startsWith("scala_migrations_")) {
66 | val sql = "DROP TABLE " + databaseAdapter.quoteTableName(tn)
67 | With.autoClosingStatement(c.prepareStatement(sql)) { _.execute() }
68 | }
69 | }
70 | }
71 | }
72 |
73 | @Test(expected = classOf[DuplicateMigrationDescriptionException])
74 | def duplicateDescriptionsThrows() {
75 | javaMigrator.installAllMigrations(
76 | "com.imageworks.migration.tests.duplicate_descriptions",
77 | false)
78 | }
79 |
80 | @Test(expected = classOf[DuplicateMigrationVersionException])
81 | def duplicateVersionsThrows() {
82 | javaMigrator.installAllMigrations(
83 | "com.imageworks.migration.tests.duplicate_versions",
84 | false)
85 | }
86 |
87 | @Test
88 | def migrateUpAndDown() {
89 | // There should be no tables in the schema initially.
90 | assertEquals(0, javaMigrator.getTableNames.size)
91 |
92 | // Migrate down the whole way.
93 | javaMigrator.removeAllMigrations(
94 | "com.imageworks.migration.tests.up_and_down",
95 | false)
96 |
97 | // The database should not be completely migrated.
98 | assertNotNull(javaMigrator.whyNotMigrated(
99 | "com.imageworks.migration.tests.up_and_down",
100 | false))
101 |
102 | // An empty array of Strings so that getTableNames.toArray returns
103 | // an Array[String] and not Array[AnyRef].
104 | val ea = new Array[String](0)
105 |
106 | // There should only be the schema_migrations table now.
107 | assertEquals(1, javaMigrator.getTableNames.size)
108 | assertFalse(javaMigrator.getTableNames.toArray(ea).find(_.toLowerCase == "scala_migrations_people").isDefined)
109 |
110 | // Apply all the migrations.
111 | javaMigrator.installAllMigrations(
112 | "com.imageworks.migration.tests.up_and_down",
113 | false)
114 |
115 | assertEquals(3, javaMigrator.getTableNames.size)
116 | assertTrue(javaMigrator.getTableNames.toArray(ea).find(_.toLowerCase == "scala_migrations_people").isDefined)
117 |
118 | // The database should be completely migrated.
119 | assertNull(javaMigrator.whyNotMigrated(
120 | "com.imageworks.migration.tests.up_and_down",
121 | false))
122 |
123 | // Migrate down the whole way.
124 | javaMigrator.removeAllMigrations(
125 | "com.imageworks.migration.tests.up_and_down",
126 | false)
127 |
128 | // There should only be the schema_migrations table now.
129 | assertEquals(1, javaMigrator.getTableNames.size)
130 | assertFalse(javaMigrator.getTableNames.toArray(ea).find(_.toLowerCase == "scala_migrations_people").isDefined)
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/OptionsTests.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests
34 |
35 | import com.imageworks.migration.Limit
36 |
37 | import org.junit.Test
38 |
39 | class OptionsTests {
40 | @Test(expected = classOf[IllegalArgumentException])
41 | def limitNegativeOneIntThrows() {
42 | Limit(-1)
43 | }
44 |
45 | @Test(expected = classOf[IllegalArgumentException])
46 | def limitNegativeOneStringThrows() {
47 | Limit("-1")
48 | }
49 |
50 | @Test
51 | def limitZeroIntOk() {
52 | Limit(0)
53 | }
54 |
55 | @Test
56 | def limitZeroStringOk() {
57 | Limit("0")
58 | }
59 |
60 | @Test
61 | def limitOneIntOk() {
62 | Limit(1)
63 | }
64 |
65 | @Test
66 | def limitOneStringOk() {
67 | Limit("1")
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/TestDatabase.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests
34 |
35 | import com.imageworks.migration.{
36 | AutoCommit,
37 | ConnectionBuilder,
38 | DatabaseAdapter,
39 | DerbyDatabaseAdapter,
40 | MysqlDatabaseAdapter,
41 | PostgresqlDatabaseAdapter,
42 | With
43 | }
44 |
45 | import java.sql.{
46 | DriverManager,
47 | SQLException
48 | }
49 |
50 | /**
51 | * Sealed trait abstracting the database to use for testing.
52 | */
53 | sealed trait TestDatabase {
54 | /**
55 | * Get the schema name the tests are being run in.
56 | */
57 | def getSchemaName: String
58 |
59 | /**
60 | * Get the username of the admin account.
61 | */
62 | def getAdminAccountName: String
63 |
64 | /**
65 | * Get a connection builder that builds connections with access to
66 | * the entire schema.
67 | */
68 | def getAdminConnectionBuilder: ConnectionBuilder
69 |
70 | /**
71 | * Get the username of the user account.
72 | */
73 | def getUserAccountName: String
74 |
75 | /**
76 | * Get a connection builder that builds connections that connect as
77 | * a user with restricted privileges.
78 | */
79 | def getUserConnectionBuilder: ConnectionBuilder
80 |
81 | /**
82 | * The DatabaseAdapter to use for the test database.
83 | */
84 | def getDatabaseAdapter: DatabaseAdapter
85 | }
86 |
87 | /**
88 | * Derby test database implementation.
89 | */
90 | object DerbyTestDatabase
91 | extends TestDatabase {
92 | // Username of the admin account, which will be the owner of the
93 | // database.
94 | private val adminUsername = "admin"
95 |
96 | override def getAdminAccountName = adminUsername
97 |
98 | // Password for the admin account.
99 | private val adminPassword = "foobar"
100 |
101 | // Username of the user account.
102 | private val userUsername = "user"
103 |
104 | override def getUserAccountName = userUsername
105 |
106 | // Password for the user account.
107 | private val userPassword = "baz"
108 |
109 | // The base JDBC URL.
110 | private val url = {
111 | "jdbc:derby:memory:" + System.currentTimeMillis.toString
112 | }
113 |
114 | // Set the Derby system home directory to "target/test-databases" so
115 | // the derby.log file and all databases will be placed in there.
116 | System.getProperties.setProperty("derby.system.home",
117 | "target/test-databases")
118 |
119 | // Load the Derby database driver.
120 | Class.forName("org.apache.derby.jdbc.EmbeddedDriver")
121 |
122 | // Create the database, set it up for connection and SQL
123 | // authorization and then shut it down, so the next connection will
124 | // "boot" it with connection and SQL authorizations enabled.
125 |
126 | // Create the database.
127 | With.autoClosingConnection(DriverManager.getConnection(
128 | url + ";create=true",
129 | adminUsername,
130 | adminPassword)) { c =>
131 | TestDatabase.execute(
132 | getAdminConnectionBuilder,
133 | """CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(
134 | 'derby.connection.requireAuthentication', 'true')""")
135 |
136 | // Setting this property cannot be undone. See
137 | // http://db.apache.org/derby/docs/10.7/ref/rrefpropersqlauth.html .
138 | TestDatabase.execute(
139 | getAdminConnectionBuilder,
140 | """CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(
141 | 'derby.database.sqlAuthorization', 'true')""")
142 |
143 | TestDatabase.execute(
144 | getAdminConnectionBuilder,
145 | """CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(
146 | 'derby.authentication.provider', 'BUILTIN')""")
147 |
148 | TestDatabase.execute(
149 | getAdminConnectionBuilder,
150 | """CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(
151 | 'derby.user.""" + adminUsername + """', '""" + adminPassword + """')""")
152 |
153 | TestDatabase.execute(
154 | getAdminConnectionBuilder,
155 | """CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(
156 | 'derby.user.""" + userUsername + """', '""" + userPassword + """')""")
157 | }
158 |
159 | // Shutdown Derby.
160 | try {
161 | With.autoClosingConnection(DriverManager.getConnection(
162 | url + ";shutdown=true",
163 | adminUsername,
164 | adminPassword)) { _ =>
165 | }
166 | }
167 | catch {
168 | // For JDBC4 (JDK 1.6), a
169 | // java.sql.SQLNonTransientConnectionException is thrown, but this
170 | // exception class does not exist in JDK 1.5, so catch a
171 | // java.sql.SQLException instead.
172 | case _: SQLException =>
173 | }
174 |
175 | override def getSchemaName: String = {
176 | adminUsername
177 | }
178 |
179 | override def getAdminConnectionBuilder: ConnectionBuilder = {
180 | new ConnectionBuilder(url, adminUsername, adminPassword)
181 | }
182 |
183 | override def getUserConnectionBuilder: ConnectionBuilder = {
184 | new ConnectionBuilder(url, userUsername, userPassword)
185 | }
186 |
187 | override def getDatabaseAdapter: DatabaseAdapter = {
188 | new DerbyDatabaseAdapter(Some(getSchemaName))
189 | }
190 | }
191 |
192 | /**
193 | * MySQL test database implementation. Enabled when the Java
194 | * "scala-migrations.db.vendor" property is set to "mysql".
195 | *
196 | * Assumes the following setup:
197 | *
198 | * 1) A user named "test-admin" with password "test-admin" exists.
199 | * 2) The "test-admin" user owns a database named "test".
200 | * 3) The "test-admin" user has rights to grant other rights in the
201 | * "test" database.
202 | * 4) A user named "test-user" with password "test-user" exists.
203 | * 5) The "test-user" has no rights to the "test" database.
204 | *
205 | * To override the defaults, set any of the following Java properties:
206 | *
207 | * "scala-migrations.db.db": database name to test with ("test")
208 | * "scala-migrations.db.admin.name": admin user username ("test-admin")
209 | * "scala-migrations.db.admin.passwd": admin user password ("test-admin")
210 | * "scala-migrations.db.user.name": plain user username ("test-user")
211 | * "scala-migrations.db.user.passwd": plain user password ("test-user")
212 | */
213 | object MysqlTestDatabase
214 | extends TestDatabase {
215 | // Username of the admin account, which will be the owner of the
216 | // database.
217 | private val adminUsername = {
218 | System.getProperty(TestDatabase.adminUserNameProperty, "test-admin")
219 | }
220 |
221 | override def getAdminAccountName = adminUsername
222 |
223 | // Password for the admin account.
224 | private val adminPassword = {
225 | System.getProperty(TestDatabase.adminUserPasswordProperty, "test-admin")
226 | }
227 |
228 | // Username of the user account.
229 | private val userUsername = {
230 | System.getProperty(TestDatabase.userUserNameProperty, "test-user")
231 | }
232 |
233 | override def getUserAccountName = userUsername
234 |
235 | // Password for the user account.
236 | private val userPassword = {
237 | System.getProperty(TestDatabase.userUserPasswordProperty, "test-user")
238 | }
239 |
240 | // MySQL doesn't have a separate concept for schemas, in MySQL a
241 | // schema is a database, so use the database name property value for
242 | // the schema name.
243 | override def getSchemaName: String = {
244 | System.getProperty(TestDatabase.databaseNameProperty, "test")
245 | }
246 |
247 | // The base JDBC URL.
248 | private val url = {
249 | "jdbc:mysql://localhost/" + getSchemaName
250 | }
251 |
252 | // Load the MySQL database driver.
253 | Class.forName("com.mysql.jdbc.Driver")
254 |
255 | override def getAdminConnectionBuilder: ConnectionBuilder = {
256 | new ConnectionBuilder(url, adminUsername, adminPassword)
257 | }
258 |
259 | override def getUserConnectionBuilder: ConnectionBuilder = {
260 | new ConnectionBuilder(url, userUsername, userPassword)
261 | }
262 |
263 | override def getDatabaseAdapter: DatabaseAdapter = {
264 | new MysqlDatabaseAdapter(Some(getSchemaName))
265 | }
266 | }
267 |
268 | /**
269 | * PostgreSQL test database implementation. Enabled when the Java
270 | * "scala-migrations.db.vendor" property is set to "postgresql".
271 | *
272 | * Assumes the following setup:
273 | *
274 | * 1) A user named "test-admin" with password "test-admin" exists.
275 | * 2) The "test-admin" user owns a database named "test".
276 | * 3) The "test-admin" user has rights to grant other rights in the
277 | * "test" database.
278 | * 4) A user named "test-user" with password "test-user" exists.
279 | * 5) The "test-user" has no rights to the "test" database.
280 | * 6) The unit tests are performed in the "public" schema.
281 | *
282 | * The above can be set up with the following commands, which are
283 | * known to work on PostgreSQL 9.1:
284 | *
285 | * $ su - postgres
286 | * $ createuser -e -D -E -P -R -S test-admin
287 | * $ createdb -e -E UTF-8 -O test-admin test
288 | * $ createuser -e -D -E -P -R -S test-user
289 | *
290 | * To override the defaults, set any of the following Java properties:
291 | *
292 | * "scala-migrations.db.db": database name to test with ("test")
293 | * "scala-migrations.db.schema": schema name to test with ("public")
294 | * "scala-migrations.db.admin.name": admin user username ("test-admin")
295 | * "scala-migrations.db.admin.passwd": admin user password ("test-admin")
296 | * "scala-migrations.db.user.name": plain user username ("test-user")
297 | * "scala-migrations.db.user.passwd": plain user password ("test-user")
298 | */
299 | object PostgresqlTestDatabase
300 | extends TestDatabase {
301 | // Username of the admin account, which will be the owner of the
302 | // database.
303 | private val adminUsername = {
304 | System.getProperty(TestDatabase.adminUserNameProperty, "test-admin")
305 | }
306 |
307 | override def getAdminAccountName = adminUsername
308 |
309 | // Password for the admin account.
310 | private val adminPassword = {
311 | System.getProperty(TestDatabase.adminUserPasswordProperty, "test-admin")
312 | }
313 |
314 | // Username of the user account.
315 | private val userUsername = {
316 | System.getProperty(TestDatabase.userUserNameProperty, "test-user")
317 | }
318 |
319 | override def getUserAccountName = userUsername
320 |
321 | // Password for the user account.
322 | private val userPassword = {
323 | System.getProperty(TestDatabase.userUserPasswordProperty, "test-user")
324 | }
325 |
326 | override def getSchemaName: String = {
327 | System.getProperty(TestDatabase.schemaNameProperty, "public")
328 | }
329 |
330 | // The base JDBC URL.
331 | private val url = {
332 | "jdbc:postgresql://localhost/" +
333 | System.getProperty(TestDatabase.databaseNameProperty, "test")
334 | }
335 |
336 | // Load the PostgreSQL database driver.
337 | Class.forName("org.postgresql.Driver")
338 |
339 | override def getAdminConnectionBuilder: ConnectionBuilder = {
340 | new ConnectionBuilder(url, adminUsername, adminPassword)
341 | }
342 |
343 | override def getUserConnectionBuilder: ConnectionBuilder = {
344 | new ConnectionBuilder(url, userUsername, userPassword)
345 | }
346 |
347 | override def getDatabaseAdapter: DatabaseAdapter = {
348 | new PostgresqlDatabaseAdapter(Some(getSchemaName))
349 | }
350 | }
351 |
352 | /**
353 | * Object which builds the correct TestDatabase according to the
354 | * system property "scala-migrations.db.vendor", defaulting to Derby if
355 | * the property is not set.
356 | */
357 | object TestDatabase
358 | extends TestDatabase {
359 | val adminUserNameProperty = "scala-migrations.db.admin.name"
360 | val adminUserPasswordProperty = "scala-migrations.db.admin.passwd"
361 | val databaseNameProperty = "scala-migrations.db.db"
362 | val schemaNameProperty = "scala-migrations.db.schema"
363 | val userUserNameProperty = "scala-migrations.db.user.name"
364 | val userUserPasswordProperty = "scala-migrations.db.user.passwd"
365 | val vendorNameProperty = "scala-migrations.db.vendor"
366 |
367 | private val db: TestDatabase = {
368 | System.getProperty(vendorNameProperty, "derby") match {
369 | case "derby" =>
370 | DerbyTestDatabase
371 | case "mysql" =>
372 | MysqlTestDatabase
373 | case "postgresql" =>
374 | PostgresqlTestDatabase
375 | case v =>
376 | throw new RuntimeException("Unexpected value for \"" +
377 | vendorNameProperty +
378 | "\" property: " +
379 | v)
380 | }
381 | }
382 |
383 | override def getSchemaName = db.getSchemaName
384 |
385 | override def getAdminAccountName = db.getAdminAccountName
386 |
387 | override def getAdminConnectionBuilder = db.getAdminConnectionBuilder
388 |
389 | override def getUserAccountName = db.getUserAccountName
390 |
391 | override def getUserConnectionBuilder = db.getUserConnectionBuilder
392 |
393 | override def getDatabaseAdapter = db.getDatabaseAdapter
394 |
395 | def execute(connectionBuilder: ConnectionBuilder,
396 | sql: String): Boolean = {
397 | connectionBuilder.withConnection(AutoCommit) { c =>
398 | With.autoClosingStatement(c.prepareStatement(sql)) { s =>
399 | s.execute()
400 | }
401 | }
402 | }
403 | }
404 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/VendorTests.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests
34 |
35 | import com.imageworks.migration.{
36 | Derby,
37 | Mysql,
38 | Oracle,
39 | Postgresql,
40 | Vendor
41 | }
42 |
43 | import org.junit.Assert._
44 | import org.junit.Test
45 |
46 | class VendorTests {
47 | @Test
48 | def forDriver() {
49 | assertSame(Derby,
50 | Vendor.forDriver("org.apache.derby.jdbc.EmbeddedDriver"))
51 |
52 | assertSame(Derby,
53 | Vendor.forDriver(classOf[org.apache.derby.jdbc.EmbeddedDriver]))
54 |
55 | assertSame(Derby,
56 | Vendor.forDriver("org.apache.derby.jdbc.ClientDriver"))
57 |
58 | assertSame(Mysql,
59 | Vendor.forDriver("com.mysql.jdbc.Driver"))
60 |
61 | assertSame(Oracle,
62 | Vendor.forDriver("oracle.jdbc.OracleDriver"))
63 |
64 | assertSame(Postgresql,
65 | Vendor.forDriver("org.postgresql.Driver"))
66 | }
67 |
68 | @Test(expected = classOf[scala.MatchError])
69 | def forNonExistentDriverThrows() {
70 | Vendor.forDriver("no.such.driver")
71 | }
72 |
73 | @Test(expected = classOf[scala.MatchError])
74 | def forNonDriverClassThrows() {
75 | Vendor.forDriver(classOf[String])
76 | }
77 |
78 | @Test(expected = classOf[IllegalArgumentException])
79 | def forNullDriverClassThrows() {
80 | Vendor.forDriver(null: Class[_])
81 | }
82 |
83 | @Test(expected = classOf[IllegalArgumentException])
84 | def forNullDriverClassNameThrows() {
85 | Vendor.forDriver(null: String)
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/WithTests.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests
34 |
35 | import com.imageworks.migration.With
36 |
37 | import org.jmock.{
38 | AbstractExpectations,
39 | Expectations,
40 | Mockery
41 | }
42 |
43 | import org.junit.Assert._
44 | import org.junit.{
45 | Before,
46 | Test
47 | }
48 |
49 | import java.sql.{
50 | ResultSet,
51 | SQLException
52 | }
53 |
54 | class WithTests {
55 | private val context = new Mockery
56 |
57 | @Test
58 | def withResultSetClosesOnNormalReturn() {
59 | val mockResultSet = context.mock(classOf[ResultSet])
60 |
61 | context.checking(new Expectations {
62 | oneOf(mockResultSet).close()
63 | })
64 |
65 | var rs1: ResultSet = null
66 |
67 | val result = With.autoClosingResultSet(mockResultSet) { rs2 =>
68 | rs1 = rs2
69 | "foobar"
70 | }
71 |
72 | assertSame(mockResultSet, rs1)
73 | assertEquals("foobar", result)
74 | context.assertIsSatisfied()
75 | }
76 |
77 | @Test
78 | def withResultSetClosesOnThrow() {
79 | val mockResultSet = context.mock(classOf[ResultSet])
80 |
81 | val e1 = new RuntimeException
82 | val e2 = new SQLException
83 |
84 | context.checking(new Expectations {
85 | oneOf(mockResultSet).close()
86 | will(AbstractExpectations.throwException(e2))
87 | })
88 |
89 | var caughtExceptionOpt: Option[Exception] = None
90 | var rs1: ResultSet = null
91 |
92 | try {
93 | With.autoClosingResultSet(mockResultSet) { rs2 =>
94 | rs1 = rs2
95 | throw e1
96 | }
97 | }
98 | catch {
99 | case e: Exception => caughtExceptionOpt = Some(e)
100 | }
101 |
102 | assertSame(mockResultSet, rs1)
103 | assertTrue("Failed to catch exception.", caughtExceptionOpt.isDefined)
104 | assertSame("Failed to catch expected exception.",
105 | e1, caughtExceptionOpt.get)
106 | context.assertIsSatisfied()
107 | }
108 |
109 | @Test
110 | def closeExceptionIsNotSuppressedIfClosureReturnsNormally() {
111 | val mockResultSet = context.mock(classOf[ResultSet])
112 |
113 | val e1 = new SQLException
114 |
115 | context.checking(new Expectations {
116 | oneOf(mockResultSet).close()
117 | will(AbstractExpectations.throwException(e1))
118 | })
119 |
120 | var caughtExceptionOpt: Option[Exception] = None
121 | var rs1: ResultSet = null
122 |
123 | try {
124 | With.autoClosingResultSet(mockResultSet) { rs2 =>
125 | rs1 = rs2
126 | }
127 | }
128 | catch {
129 | case e: Exception => caughtExceptionOpt = Some(e)
130 | }
131 |
132 | assertSame(mockResultSet, rs1)
133 | assertTrue("Failed to catch exception.", caughtExceptionOpt.isDefined)
134 | assertSame("Failed to catch expected exception.",
135 | e1, caughtExceptionOpt.get)
136 | context.assertIsSatisfied()
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/alter_column/Migrate_20110214054347_CreateTable.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.alter_column
34 |
35 | import com.imageworks.migration.{
36 | Limit,
37 | Migration,
38 | NotNull,
39 | Unique
40 | }
41 |
42 | class Migrate_20110214054347_CreateTable
43 | extends Migration {
44 | val tableName = "scala_migrations_altering"
45 |
46 | def up() {
47 | createTable(tableName) { t =>
48 | t.varchar("name", Unique, Limit(127), NotNull)
49 | }
50 | }
51 |
52 | def down() {
53 | dropTable(tableName)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/alter_column/Migrate_20110214060042_AlterColumn.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2011 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.alter_column
34 |
35 | import com.imageworks.migration.{
36 | IrreversibleMigrationException,
37 | Limit,
38 | Migration,
39 | VarcharType
40 | }
41 |
42 | class Migrate_20110214060042_AlterColumn
43 | extends Migration {
44 | val tableName = "scala_migrations_altering"
45 |
46 | def up() {
47 | alterColumn(tableName, "name", VarcharType, Limit(255))
48 | }
49 |
50 | def down() {
51 | throw new IrreversibleMigrationException
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/auto_increment/Migrate_20121226170550_CreateTableWithAutoIncrementingColumn.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.auto_increment
34 |
35 | import com.imageworks.migration.{
36 | AutoIncrement,
37 | Limit,
38 | Migration,
39 | NotNull,
40 | PrimaryKey,
41 | Unique
42 | }
43 |
44 | class Migrate_20121226170550_CreateTableWithAutoIncrementingColumn
45 | extends Migration {
46 | val tableName = "scala_migrations_auto_incr"
47 |
48 | def up() {
49 | createTable(tableName) { t =>
50 | t.integer("pk_" + tableName, PrimaryKey, AutoIncrement)
51 | t.varchar("name", Unique, Limit(255), NotNull)
52 | }
53 | }
54 |
55 | def down() {
56 | dropTable(tableName)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/duplicate_descriptions/Migrate_20081118191214_FooBar.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.duplicate_descriptions
34 |
35 | import com.imageworks.migration.Migration
36 |
37 | class Migrate_20081118191214_FooBar
38 | extends Migration {
39 | def up() {}
40 | def down() {}
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/duplicate_descriptions/Migrate_20081118191215_FooBar.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.duplicate_descriptions
34 |
35 | import com.imageworks.migration.Migration
36 |
37 | class Migrate_20081118191215_FooBar
38 | extends Migration {
39 | def up() {}
40 | def down() {}
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/duplicate_versions/Migrate_20081118191214_Bar.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.duplicate_versions
34 |
35 | import com.imageworks.migration.Migration
36 |
37 | class Migrate_20081118191214_Bar
38 | extends Migration {
39 | def up() {}
40 | def down() {}
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/duplicate_versions/Migrate_20081118191214_Foo.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.duplicate_versions
34 |
35 | import com.imageworks.migration.Migration
36 |
37 | class Migrate_20081118191214_Foo
38 | extends Migration {
39 | def up() {}
40 | def down() {}
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/grant_and_revoke/Migrate_200811241940_CreateUser.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.grant_and_revoke
34 |
35 | import com.imageworks.migration.{
36 | Limit,
37 | Migration,
38 | NotNull,
39 | PrimaryKey,
40 | Unique
41 | }
42 |
43 | class Migrate_200811241940_CreateUser
44 | extends Migration {
45 | val tableName = "scala_migrations_location"
46 |
47 | def up() {
48 | createTable(tableName) { t =>
49 | t.varbinary("pk_" + tableName, PrimaryKey, Limit(16))
50 | t.varchar("name", Unique, Limit(255), NotNull)
51 | }
52 | }
53 |
54 | def down() {
55 | dropTable(tableName)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/grant_and_revoke/Migrate_200811261513_Grants.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.grant_and_revoke
34 |
35 | import com.imageworks.migration.tests.TestDatabase
36 | import com.imageworks.migration.{
37 | Migration,
38 | Postgresql,
39 | SelectPrivilege,
40 | UsagePrivilege
41 | }
42 |
43 | class Migrate_200811261513_Grants
44 | extends Migration {
45 | val tableName = "scala_migrations_location"
46 |
47 | def up() {
48 | databaseVendor match {
49 | case Postgresql =>
50 | grantSchemaPrivilege(TestDatabase.getUserAccountName, UsagePrivilege)
51 | case _ =>
52 | }
53 | grant(tableName, TestDatabase.getUserAccountName, SelectPrivilege)
54 | }
55 |
56 | def down() {
57 | revoke(tableName, TestDatabase.getUserAccountName, SelectPrivilege)
58 | databaseVendor match {
59 | case Postgresql =>
60 | revokeSchemaPrivilege(TestDatabase.getUserAccountName, UsagePrivilege)
61 | case _ =>
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/grant_and_revoke/Migrate_20121013072344_EmptyPrivilegeList.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.grant_and_revoke
34 |
35 | import com.imageworks.migration.tests.TestDatabase
36 | import com.imageworks.migration.Migration
37 |
38 | class Migrate_20121013072344_EmptyPrivilegeList
39 | extends Migration {
40 | val tableName = "scala_migrations_location"
41 |
42 | def up() {
43 | grant(tableName, TestDatabase.getUserAccountName)
44 | }
45 |
46 | def down() {
47 | revoke(tableName, TestDatabase.getUserAccountName)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/no_migrations/Stamp.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.no_migrations
34 |
35 | /**
36 | * This is an empty class that exists to ensure that the
37 | * com.imageworks.migration.tests.no_migrations package exists for
38 | * MigrationTests#test_is_migrated_does_not_create_schema_migrations().
39 | */
40 | class Stamp
41 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/scale_without_precision/Migrate_200812041647_Foo.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.scale_without_precision
34 |
35 | import com.imageworks.migration.{
36 | Migration,
37 | Scale
38 | }
39 |
40 | class Migrate_200812041647_Foo
41 | extends Migration {
42 | def up() {
43 | createTable("foo") { t =>
44 | t.decimal("bar", Scale(3))
45 | }
46 | }
47 |
48 | def down() {}
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/types/Migrate_20081212213908_CreateTypetestTable.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.types
34 |
35 | import com.imageworks.migration.{
36 | Limit,
37 | Migration,
38 | Precision,
39 | Scale
40 | }
41 |
42 | class Migrate_20081212213908_CreateTypetestTable
43 | extends Migration {
44 | val tableName = "scala_migrations_types_test"
45 |
46 | def up() {
47 | createTable(tableName) { t =>
48 | // The binary column is not tested because its representation is
49 | // database dependent.
50 |
51 | t.bigint("bigint_column")
52 | t.blob("blob_column")
53 | t.char("char_column", Limit(4))
54 | t.decimal("decimal_column", Precision(22), Scale(2))
55 | t.integer("integer_column")
56 | t.timestamp("timestamp_column")
57 | t.varbinary("varbinary_column", Limit(4))
58 | t.varchar("varchar_column", Limit(4))
59 | }
60 | }
61 |
62 | def down() {
63 | dropTable(tableName)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/up_and_down/Migrate_20081118201000_CreateLocationTable.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.up_and_down
34 |
35 | import com.imageworks.migration.{
36 | Limit,
37 | Migration,
38 | NotNull,
39 | PrimaryKey,
40 | Unique
41 | }
42 |
43 | class Migrate_20081118201000_CreateLocationTable
44 | extends Migration {
45 | val tableName = "scala_migrations_location"
46 |
47 | def up() {
48 | createTable(tableName) { t =>
49 | t.varbinary("pk_" + tableName, PrimaryKey, Limit(16))
50 | t.varchar("name", Unique, Limit(255), NotNull)
51 | }
52 | }
53 |
54 | def down() {
55 | dropTable(tableName)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/up_and_down/Migrate_20081118201742_CreatePeopleTable.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.up_and_down
34 |
35 | import com.imageworks.migration.{
36 | Cascade,
37 | CharacterSet,
38 | Check,
39 | Default,
40 | Limit,
41 | Migration,
42 | Name,
43 | NamedCheck,
44 | NotNull,
45 | Nullable,
46 | OnDelete,
47 | OnUpdate,
48 | Precision,
49 | PrimaryKey,
50 | Restrict,
51 | Scale,
52 | Unicode,
53 | Unique,
54 | VarbinaryType
55 | }
56 |
57 | class Migrate_20081118201742_CreatePeopleTable
58 | extends Migration {
59 | val tableName = "scala_migrations_people"
60 |
61 | def up() {
62 | createTable(tableName) { t =>
63 | t.varbinary("pk_" + tableName, PrimaryKey, Limit(16))
64 | t.varbinary("pk_scala_migrations_location", Limit(16), NotNull)
65 | t.integer("employee_id", Unique)
66 | t.integer("ssn", NotNull)
67 | t.varchar("first_name", Limit(255), NotNull,
68 | CharacterSet(Unicode, "utf8_unicode_ci"))
69 | t.char("middle_initial", Limit(1), Nullable)
70 | t.varchar("last_name", Limit(255), NotNull, CharacterSet(Unicode))
71 | t.timestamp("birthdate", Limit(0), NotNull)
72 | t.smallint("height", NotNull, NamedCheck("chk_height_nonnegative",
73 | "height > 0"))
74 | t.smallint("weight", NotNull, Check("weight > 0"))
75 | t.integer("vacation_days", NotNull, Default("0"))
76 | t.bigint("hire_time_micros", NotNull)
77 | t.decimal("salary", Precision(7), Scale(2), Check("salary > 0"))
78 | t.blob("image")
79 | }
80 |
81 | addIndex(tableName, "ssn", Unique)
82 |
83 | addForeignKey(on(tableName ->
84 | "pk_scala_migrations_location"),
85 | references("scala_migrations_location" ->
86 | "pk_scala_migrations_location"),
87 | OnDelete(Cascade),
88 | OnUpdate(Restrict),
89 | Name("fk_smp_pk_sml_sml_pk_sml"))
90 |
91 | if (!addingForeignKeyConstraintCreatesIndex) {
92 | addIndex(tableName,
93 | "pk_scala_migrations_location",
94 | Name("idx_smp_pk_sml"))
95 | }
96 |
97 | addColumn(tableName, "secret_key", VarbinaryType, Limit(16))
98 |
99 | addCheck(on(tableName -> "vacation_days"), "vacation_days >= 0")
100 | }
101 |
102 | def down() {
103 | removeCheck(on(tableName -> "vacation_days"))
104 | removeForeignKey(on(tableName ->
105 | "pk_scala_migrations_location"),
106 | references("scala_migrations_location" ->
107 | "pk_scala_migrations_location"),
108 | Name("fk_smp_pk_sml_sml_pk_sml"))
109 | if (!addingForeignKeyConstraintCreatesIndex) {
110 | removeIndex(tableName,
111 | "pk_scala_migrations_location",
112 | Name("idx_smp_pk_sml"))
113 | }
114 |
115 | removeIndex(tableName, "ssn")
116 | removeColumn(tableName, "secret_key")
117 | dropTable(tableName)
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/test/scala/com/imageworks/migration/tests/vendor/Migrate_20121104011043_CheckVendor.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Sony Pictures Imageworks Inc.
3 | *
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the
15 | * distribution. Neither the name of Sony Pictures Imageworks nor the
16 | * names of its contributors may be used to endorse or promote
17 | * products derived from this software without specific prior written
18 | * permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | * OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 | package com.imageworks.migration.tests.vendor
34 |
35 | import com.imageworks.migration.{
36 | Derby,
37 | Migration,
38 | Mysql,
39 | Oracle,
40 | Postgresql
41 | }
42 |
43 | class Migrate_20121104011043_CheckVendor
44 | extends Migration {
45 | def up() {
46 | databaseVendor match {
47 | case Derby =>
48 | case Mysql =>
49 | case Oracle =>
50 | case Postgresql =>
51 | case v => throw new AssertionError("Database vendor '" +
52 | v +
53 | "' not handled.")
54 | }
55 | }
56 |
57 | def down() {}
58 | }
59 |
--------------------------------------------------------------------------------