Can I rename Flyway migration scripts? - flyway

I have a project whose database is managed by Flyway in strict validation mode.
My migration files look like this:
V1.0__init.sql
V11.0__even_better.sql
V2.0__update.sql
V7.0__enhance.sql
The files are not displayed in the correct order (11 is between 1 and 2).
Therefore I would like to change them to look like:
V001.000__init.sql
V002.000__update.sql
V007.000__enhance.sql
V011.000__even_better.sql
The documentation says:
Leading zeroes are ignored in each part
This could mean that the above renamings are ok.
But looking at the schema_version table, the leading zeroes are kept, which seems like the above renamings would break the migration. So can I do the renaming, or will it blow up everything?

After trying it locally, it just worked.
The reason why I didn’t expect that is that the version numbers in the schema_version table include the leading zeroes, and the script column also mentions the original script in its full name.
But despite of that, validation succeeded after renaming the files.

Related

Referenced table is not in dictionary

When I scaffold my database get the following error:
Referenced table `contentcategory` is not in dictionary.
Referenced table `contentcategory` is not in dictionary.
Referenced table `contenttype` is not in dictionary.
Referenced table `content` is not in dictionary.
I Use Mysql and Pomelo.EntityFrameworkCore.MySql
This is very likely to be a casing issue, where MySQL assumes the table name to be contentcategory for the reference, while it is actually something like ContentCategory.
We have a pull request for this open since April, that looks abandoned by the original contributor.
I will fix the PR and merge it, so that the workaround for this issue will be part of our nightly builds as of tomorrow.
The linked PR also contains the information of how this issue can arise:
Okay, that is in line with what I experienced as well. So manually (either by writing the name in the GUI or by using an ALTER TABLE statement directly) adding a reference with different casing (on a server with case insensitive file name handling) or disabling SQL Identifiers are Case Sensitive [in MySQL Workbench] can lead to this result.
Technically, this is a MySQL or Workbench bug, but we will implement a workaround for it anyway.

Is there a way to query Oracle DB server name and use in conditional compilation?

I got bit trying to maintain code packages that run on two different Oracle 11g2 systems when a line of code to be changed slipped by me. We develop on one system with a specific data set and then test on another system with a different data set.
The differences aren't tremendous, but include needing to change a single field name in two different queries in two different packages to have the packages run. On one system, we use one field, on the other system... a different one. The databases have the same schema name, object names, and field names, but the hosting system server names are different.
The change is literally as simple as
INSERT INTO PERSON_HISTORY
( RECORD_NUMBER,
UNIQUE_ID,
SERVICE_INDEX,
[... 140 more fields... ]
)
SELECT LOD.ID RECORD_NUMBER ,
-- for Mgt System, use MD5 instead of FAKE_SSN
-- Uncomment below, and comment out Dev system statement
-- MD5 UNIQUE_ID ,
-- for DEV system, use below
'00000000000000000000' || LOD.FAKE_SSN UNIQUE_ID ,
null SERVICE_INDEX ,
[... 140 more fields... ]
FROM LEGACY_DATE LOD
WHERE (conditions follow)
;
I missed one of the field name changes in one of the queries, and our multi-day run is crap.
For stupid reasons I won't go into, I wind up maintaining all of the code, including having to translate and reprocess developer changes manually between versions, then transfer and update the required changes between systems.
I'm trying to reduce the repetitive input I have to provide to swap out code -- I want to automate this step so I don't overlook it again.
I wanted to implement conditional compilation, pulling the name of the database system from Oracle and having the single line swap automatically -- but Oracle conditional compilation requires a package static constant (boolean in this case). I can't use the sys_context function to populate the value. Or, it doesn't seem to let ME pull data from the sys_context and evaluate it conditionally and assign that to a constant. Oracle isn't having any. DB_DOMAIN, DB_NAME, or SERVER_HOST might work to differentiate the systems, but I can't find a way to USE the information.
An option is to create a global constant that I set manually when I move the code to the other system, but at this point, I have so many steps to do for a transfer that I'm worried that I'd even screw that up. I would like to make this independent of other packages or my own processes.
Is there a good way to do this?
-------- edit
I will try the procedure and try to figure out the view over the weekend. Ultimately, the project will be turned over to a customer who expects to "just run it", so they won't understand what any switches are meant to do, or why I have "special" code in a package. And, they won't need to... I don't even know if they'll look at the comments.
Thank you
As Mat says in the comments for this specific example you can solve with a view, however there are other ways for more complex situations.
If you're compiling from a filesystem or using any automatic system you can create a separate PL/SQL block/procedure, which you execute in the same session prior to compilation. I'd do something like this:
declare
l_db varchar2(30) := sys_context('userenv','instance_name');
begin
if l_db = 'MY_DB' then
execute immediate 'alter session set plsql_ccflags = ''my_db:true''';
end if;
end;
/
One important point; conditional compilation does not involve a "package static constant", but a session one. So, you need to ensure that your compilation flags are identical/unique across packages/sessions.

