Liquibase: Cache for column - sql

I would like do the following by using liquibase:
alter table SCHEMAX.TABLEX modify lob (COLUMNX)(CACHE);
Does anybody know if this is possible?
Thanks

You can specify any kind of SQL in an sql change set:
Example:
<changeSet author="liquibase-docs" id="sql-example">
<sql dbms="mysql">
alter table SCHEMAX.TABLEX modify lob (COLUMNX)(CACHE);
</sql>
</changeSet>
you should specify the supported dbms, because the SQL might not execute on other DBMSs, as it might use vendor specific commands.

Related

Rename Schema Using Liquibase

Assume that V1 of the Liquibase change set was defined like so:
<changeSet author="newco" id="create-old_table_name">
<createTable tableName="old_table_name">
...
</createTable>
</changeSet>
V1 didn't define a schema name, therefore as I understand it has a default value, but in V2 I want to specify a schema name:
<changeSet author="newco" id="update-v2-rename-old_table_name">
<renameTable newTableName="old_table_name"
oldTableName="old_table_name"
schemaName="example"/>
</changeSet>
But this doesn't work and throws an exception stating that the table name didn't change. Is it not possible to change the schema?
What DB change are you trying to achieve here?
If you want to move a table from one schema to another you will need to use a SQL change as the "renameTable" change type is only for renaming a table within the same schema.
See e.g. how to move tables from public to other schema in Postgres for the SQL needed to achieve that move in psql
Something like this?
<sql>
ALTER TABLE old_table_name
SET SCHEMA example;
</sql>

How to use different tablespaces for tables and indexes with Liquibase

I am using Liquibase 4.0 and I am executing DB changes using SQL scripts. So I am pointing the SQL files path in the master change log to execute the changes via Liquibase.
Now I need to segregate them since I have a requirement to have different tablespace for both tables and indexes.
Hence I tried to find an option for parameterization in Liquibase, but could not find so.
My Masterchangelog for the change looks like:-
<changeSet author="sanjib" id="01_PR_001">
<sqlFile dbms="oracle"
endDelimiter=";"
path="../scripts/PR_001/PR_001.sql"
relativeToChangelogFile="true"
splitStatements="true"
stripComments="true"/>
<rollback>
<dropTable cascadeConstraints="true" tableName="PERSON"/>
</rollback>
</changeSet>
The Liquibase.properties file looks like this:-
driver: oracle.jdbc.OracleDriver
classpath: ojdbc6.jar
url: jdbc:oracle:thin:#localhost:1521/xe
databaseChangeLogTablespaceName:DATA
username: sanjib
Now the main issue is that the table defined in the SQL script is not created under the user's tablespace. Instead, it is using the username from the properties file as tablespace name, hence facing the issue that Table cannot be created since tablespace is missing, which is an obvious error. Hence to create the DATABSAECHANGELOG & DATABASECHANGELOGLOCK table, I had to add the property 'databaseChangeLogTablespaceName' in the properties file, but the tables and indexes are not getting created.
So please help in fixing the 2 issues.
How to point the installation via Liquibase to use the user's default tablespace instead of using the username as tablespace.
Can we parameterize the Table's tablespace and index's tablespace using the above setup as defined in the XML file?
To use different tablespaces for tables and indexes, liquibase property substitution is the way to achieve it. You can declare 2 tablespaces name properties, one for tables and the other for indexes. These properties can be declared in liquibase.properties file or at the start of your changelog itself. You can then access it using the syntax ${property_name} and use it at the places to provide tablespace name.
From liquibase docs on this link, you can specify tablespace name at the time of creating table. Example for the same is as below:
(Example with declaring a property in liquibase.properties file)
Add a property in your liquibase.properties file :
tablespace: tablespaceQA
<changeSet id="2" author="liquibase">
<createTable catalogName="department2"
remarks="A String"
schemaName="public"
tableName="person"
tablespace="${tablespace}">
<column name="address" type="varchar(255)"/>
</createTable>
</changeSet>
the property ${tablespace} gets substituted with it's value as configured in your liquibase.properties file or with the value you pass when you run liquibase update command (liquibase -Dtablespace='tablespaceQA' update)
(Example with declaring a property at start of your changelog)
For indexes, you can declare a property at the start of your changelog (or in liquibase.properties file).
<property name="index_tablespace" value="INDEX" dbms="oracle"/>
now, use the property in createIndex tag as folows:
<createIndex indexName="idx_firstname" tableName="person" tablespace="${index_tablespace}"/>
For more details, visit the comments on this post.
Cheers!!
I don't remember how exactly sql files works, but if I'm not mistaken then replacing properties should work also in sql files. So in your sqlfile you can do something like this:
create index somespecificindex tablespace ${indexTablespace} ...
Then you can define some property that will be substituted. So for example something like this
<property name="indexTablespace" value="indexes" />
And when you execute your migration then everything should work.

