
Classes | |
| class | Migration |
Public Member Functions | |
| EOModel | _blankModel () |
| void | _tableDropped (ERXMigrationTable table) |
| EOAdaptor | adaptor () |
| EOAdaptorChannel | adaptorChannel () |
| ERXMigrationColumn | existingColumnNamed (String tableName, String columnName) |
| ERXMigrationTable | existingTableNamed (String name) |
| boolean | is (String name) |
| NSArray< String > | languages () |
| EOModel | model () |
| ERXMigrationTable | newTableNamed (String name) |
| String | productName () |
| EOSynchronizationFactory | synchronizationFactory () |
Static Public Member Functions | |
| static void | _ensureNotEmpty (NSArray< EOSQLExpression > expressions, String operationName, boolean required) |
| static NSArray< String > | _stringsForExpressions (NSArray< EOSQLExpression > expressions) |
| static ERXMigrationDatabase | database (EOAdaptorChannel adaptorChannel, EOModel model) |
| static ERXMigrationDatabase | database (EOAdaptorChannel adaptorChannel, EOModel model, NSArray< String > languages) |
| static ERXMigrationDatabase | database (EOAdaptorChannel adaptorChannel) |
Static Public Attributes | |
| static final Logger | log = Logger.getLogger(ERXMigrationDatabase.class) |
Private Member Functions | |
| ERXMigrationDatabase (EOAdaptorChannel adaptorChannel, EOModel model, NSArray< String > languages) | |
| ERXMigrationDatabase (EOAdaptorChannel adaptorChannel, EOModel model) | |
Private Attributes | |
| EOAdaptorChannel | _adaptorChannel |
| NSArray< String > | _languages |
| EOModel | _model |
| NSMutableArray< ERXMigrationTable > | _tables |
Prior to this API, and still fully supported (and required for more complicated operations), all migrations had to be written with SQL. The downside of writing SQL is that you are writing database-specific operations, which you must provide per-database implementations of. EOF already supports an API for database-agnostic SQL generation that via the EOSynchronizationFactory family of interfaces, but that API is overly complicated. ERXMigrationDatabase aims to provide a much simpler API on top of EOSynchronizationFactory that lets you perform common database-agnostic operations like adding and deleting columns, creating and dropping tables, adding primary keys, and adding foreign keys.
ERXMigrationDatabase is conceptually similar to an EOModel, ERXMigrationTable to an EOEntity, and ERXMigrationColumn to an EOAttribute. The names were specifically chosen to make the SQL-specific nature of the API clear (currently most of the API does not expose SQL-ness, but I'm assuming that in the future it may as the complexity of the operations provided increases). All of the API allows you to build an in-memory model of your structural changes along with some "perform now" method calls that actual execute SQL commands against the provided adaptor channel.
Let's take a look at some examples. Take the very common case of a migration that just adds a new column to a table: ERXMigrationDatabase.database(channel).existingTableNamed("Request").newStringColumn("requestedByEmailAddress", 255, true);
Another more complex case is that you are introducing an entirely new table that has a foreign key to some existing table:
ERXMigrationDatabase database = ERXMigrationDatabase.database(channel);
ERXMigrationTable table = ERXMigrationDatabase.database(channel).newTableNamed("TestPerson");
table.newStringColumn("FirstName", 100, false);
table.newStringColumn("LastName", 100, false);
table.newStringColumn("EmailAddress", 100, false);
table.newStringColumn("PhoneNumber", 10, true);
table.newIntegerColumn("PantSize", true);
table.newTimestampColumn("Birthdate", true);
table.newBigDecimalColumn("HourlyRate", 32, 4, true);
table.newFloatColumn("Rating", 10, 2, true);
table.newBooleanColumn("Married", false);
table.newIntBooleanColumn("Bald", false);
table.newIntegerColumn("CompanyID", false);
table.create();
table.addForeignKey(table.existingColumnNamed("CompanyID"), database.existingTableNamed("Company").existingColumnNamed("companyID"));
In the above examples, database.existingTableNamed and table.existingColumnNamed are called. Calling table/database.existingXxx() does not perform database reverse engineering. It only creates a stub entry that is enough to perform operations like deleting, renaming, foreign keys, etc. Calling table.newXxx does not create the element in the database if the table is new, rather it returns a metadata wrapper (similar to EOAttribute, etc, but with migration-specific API's). However, if the table already exists, calling .newXxxColumn on the table will create the column immediately. You should generally not call .create() on an object you obtained from a call to .existingXxx, because it will only be a stub and generally insufficient to actually create in the database. The call to .existingXxx implies that the corresponding element already exists in the database. If you are creating an entire table, you can use the batching API like the second example where you can call database.newTableNamed(), then .newColumn all the columns in it, followed by a table.create() to create the entire block. For foreign keys, you must have .create()'d both tables (or use existing tables) prior to calling the foreign key methods.
It's important to note that this API relies entirely on EOSynchronizationFactory. If the sync factory for your plugin is wrong, the SQL generation in the ERXMigrationDatabase API's will likewise be wrong.
| ERXMigrationDatabase | ( | EOAdaptorChannel | adaptorChannel, | |
| EOModel | model | |||
| ) | [private] |
Constructs an ERXMigrationDatabase
| adaptorChannel | the adaptor channel to connect to | |
| model | the model being migrated (necessary for more reliable sql generation) |
| ERXMigrationDatabase | ( | EOAdaptorChannel | adaptorChannel, | |
| EOModel | model, | |||
| NSArray< String > | languages | |||
| ) | [private] |
Constructs an ERXMigrationDatabase
| adaptorChannel | the adaptor channel to connect to | |
| model | the model being migrated (necessary for more reliable sql generation) | |
| languages | the langauges to use for localization |
| EOModel _blankModel | ( | ) |
Returns a blank EOModel with the connection dictionary from the adaptor.
| static void _ensureNotEmpty | ( | NSArray< EOSQLExpression > | expressions, | |
| String | operationName, | |||
| boolean | required | |||
| ) | [static] |
Throws an ERXMigrationFailedException if the array of expressions is empty. Not all sync factories support all the listed operations, so this makes sure that the requested operation doesn't silently fail.
| expressions | the expressions to check | |
| operationName | the name of the operation being performed (for better error messages) | |
| required | if true, an exception is thrown; if false, an error is logged |
| static NSArray<String> _stringsForExpressions | ( | NSArray< EOSQLExpression > | expressions | ) | [static] |
| void _tableDropped | ( | ERXMigrationTable | table | ) |
Notification callback to tell the database that the user dropped the given table.
| table | the table that was dropped |
| EOAdaptor adaptor | ( | ) |
Returns the adaptor for the given channel.
| EOAdaptorChannel adaptorChannel | ( | ) |
Returns the adaptor channel.
| static ERXMigrationDatabase database | ( | EOAdaptorChannel | adaptorChannel, | |
| EOModel | model | |||
| ) | [static] |
Returns an ERXMigrationDatabase for the given EOAdaptorChannel. This will return a new ERXMigrationDatabase for every call, so if you need to perform multiple operations within a single database instance (for instance, adding foreign keys that talk to two tables), you should operate within a single ERXMigrationDatabase instance.
| adaptorChannel | the adaptor channel to operate within | |
| model | the model that corresponds to this table |
| static ERXMigrationDatabase database | ( | EOAdaptorChannel | adaptorChannel, | |
| EOModel | model, | |||
| NSArray< String > | languages | |||
| ) | [static] |
Returns an ERXMigrationDatabase for the given EOAdaptorChannel. This will return a new ERXMigrationDatabase for every call, so if you need to perform multiple operations within a single database instance (for instance, adding foreign keys that talk to two tables), you should operate within a single ERXMigrationDatabase instance.
| adaptorChannel | the adaptor channel to operate within | |
| model | the model that corresponds to this table | |
| languages | the langauges to use for localization |
| static ERXMigrationDatabase database | ( | EOAdaptorChannel | adaptorChannel | ) | [static] |
Returns an ERXMigrationDatabase for the given EOAdaptorChannel. This will return a new ERXMigrationDatabase for every call, so if you need to perform multiple operations within a single database instance (for instance, adding foreign keys that talk to two tables), you should operate within a single ERXMigrationDatabase instance. If you have a model, you should use database(adaptorChannel, model) instead of this variant so that migrations can use the connection dictionary that is closest to being correct.
| adaptorChannel | the adaptor channel to operate within |
| ERXMigrationColumn existingColumnNamed | ( | String | tableName, | |
| String | columnName | |||
| ) |
Shortcut to ERXMigrationTable.existingColumnNamed(String).
| tableName | the name of the existing table | |
| columnName | the name of the existing column |
| ERXMigrationTable existingTableNamed | ( | String | name | ) |
Returns an ERXMigrationTable with the given table name. This method does not perform any database reverse engineering. If you ask for an existing table, it will only return a stub of the table that should be sufficient for performing column operations and miscellaneous table operations like dropping. If you call newTableNamed, existingTableNamed will return the tables you create.
| name | the name of the table to lookup |
| boolean is | ( | String | name | ) |
| name | name of database to match productName() |
true if productName().equals(name) | NSArray<String> languages | ( | ) |
| EOModel model | ( | ) |
| ERXMigrationTable newTableNamed | ( | String | name | ) |
Creates a new blank ERXMigrationTable. This is essentially the same as calling existingTableNamed except that it performs some simple validation to make sure this table hasn't been created in this ERXMigrationDatabase yet. Note that this check is not checking the actual database -- it is only verifying that you have not called newTableNamed or existingTableNamed on the name you provide. After calling newTableNamed, the instance returned from this method will also be returned from calls to existingTableNamed. The table will not be created from this call, only an object model is built.
| name | the name of the table to create |
| String productName | ( | ) |
| EOSynchronizationFactory synchronizationFactory | ( | ) |
Returns the synchronization factory for this adaptor.
EOAdaptorChannel _adaptorChannel [private] |
NSArray<String> _languages [private] |
EOModel _model [private] |
NSMutableArray<ERXMigrationTable> _tables [private] |
final Logger log = Logger.getLogger(ERXMigrationDatabase.class) [static] |
1.5.8