Liquibase: Specify schema when adding foreign key constraint - postgresql

I'm using liquibase 3.5.5 with postgresql. All my tables are being created in a specified schema, however when liquibase tried to generate the DDL, it is appending "public." in front of the referencesTableName. I've tried making the table name "identity.users", but it just tries to create public."identity.users".
For example, the below
<createTable tableName="users" schemaName="identity">
<column name="id" type="bigint" defaultValueSequenceNext="seq_users">
<constraints primaryKey="true" primaryKeyName="pk_users"/>
</column>
</createTable>
<createTable tableName="external_identities" schemaName="identity">
<column name="id" type="bigint" defaultValueSequenceNext="seq_external_identities">
<constraints primaryKey="true" primaryKeyName="pk_external_identities"/>
</column>
<column name="user_id" type="bigint">
<constraints foreignKeyName="fk_external_identities_users" referencedTableName="users" referencedColumnNames="id" nullable="false"/>
</column>
</createTable>
Produces:
CREATE TABLE identity.external_identities (id BIGINT DEFAULT nextval('identity.seq_external_identities') NOT NULL, user_id BIGINT NOT NULL, CONSTRAINT fk_external_identities_users FOREIGN KEY (user_id) REFERENCES public.users(id))
The docs don't help much, and the XSD file does not list schema as an option:
<!-- Attributes for constraints -->
<xsd:attributeGroup name="constraintsAttributes">
<xsd:attribute name="nullable" type="booleanExp" />
<xsd:attribute name="primaryKey" type="booleanExp" />
<xsd:attribute name="primaryKeyName" type="xsd:string" />
<xsd:attribute name="primaryKeyTablespace" type="xsd:string" />
<xsd:attribute name="unique" type="booleanExp" />
<xsd:attribute name="uniqueConstraintName" type="xsd:string" />
<xsd:attribute name="references" type="xsd:string" />
<xsd:attribute name="referencedTableName" type="xsd:string"/>
<xsd:attribute name="referencedColumnNames" type="xsd:string"/>
<xsd:attribute name="foreignKeyName" type="xsd:string" />
<xsd:attribute name="deleteCascade" type="booleanExp" />
<xsd:attribute name="deferrable" type="booleanExp" />
<xsd:attribute name="initiallyDeferred" type="booleanExp" />
<xsd:attribute name="checkConstraint" type="xsd:string" />
</xsd:attributeGroup>

Try using separate changeset for adding foreign key constratint. It'll be addForeignKeyConstraint. It has schema attributes.
ChangeSet will look like this:
<changeSet author="liquibase-docs" id="addForeignKeyConstraint-example">
<addForeignKeyConstraint
baseColumnNames="user_id"
baseTableName="external_identities"
constraintName="fk_external_identities_users"
referencedColumnNames="id"
referencedTableName="users"
baseTableSchemaName="identity"
referencedTableSchemaName="identity"/>
</changeSet>

Had to use changeSet with sql like:
ALTER TABLE schema.table ADD CONSTRAINT constraint FOREIGN KEY (fk_field) REFERENCES schema.ref_table (field)

Support for specifying the referenced schema of a foreign key defined in the constraints element was added in version 3.5 of Liquibase. In version 3.5 of the dbchangelog XSD you can find the new referencedTableSchemaName attribute on the constraints element.
Liquibase will not recognize this new attribute if your changelog XML file still imports an older XSD version, so make sure that the databaseChangeLog root element references version 3.5 or newer of the XSD file:
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
<!-- ... -->
</databaseChangeLog>
Then update the constraints element of your column definition with a value for the referencedTableSchemaName attribute:
<column name="user_id" type="bigint">
<constraints
foreignKeyName="fk_external_identities_users"
referencedTableSchemaName="identity"
referencedTableName="users"
referencedColumnNames="id"
nullable="false"/>
</column>

Related

Unsure how to fix the error in the Azure Devops Migration Tool for very old TFS collections