WHERE clause in liquibase changelog to create database

How can I generate this SQL statement in my changelog file with liquibase?
CREATE UNIQUE INDEX RL_UK on RUN_LOG(status) WHERE status = 'R'
I have tried it like this but it doesnt work:
<changeSet author="Ferid (generated)" id="1528876614155-232">
<createIndex indexName="RL_UK" tableName="RUN_LOG" unique="true">
<where> status='R'</where>
</createIndex>
I dont use this changelog file to update the database but to create it.
The clause is not available.
As suggested in comments, you could write custom SQL statments with tag but you will have to take care of the rollback yourself :
<changeSet author="Ferid (generated)" id="1528876614155-232">
<sql>
CREATE UNIQUE INDEX RL_UK on RUN_LOG(status) WHERE status = 'R';
</sql>
<rollback>
<sql>
DROP INDEX RL_UK on RUN_LOG;
</sql>
</rollback>
</changeSet>
Although I would personnally suggest that you use the tag properly without the WHERE CLAUSE because :
I can't understand what you are trying to achieve with this where clause. Espacially since it is on the same column
Your changeset probably won't be compatible with all databases supported by Liquibase so it will work with Postgres and fail with Oracle for example. The WHERE CLAUSE in the CREATE INDEX statement is probably not even ANSI-SQL
You add bothering about the rollback for a very simple statement => not worth. Auto-rollback is available on every supported databases for this tag. Check it here : http://www.liquibase.org/documentation/changes/create_index.html

Liquibase add comment to table

I'm currently trying to add comment on tables in liquibase 3.1.1
What I want to do is ALTER TABLE t1 COMMENT = 'New table comment';
I didn't find any help in the documentation of liquibase about this case, there is only help for adding comments on columns.
I am currently thinking of creating a customChange or doing the change by myself with SQL statements but as we are going to migrate from MySQL to Oracle I would like to avoid this solution (or use it in last resort).
Has anyone found another solution for this problem ?
COMMENT ON TABLE is absolutely helpful in this case. See example I provided below along with some tips and pitfalls about editing tables using liqubase.
Continuing the response above, I'd like to pay attention on tag <preConditions> here. It's critical when dealing with tables to ask liqubase whether the certain table exists at the moment you try to edit one. Here's some example of this behavior:
<changeSet id="your_table_id" author="author_name" dbms="postgresql">
<preConditions onFail="MARK_RAN">
<tableExists tableName="table_name" schemaName="schema_name"/>
</preConditions>
<sql>
COMMENT ON TABLE schema_name.table_name is 'YOUR_COMMENT_ON_TABLE';
</sql>
</changeSet>
In case dealing with columns (editing, adding, deleting) ALSO consider asking liqubase the similar way of the existing or absence of the specific column(s):
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="table_name" schemaName="schema_name"
columnName="column_name"/>
</not>
</preConditions>
<sql>
...
</sql>
The example above checks if column NOT present in table and then executes some SQL script.
I solved this problem by creating a custom SQL statement with a <sql> tag (or "sql" key if you are using JSON) in the changeSet (documentation can be found here).
Since I am using PostgreSQL, the SQL syntax for adding a comment to a table is COMMENT ON TABLE table_name IS 'text'. Below is the entire changeSet in XML format:
<changeSet author="gfigueroa" id="add-comment-to-table-xyz">
<sql dbms="postgresql"
endDelimiter=";"
splitStatements="true"
stripComments="true">
COMMENT ON TABLE xyz IS 'This is a test comment';
</sql>
</changeSet>

Compress Column in Liquibase

I am looking to compress a column through Liquibase and I haven't been able to find any examples of this on the Liquidbase site.
I was wondering if anyone has an example of this?
You can add custom SQL statements to Liquibase change logs using the <sql> element and use the dbms attribute on change sets to define for which databases they are meant to be run.
<changeSet id=".." dbms="oracle">
<sql>
alter table foobar move compress;
</sql>
<rollback>
<sql>
alter table foobar nocompress;
</sql>
</rollback>
</changeSet>
You can use modifyDataType
<changeSet author="liquibase-docs" id="modifyDataType-example">
<modifyDataType catalogName="cat"
columnName="id"
newDataType="A String"
schemaName="public"
tableName="person"/>
</changeSet>