UPDATE statement not working in sqlite

I'm using the following command to update a field in my database:
UPDATE Movies SET 'From'=2 WHERE 'Name'="foo";
I'm using sqlite3.exe in windows (command prompt). Although no error message is produced, nothing changes in the table. I examined the database with a couple of gui tools and I'm sure UPDATE does nothing.
'From' is of type integer and 'Name' is text.
The problem you've got is that you're getting your quoting wrong. SQLite follows the SQL standard here, and that specifies what quote characters to use: '…' is for strings, and "…" is for tokens (like special names used as column or table names). Sometimes it manages to guess what you mean anyway and compensate for getting it wrong, but it can't with the WHERE clause because that is syntactically correct (if decidedly unhelpful):
Swapping the quoting appears to work:
UPDATE Movies SET "From"=2 WHERE "Name"='foo';
Those aren't good column names. Both are keywords, best avoided, and not self-explanatory at all.
Do a SELECT to see how many rows match the WHERE clause in the UPDATE. If none come back, you have your answer.
Did you commit the UPDATE? Is auto commit turned on?

Base directory and schema_version

I just tested the commandline tool and I was able to migrate my database schema changes (DDL scripts) as expected. But I had to move all my scripts under the sql dir.
Is there a way to point flyway to the directory where my real scripts will reside (git or svn repository)? Looks like flyway.locations is only for relative paths.
The schema_version table name and column names are all created in lower case in my database (Oracle). The vast majority of people using Oracle are used to upper case object names and column names (default in Oracle). I found a property in the config file to set my own table name. Is there any to get flyway to use upper case for column names?
I checked the data inserted into version_schema after my test run. All look good except that the first character of the "script" column seem to be removed.
My prefix is "db_". Here is what I see in schema_version,
SQL> select "script" from schema_version;
script
b_1_0__test10.sql
b_1_1__test10.sql
b_1_0_1__test10.sql
atabase/db_2012_11_20__query.sql
<< Flyway Init >>
Lots of questions here (It's easier if you keep them separate). I'll try my best to answer them:
Not currently supported. See https://github.com/flyway/flyway/issues/108 . Symlinking can be used as a workaround.
No, there is no configuration property for the column names. The schema_version table is private to Flyway and not meant for outside consumption.
This sounds like a bug. Please file an issue containing your configuration (OS + version, DB + version, Flyway version, config file contents) and exact steps to reproduce.

SQLite Modify Column

I need to modify a column in a SQLite database but I have to do it programatically due to the database already being in production. From my research I have found that in order to do this I must do the following.
Create a new table with new schema
Copy data from old table to new table
Drop old table
Rename new table to old tables name
That seems like a ridiculous amount of work for something that should be relatively easy. Is there not an easier way? All I need to do is change a constraint on a existing column and give it a default value.
That's one of the better-known drawbacks of SQLite (no MODIFY COLUMN support on ALTER TABLE), but it's on the list of SQL features that SQLite does not implement.
edit: Removed bit that mentioned it may being supported in a future release as the page was updated to indicate that is no longer the case
If the modification is not too big (e.g. change the length of a varchar), you can dump the db, manually edit the database definition and import it back again:
echo '.dump' | sqlite3 test.db > test.dump
then open the file with a text editor, search for the definition you want to modify and then:
cat test.dump | sqlite3 new-test.db
As said here, these kind of features are not implemented by SQLite.
As a side note, you could make your two first steps with a create table with select:
CREATE TABLE tmp_table AS SELECT id, name FROM src_table
When I ran "CREATE TABLE tmp_table AS SELECT id, name FROM src_table", I lost all the column type formatting (e.g., time field turned into a integer field
As initially stated seems like it should be easier, but here is what I did to fix. I had this problem b/c I wanted to change the Not Null field in a column and Sqlite doesnt really help there.
Using the 'SQLite Manager' Firefox addon browser (use what you like). I created the new table by copying the old create statement, made my modification, and executed it. Then to get the data copied over, I just highlighted the rows, R-click 'Copy Row(s) as SQL', replaced "someTable" with my table name, and executed the SQL.
Various good answers already given to this question, but I also suggest taking a look at the sqlite.org page on ALTER TABLE which covers this issue in some detail: What (few) changes are possible to columns (RENAME|ADD|DROP) but also detailed workarounds for other operations in the section Making Other Kinds Of Table Schema Changes and background info in Why ALTER TABLE is such a problem for SQLite. In particular the workarounds point out some pitfalls when working with more complex tables and explain how to make changes safely.

Resources