We've been asked to migrate some very old legacy projects (i.e. from TFS 2010 days) onto Azure Devops Services. These very old projects have almost nothing in their Process Configuration and only have one error line in the logs from the migration tool for all project types (Scrum, Agile, Basic etc...).
[Info #15:27:48.998] === Found 1 error(s) when compared against process TFS 2019 Update 1 Scrum ===
[Error #15:27:48.998] Custom processConfiguration typeField count '0' is different than system '8'.
[Info #15:27:48.998] === End of error(s) when compared against process TFS 2019 Update 1 Scrum ===
When looking at their Process Configuation it is only a few lines:
<?xml version="1.0" encoding="utf-16"?>
<ProjectProcessConfiguration>
<RequirementBacklog workItemCountLimit="1000">
<AddPanel />
</RequirementBacklog>
<TaskBacklog workItemCountLimit="1000">
<AddPanel />
</TaskBacklog>
<Properties>
<Property name="BugsBehavior" value="Off" />
</Properties>
</ProjectProcessConfiguration>
The only project that has no errors was a project added much later on TFS 2015:
<?xml version="1.0" encoding="utf-16"?>
<ProjectProcessConfiguration>
<BugWorkItems category="Microsoft.BugCategory" pluralName="Bugs" singularName="Bug">
<States>
<State type="Proposed" value="New" />
<State type="InProgress" value="Active" />
<State type="Complete" value="Closed" />
<State type="Resolved" value="Resolved" />
</States>
</BugWorkItems>
<FeedbackRequestWorkItems category="Microsoft.FeedbackRequestCategory" pluralName="Feedback Requests" singularName="Feedback Request">
<States>
<State type="InProgress" value="Active" />
<State type="Complete" value="Closed" />
</States>
</FeedbackRequestWorkItems>
<FeedbackResponseWorkItems category="Microsoft.FeedbackResponseCategory" pluralName="Feedback Responses" singularName="Feedback Response">
<States>
<State type="InProgress" value="Active" />
<State type="Complete" value="Closed" />
</States>
</FeedbackResponseWorkItems>
<PortfolioBacklogs>
<PortfolioBacklog category="Microsoft.EpicCategory" pluralName="Epics" singularName="Epic" workItemCountLimit="1000">
<AddPanel>
<Fields>
<Field refname="System.Title" />
</Fields>
</AddPanel>
<Columns>
<Column width="100" refname="System.WorkItemType" />
<Column width="400" refname="System.Title" />
<Column width="100" refname="System.State" />
<Column width="50" refname="Microsoft.VSTS.Scheduling.Effort" />
<Column width="50" refname="Microsoft.VSTS.Common.BusinessValue" />
<Column width="100" refname="Microsoft.VSTS.Common.ValueArea" />
<Column width="200" refname="System.Tags" />
</Columns>
<States>
<State type="Proposed" value="New" />
<State type="InProgress" value="Active" />
<State type="InProgress" value="Resolved" />
<State type="Complete" value="Closed" />
</States>
</PortfolioBacklog>
<PortfolioBacklog category="Microsoft.FeatureCategory" parent="Microsoft.EpicCategory" pluralName="Features" singularName="Feature" workItemCountLimit="1000">
<AddPanel>
<Fields>
<Field refname="System.Title" />
</Fields>
</AddPanel>
<Columns>
<Column width="100" refname="System.WorkItemType" />
<Column width="400" refname="System.Title" />
<Column width="100" refname="System.State" />
<Column width="50" refname="Microsoft.VSTS.Scheduling.Effort" />
<Column width="50" refname="Microsoft.VSTS.Common.BusinessValue" />
<Column width="100" refname="Microsoft.VSTS.Common.ValueArea" />
<Column width="200" refname="System.Tags" />
</Columns>
<States>
<State type="Proposed" value="New" />
<State type="InProgress" value="Active" />
<State type="InProgress" value="Resolved" />
<State type="Complete" value="Closed" />
</States>
</PortfolioBacklog>
</PortfolioBacklogs>
<RequirementBacklog category="Microsoft.RequirementCategory" parent="Microsoft.FeatureCategory" pluralName="Stories" singularName="User Story" workItemCountLimit="1000">
<AddPanel>
<Fields>
<Field refname="System.Title" />
</Fields>
</AddPanel>
<Columns>
<Column width="100" refname="System.WorkItemType" />
<Column width="400" refname="System.Title" />
<Column width="100" refname="System.State" />
<Column width="50" refname="Microsoft.VSTS.Scheduling.StoryPoints" />
<Column width="100" refname="Microsoft.VSTS.Common.ValueArea" />
<Column width="200" refname="System.IterationPath" />
<Column width="200" refname="System.Tags" />
</Columns>
<States>
<State type="Proposed" value="New" />
<State type="InProgress" value="Active" />
<State type="InProgress" value="Resolved" />
<State type="Complete" value="Closed" />
</States>
</RequirementBacklog>
<TaskBacklog category="Microsoft.TaskCategory" parent="Microsoft.RequirementCategory" pluralName="Tasks" singularName="Task" workItemCountLimit="1000">
<AddPanel>
<Fields>
<Field refname="System.Title" />
</Fields>
</AddPanel>
<Columns>
<Column width="400" refname="System.Title" />
<Column width="100" refname="System.State" />
<Column width="100" refname="System.AssignedTo" />
<Column width="50" refname="Microsoft.VSTS.Scheduling.RemainingWork" />
</Columns>
<States>
<State type="Proposed" value="New" />
<State type="InProgress" value="Active" />
<State type="Complete" value="Closed" />
</States>
</TaskBacklog>
<TypeFields>
<TypeField refname="Microsoft.VSTS.Common.Activity" type="Activity" />
<TypeField refname="Microsoft.VSTS.Common.StackRank" type="Order" />
<TypeField refname="Microsoft.VSTS.Feedback.ApplicationLaunchInstructions" type="ApplicationLaunchInstructions" />
<TypeField refname="Microsoft.VSTS.Feedback.ApplicationStartInformation" type="ApplicationStartInformation" />
<TypeField refname="Microsoft.VSTS.Feedback.ApplicationType" type="ApplicationType">
<TypeFieldValues>
<TypeFieldValue type="ClientApp" value="Client application" />
<TypeFieldValue type="RemoteMachine" value="Remote machine" />
<TypeFieldValue type="WebApp" value="Web application" />
</TypeFieldValues>
</TypeField>
<TypeField format="{0} h" refname="Microsoft.VSTS.Scheduling.RemainingWork" type="RemainingWork" />
<TypeField refname="Microsoft.VSTS.Scheduling.StoryPoints" type="Effort" />
<TypeField refname="System.AreaPath" type="Team" />
</TypeFields>
<Weekends>
<DayOfWeek>Sunday</DayOfWeek>
<DayOfWeek>Saturday</DayOfWeek>
</Weekends>
<Properties>
<Property name="HiddenBacklogs" value="Microsoft.EpicCategory" />
<Property name="BugsBehavior" value="AsTasks" />
</Properties>
<WorkItemColors>
<WorkItemColor primary="FFCC293D" secondary="FFFAEAE5" name="Bug" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Code Review Request" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Code Review Response" />
<WorkItemColor primary="FFFF7B00" secondary="FFFFD7B5" name="Epic" />
<WorkItemColor primary="FF773B93" secondary="FFEEE2F2" name="Feature" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Feedback Request" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Feedback Response" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Issue" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Shared Parameter" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Shared Steps" />
<WorkItemColor primary="FFF2CB1D" secondary="FFF6F5D2" name="Task" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Test Case" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Test Plan" />
<WorkItemColor primary="FFFF9D00" secondary="FFFCEECF" name="Test Suite" />
<WorkItemColor primary="FF009CCC" secondary="FFD6ECF2" name="User Story" />
</WorkItemColors>
</ProjectProcessConfiguration>
Anyone know of a easy way to fix the older projects? We want to import the code with changeset histories into Azure Devop Services and none of them have actually have work items (was managed externally on JIRA), build and release configs etc... We just want to get them onto the cloud to retire the legacy onpremise TFS servers (which are now running Azure Devops Server 2020.1.1 as per the migration suggestions).
Thanks for any help.
Edit: we're using TFS Team Project Manager from Jelle Druyts to help do some of the analysis, and am wondering if we can use the Transform function under Process Configuration to import the working projects config into the other projects.
Mark.
Sorry for the late reply on this. Since we didn't need to preserve templates and work items/ task history, we ended up abandoning full migrations. Ended up using the git-tfs (https://git-tfs.com/) tool to convert the TFS projects to a local git repository, then attaching that to a new Azure git project. Preserved all our history which was great.

Hibernate exception javassist

I need some help as I'm stumped on an Hibernate 4/Struts 2 project. This is my first Hibernate 4 (4.3.11) project, as I worked for years with Hibernate 3. The database is MySQL 5.
All mapping classes were produced with Hibernate Tools provided by JBoss Tools 4.3.5, on Eclipse Mars 2. No problem was encountered, it worked fine.
But when testing, I faced this exception :
2017-02-16 17:23:45 ERROR Dispatcher:38 - Exception occurred during processing request: metier.Ville_$$_javassist_2 cannot be cast to javassist.util.proxy.Proxy
java.lang.ClassCastException: metier.Ville_$$_javassist_2 cannot be cast to javassist.util.proxy.Proxy
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxy(JavassistLazyInitializer.java:147)
at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.getProxy(JavassistProxyFactory.java:75)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:771)
I read that post but I don't understand what's happening.
Two classes are involved : Salle and Ville. Here's the Hibernate XML files : Salle.hbm.xml & Ville.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated 2 f?vr. 2017 11:28:16 by Hibernate Tools 4.3.5.Final -->
<hibernate-mapping>
<class name="metier.Salle" table="salle" catalog="aevbadherents" optimistic-lock="version">
<id name="idSalle" type="int">
<column name="idSALLE" />
<generator class="assigned" />
</id>
<many-to-one name="ville" class="metier.Ville" fetch="select">
<column name="idVilleSalle" />
</many-to-one>
<property name="adresse1" type="string">
<column name="Adresse1" length="80" />
</property>
<property name="adresse2" type="string">
<column name="Adresse2" length="80" />
</property>
<property name="description" type="string">
<column name="Description" length="500" />
</property>
<set name="courses" table="cours" inverse="true" lazy="true" fetch="select">
<key>
<column name="IdSalle" not-null="true" />
</key>
<one-to-many class="metier.Cours" />
</set>
<set name="passagegrades" table="passagegrade" inverse="true" lazy="true" fetch="select">
<key>
<column name="IdSalle" />
</key>
<one-to-many class="metier.Passagegrade" />
</set>
</class>
</hibernate-mapping>
The second file :
<hibernate-mapping>
<class name="metier.Ville" table="ville" catalog="aevbadherents" optimistic-lock="version">
<id name="idVille" type="int">
<column name="idVILLE" />
<generator class="assigned" />
</id>
<many-to-one name="departement" class="metier.Departement" fetch="select">
<column name="idDepartement" not-null="true" />
</many-to-one>
<property name="nom" type="string">
<column name="Nom" length="60" not-null="true" />
</property>
<property name="codepostal" type="string">
<column name="codepostal" length="6" not-null="true" />
</property>
<property name="gpslat" type="string">
<column name="GPSLat" length="12" not-null="true" />
</property>
<property name="gpslon" type="string">
<column name="GPSLon" length="12" not-null="true" />
</property>
<set name="adherentsForIdVilleResid" table="adherent" inverse="true" lazy="true" fetch="select">
<key>
<column name="IdVilleResid" />
</key>
<one-to-many class="metier.Adherent" />
</set>
<set name="clubs" table="club" inverse="true" lazy="true" fetch="select">
<key>
<column name="idville" not-null="true" />
</key>
<one-to-many class="metier.Club" />
</set>
<set name="salles" table="salle" inverse="true" lazy="true" fetch="select">
<key>
<column name="idVilleSalle" />
</key>
<one-to-many class="metier.Salle" />
</set>
<set name="adherentsForIdVilleNais" table="adherent" inverse="true" lazy="true" fetch="select">
<key>
<column name="IdVilleNais" />
</key>
<one-to-many class="metier.Adherent" />
</set>
</class>
</hibernate-mapping>
I read that this exception may be caused by a JAR conflict, but I did not find anything.I don't use Maven (maybe I should ?), so let me show you the JARs included :
antlr-2.7.7.jar
commons-fileupload-1.3.jar
commons-io-2.0.1.jar
commons-lang3-3.1.jar
commons-logging-1.2-javadoc.jar
commons-logging-1.2.jar
dom4j-1.6.1.jar
freemarker-2.3.19.jar
hibernate-commons-annotations-4.0.5.Final.jar
hibernate-core-4.3.11.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
jandex-1.1.0.Final.jar
javassist-3.18.1-GA.jar
jboss-logging-3.1.3.GA.jar
jboss-logging-annotations-1.2.0.Beta1.jar
jboss-transaction-api_1.2_spec-1.0.0.Final.jar
log4j-1.2.15.jar
mysql-connector-java-5.1.40-bin.jar
ognl-3.0.6.jar
struts2-core-2.3.15.3.jar
truc.txt
xwork-core-2.3.15.3.jar
Please help me, as I'm stumped...
One of the possible cause for this problem is that you have in your classpath several versions of the same class.
I have been looking in java2s.com and, none of the jar you listed, seems to contain the class javassist.util.proxy.Proxy, so I will try to find if any other jar contains that class using jarscan with the following command:
jarscan -d PATH_TO_YOUR_CLASSPATH_DIR -j javassist.util.proxy.Proxy
You can download jarscan from here https://java.net/projects/jarscan/downloads
If you found that several packages contains the same class, you are done.
Malaguna,
Thanks for your help. Here's the result of jarscan :
D:\temp\java\jarscan>jarscan -j javassist.util.proxy.Proxy
......................
+javassist-3.18.1-GA.jar
javassist-3.18.1-GA.jar\javassist/util/proxy/Proxy.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$1.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$2.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$3.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$ClassLoaderProvide
r.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$Find2MethodsArgs.c
lass
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$ProxyDetails.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory$UniqueName.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyFactory.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyObject.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyObjectInputStream.class
javassist-3.18.1-GA.jar\javassist/util/proxy/ProxyObjectOutputStream.class
----------------------------------------------
Scanned archives: 22
Errors: 0
Archives with hits: 12
So, it means that no other jar contains that class.

openjpa enhancer fails on one-to-many, but only if its after one-to-one?

I get the following exception when I have my open JPA entity mapping set up with a one-to-many mapping listed after a one-to-one mapping. When I switch the order, I don't get the exception.
I'm assuming that there is an XSD rule being applied, but what is the purpose of that rule?
Failed to execute goal
org.apache.openjpa:openjpa-maven-plugin:2.2.2:enhance (enhancer) on
project: Execution enhancer of goal
org.apache.openjpa:openjpa-maven-plugin:2.2.2:enhance failed:
org.xml.sax.SAXException: Invalid content was found starting with
element 'one-to-many'. One of
'{"http://java.sun.com/xml/ns/persistence/orm":one-to-one,
"http://java.sun.com/xml/ns/persistence/orm":many-to-many,
"http://java.sun.com/xml/ns/persistence/orm":element-collection,
"http://java.sun.com/xml/ns/persistence/orm":embedded,
"http://java.sun.com/xml/ns/persistence/orm":transient}' is expected.
<!-- FAILED -->
<entity class="com.test.comm">
<table schema="dbo" name="tbl_comm_data"/>
<attributes>
<id name="commId">
<column name="comm_id"/>
</id>
<basic name="commName">
<column name="comm_name"/>
</basic>
<one-to-one name="CommType" target-entity="com.test.TblCommType" mapped-by="TblComm" fetch="LAZY">
<cascade>
<cascade-merge/>
</cascade>
</one-to-one>
<one-to-many name="CommDtls" target-entity="com.test.TblCommDtl" mapped-by="tblCommFreq">
<cascade>
<cascade-merge/>
</cascade>
</one-to-many>
</attributes>
</entity>
<!-- WORKED -->
<entity class="com.test.comm">
<table schema="dbo" name="tbl_comm_data"/>
<attributes>
<id name="commId">
<column name="comm_id"/>
</id>
<basic name="commName">
<column name="comm_name"/>
</basic>
<one-to-many name="CommDtls" target-entity="com.test.TblCommDtl" mapped-by="tblCommFreq">
<cascade>
<cascade-merge/>
</cascade>
</one-to-many>
<one-to-one name="CommType" target-entity="com.test.TblCommType" mapped-by="TblComm" fetch="LAZY">
<cascade>
<cascade-merge/>
</cascade>
</one-to-one>
</attributes>
</entity>

PropelORM+PostgreSQL: How do I define an SQL-like CHECK constraint on a column in 'schema.xml'?

A little snippet of a database schema I'm trying to define in my "schema.xml" file:
<table name="hotelroom" phpName="hotelroom">
<column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
<column name="room_number" type="varchar" size="10" required="true" />
<column name="price" type="numeric" defaultValue="1000" required="true" />
<unique>
<unique-column name="room_number" />
</unique>
</table>
In PostgreSQL for that "price" column I would've written CHECK (price > 0::numeric),but I can't seem to find any way to achieve this here.I've checked the documentation (http://propelorm.org/documentation/reference/schema.html), but couldn't find anything on this.
Thank you for the time.
You're using v1, but from the doc link above, looks like you're using v2,
I think you're looking for the GreaterThan which is only available from v2 onwards.
<behavior name="validate">
<parameter name="rule1" value="{column: price, validator: GreaterThan, options: {value: 0, message=Price is not valid}}" />
</behavior>

Liquibase changeset by dbms type

How can I use the same change set with content for different databases?
<changeSet author="azare (generated)" id="some-data>
<insert tableName="some-table">
<column name="id" valueNumeric="1"/>
if h2
<column name="some-column" value="h2-val"/>
if postgresql
<column name="some-column" value="postgresql-val"/>
</insert>
</changeSet>
I found a way to solve this issue:
<property name="val" dbms="postgresql" value="postgresql-val"/>
<property name="val" dbms="h2" value="h2-val"/>
<changeSet author="azare (generated)" id="some-data">
<insert tableName="some-table">
<column name="id" valueNumeric="1"/>
<column name="some-column" value="${val}"/>
</insert>
</changeSet>