Hello Patrik,
attached you can find patch for MysqlDDL.xpt. I did my best and pull out
only necessary foreign references. Maybe I also find bug in OracleDDL.xpt
My testing model.design (bellow) generate with Oracle following error:
3585 ERROR AbstractExpressionsUsingWorkflowComponent - Error in
Component generator of type org.openarchitectureware.xpand2.Generator:
EvaluationException : Ambiguous operations String
getDatabaseName(Attribute attribute) and String
getDatabaseName(DomainObject domainObject) for param types [Void]
templates::OracleDDL.xpt[6989,39] on line 162
'from.getIdAttribute().getDatabaseName()'
templates::OracleDDL.xpt[6122,152] on line 150 'EXPAND
uniManyForeignKeyConstraint FOREACH
references.select(r|r.many&&r.opposite.==(null)&&r.isInverse()&&r.to.hasOwnDatabaseRepresentation())'
I guess you should replace line 162 in OracleDDL.xpt
FOREIGN KEY («from.getDatabaseName()») REFERENCES
«from.getDatabaseName()» («from.getIdAttribute().getDatabaseName()»)
with
FOREIGN KEY («from.getDatabaseName()») REFERENCES
«from.getRootExtends().getDatabaseName()»(«from.getRootExtends().getIdAttribute().getDatabaseName()»);
of course if I understand you idea about inverse reference right. If
not, please fix MySQL version too.
Regards
Pavel
--------------------------------- model.design ---------------------------------
Application MyApp {
basePackage=org.f4s.s4cc
Module core {
abstract Entity C {
String keyC1 key;
String keyC2 key;
}
Entity A extends C {
String keyA1 key;
String keyA2 key;
- @B bcko;
- Set<@B> setBcko;
- Set<@B> setBckoInv inverse <-> bBackInv;
- Set<@B> setBckoInvOne inverse;
- Set<@B> setBckoOpo <-> bBack;
}
Entity B {
String noKeyB1;
String noKeyB2;
- Set<@A> bBackInv <-> setBckoInv;
- @A bBack <-> setBckoOpo;
}
}
}
--------------------------------- MyApp_DDL.sql
---------------------------------
-- ###########################################
-- # Drop entities
-- ###########################################
-- Many to many relations
DROP TABLE IF EXISTS BBACKINV_SETBCKOINV;
DROP TABLE IF EXISTS A_SETBCKO;
-- Normal entities
DROP TABLE IF EXISTS A;
DROP TABLE IF EXISTS B;
DROP TABLE IF EXISTS C;
-- ###########################################
-- # Create new entities
-- ###########################################
-- Normal entities
CREATE TABLE C (
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
KEYC1 VARCHAR(100) NOT NULL,
KEYC2 VARCHAR(100) NOT NULL,
CREATEDDATE TIMESTAMP,
CREATEDBY VARCHAR(50),
LASTUPDATED TIMESTAMP,
LASTUPDATEDBY VARCHAR(50),
VERSION BIGINT NOT NULL,
CONSTRAINT UNIQUE (KEYC1, KEYC2)
);
CREATE TABLE B (
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
NOKEYB1 VARCHAR(100) NOT NULL,
NOKEYB2 VARCHAR(100) NOT NULL,
UUID VARCHAR(255) NOT NULL,
CREATEDDATE TIMESTAMP,
CREATEDBY VARCHAR(50),
LASTUPDATED TIMESTAMP,
LASTUPDATEDBY VARCHAR(50),
VERSION BIGINT NOT NULL,
BBACK BIGINT NOT NULL,
A BIGINT,
CONSTRAINT UNIQUE (UUID)
);
CREATE TABLE A (
KEYA1 VARCHAR(100) NOT NULL,
KEYA2 VARCHAR(100) NOT NULL,
BCKO BIGINT NOT NULL,
C BIGINT,
CONSTRAINT UNIQUE (KEYA1, KEYA2)
);
-- Reference from B.BBACK to A
ALTER TABLE B ADD CONSTRAINT FK_B_BBACK
FOREIGN KEY (BBACK) REFERENCES C(ID) ON DELETE CASCADE;
-- Reference from A.BCKO to B
ALTER TABLE A ADD CONSTRAINT FK_A_BCKO
FOREIGN KEY (BCKO) REFERENCES B(ID);
-- Entity B inverse referenced from A.setBckoInvOne
ALTER TABLE B ADD CONSTRAINT FK_B_A
FOREIGN KEY (A) REFERENCES C(ID);
-- Entity A extends C
ALTER TABLE A ADD CONSTRAINT FK_A_C
FOREIGN KEY (C) REFERENCES C(ID);
-- Many to many relations
CREATE TABLE A_SETBCKO (
SETBCKO BIGINT NOT NULL,
FOREIGN KEY (SETBCKO) REFERENCES B(ID),
A BIGINT NOT NULL,
FOREIGN KEY (A) REFERENCES C(ID));
CREATE TABLE BBACKINV_SETBCKOINV (
SETBCKOINV BIGINT NOT NULL,
FOREIGN KEY (SETBCKOINV) REFERENCES B(ID),
BBACKINV BIGINT NOT NULL,
FOREIGN KEY (BBACKINV) REFERENCES C(ID));
Index: src/main/resources/templates/MysqlDDL.xpt
===================================================================
--- src/main/resources/templates/MysqlDDL.xpt (revision 4154)
+++ src/main/resources/templates/MysqlDDL.xpt (working copy)
@@ -21,23 +21,35 @@
?EXTENSION extensions::properties?
?DEFINE ddl FOR Application?
- ?FILE "dbschema/" + name + "_ddl.sql" TO_GEN_RESOURCES?
-
+ ?FILE "dbschema/" + name + "_ddl.sql" TO_GEN_RESOURCES-?
+-- ###########################################
+-- # Drop entities
+-- ###########################################
+
+-- Many to many relations
?EXPAND dropTable FOREACH resolveManyToManyRelations(false)?
+-- Normal entities
?EXPAND dropTable FOREACH getDomainObjectsInCreateOrder(false)?
- ?EXPAND createTable FOREACH getDomainObjectsInCreateOrder(true)?
-
- ?EXPAND createTable FOREACH resolveManyToManyRelations(true)?
+-- ###########################################
+-- # Create new entities
+-- ###########################################
+
+-- Normal entities
+ ?EXPAND createTable(false) FOREACH getDomainObjectsInCreateOrder(true)-?
+ ?EXPAND foreignKeyAlter FOREACH getDomainObjectsInCreateOrder(true)-?
+ ?EXPAND extendsForeignKeyAlter FOREACH getDomainObjectsInCreateOrder(true).select(d | d.extends != null)?
+-- Many to many relations
+ ?EXPAND createTable(true) FOREACH resolveManyToManyRelations(true)-?
?ENDFILE ?
?ENDDEFINE ?
-?DEFINE dropTable FOR DomainObject?
+?DEFINE dropTable FOR DomainObject-?
DROP TABLE IF EXISTS ?getDatabaseName()?;
-?ENDDEFINE ?
+?ENDDEFINE?
-?DEFINE createTable FOR DomainObject?
+?DEFINE createTable(Boolean manyToManyRelationTable) FOR DomainObject-?
?LET module == null ? {} : module.application.modules.domainObjects.references.select(e | e.to == this && e.many && e.opposite == null && e.isInverse()) AS uniManyToThis -?
?LET !uniManyToThis.isEmpty AS hasUniManyToThis -?
?LET references.select(r | !r.many && (r.to.hasOwnDatabaseRepresentation())).size != 0 AS hasOneReferences -?
@@ -45,31 +57,27 @@
?LET references.select(r | r.to.metaType == Enum).size != 0 AS hasEnumColumns -?
?LET getNaturalKeyReference() != null || !getNaturalKeyAttributes().isEmpty || attributes.exists(a | a.name == "uuid") AS hasUniqueConstraints -?
CREATE TABLE ?getDatabaseName()? (
-?EXPAND column("") FOREACH attributes SEPARATOR ",
-"-?
+?EXPAND column("") FOREACH attributes SEPARATOR ",\n"-?
?IF (attributes.size > 0) && hasOneReferences?,
?ENDIF-?
-?EXPAND foreignKey FOREACH references.select(r | !r.many && r.to.hasOwnDatabaseRepresentation()).reject(e|e.isOneToOne() && e.isInverse()) SEPARATOR ",
-"-?
+?EXPAND foreignKey(manyToManyRelationTable) FOREACH references.select(r | !r.many && r.to.hasOwnDatabaseRepresentation()).reject(e|e.isOneToOne() && e.isInverse()) SEPARATOR ",\n"-?
?IF ((attributes.size > 0) || hasOneReferences) && hasUniManyToThis?,
?ENDIF-?
-?EXPAND uniManyForeignKey FOREACH uniManyToThis SEPARATOR ",
-"-?
+?EXPAND uniManyForeignKey FOREACH uniManyToThis SEPARATOR ",\n"-?
?IF ((attributes.size > 0) || hasOneReferences || hasUniManyToThis) && hasContainedColumns?,
?ENDIF-?
-?EXPAND containedColumns FOREACH getBasicTypeReferences() SEPARATOR ",
-"-?
+?EXPAND containedColumns FOREACH getBasicTypeReferences() SEPARATOR ",\n"-?
?IF ((attributes.size > 0) || hasOneReferences || hasUniManyToThis || hasContainedColumns) && hasEnumColumns?,
?ENDIF-?
-?EXPAND enumColumn("") FOREACH references.select(r | r.to.metaType == Enum) SEPARATOR ",
-"-?
-?IF ((attributes.size > 0) || hasOneReferences || hasUniManyToThis || hasContainedColumns || hasEnumColumns) && (extends != null)?,
+?EXPAND enumColumn("") FOREACH references.select(r | r.to.metaType == Enum) SEPARATOR ",\n"-?
+?IF ((attributes.size > 0) || hasOneReferences || hasUniManyToThis || hasContainedColumns || hasEnumColumns) && (extends != null)-?,
+?EXPAND extendsForeignKey-?
?ENDIF-?
-?IF extends != null??EXPAND extendsForeignKey??ENDIF?
?IF hasUniqueConstraints-?,
?EXPAND uniqueConstraint -?
?ENDIF-?
);
+
?ENDLET -?
?ENDLET -?
?ENDLET -?
@@ -82,35 +90,62 @@
?prefix??getDatabaseName()? ?getDatabaseType()??getDatabaseTypeNullability()??
IF name == "id"? AUTO_INCREMENT PRIMARY KEY?ENDIF-??
IF index?,
- INDEX (?prefix??getDatabaseName()?)?ENDIF??ENDDEFINE?
+ INDEX (?prefix??getDatabaseName()?)?ENDIF-?
+?ENDDEFINE?
?DEFINE containedColumns FOR Reference-?
- ?EXPAND column(getDatabaseName() + "_") FOREACH to.attributes SEPARATOR ",
- "-??IF !to.references.select(r | r.to.metaType == Enum).isEmpty?,
- ?ENDIF??EXPAND enumColumn(getDatabaseName() + "_") FOREACH to.references.select(r | r.to.metaType == Enum) SEPARATOR ",
- "-??ENDDEFINE?
+ ?EXPAND column(getDatabaseName() + "_") FOREACH to.attributes SEPARATOR ",\n"-?
+ ?IF !to.references.select(r | r.to.metaType == Enum).isEmpty?,
+ ?ENDIF??EXPAND enumColumn(getDatabaseName() + "_") FOREACH to.references.select(r | r.to.metaType == Enum) SEPARATOR ",\n"-?
+?ENDDEFINE?
?DEFINE enumColumn(String prefix) FOR Reference-?
?prefix??getDatabaseName()? ?getEnumDatabaseType()??getDatabaseTypeNullability()??ENDDEFINE?
-?DEFINE foreignKey FOR Reference-?
+?DEFINE foreignKey(Boolean manyToManyRelationTable) FOR Reference-?
?IF "list" == getCollectionType()-?
?getDatabaseName()?_INDEX INTEGER,
?ENDIF-?
- ?getForeignKeyName()? ?getForeignKeyType()?,
+ ?getForeignKeyName()? ?getForeignKeyType()??
+ IF manyToManyRelationTable-?,
+ FOREIGN KEY (?getForeignKeyName()?) REFERENCES ?to.getRootExtends().getDatabaseName()?(?to.getRootExtends().getIdAttribute().getDatabaseName()?)?
+ IF (opposite != null) && opposite.isDbOnDeleteCascade()? ON DELETE CASCADE?ENDIF??ENDIF-?
+?ENDDEFINE?
+
+?DEFINE foreignKeyAlter FOR DomainObject-?
+ ?EXPAND foreignKeyAlter FOREACH references.select(r | !r.many && r.to.hasOwnDatabaseRepresentation()).reject(e|e.isOneToOne() && e.isInverse())-?
+ ?EXPAND uniManyForeignKeyAlter FOREACH references.select(r | r.many && r.opposite == null && r.isInverse() && (r.to.hasOwnDatabaseRepresentation()))?
+?ENDDEFINE?
+
+?DEFINE foreignKeyAlter FOR Reference-?
+-- Reference from ?from.name?.?getForeignKeyName()? to ?to.name?
+ALTER TABLE ?from.getDatabaseName()? ADD CONSTRAINT FK_?truncateLongDatabaseName(from.getDatabaseName() + "_" + getDatabaseName())?
FOREIGN KEY (?getForeignKeyName()?) REFERENCES ?to.getRootExtends().getDatabaseName()?(?to.getRootExtends().getIdAttribute().getDatabaseName()?)?
- IF (opposite != null) && opposite.isDbOnDeleteCascade()? ON DELETE CASCADE?ENDIF??ENDDEFINE?
+ IF (opposite != null) && opposite.isDbOnDeleteCascade()? ON DELETE CASCADE?ENDIF?;
+?ENDDEFINE?
?DEFINE extendsForeignKey FOR DomainObject-?
- ?extends.getExtendsForeignKeyName()? ?extends.getForeignKeyType()?,
- FOREIGN KEY (?extends.getExtendsForeignKeyName()?) REFERENCES ?extends.getRootExtends().getDatabaseName()?(?extends.getRootExtends().getIdAttribute().getDatabaseName()?)?ENDDEFINE?
+ ?extends.getExtendsForeignKeyName()? ?extends.getForeignKeyType()-?
+?ENDDEFINE?
+
+?DEFINE extendsForeignKeyAlter FOR DomainObject-?
+-- Entity ?name? extends ?extends.getRootExtends().name?
+ALTER TABLE ?getDatabaseName()? ADD CONSTRAINT FK_?getDatabaseName()?_?extends.getExtendsForeignKeyName()?
+ FOREIGN KEY (?extends.getExtendsForeignKeyName()?) REFERENCES ?extends.getRootExtends().getDatabaseName()?(?extends.getRootExtends().getIdAttribute().getDatabaseName()?);
+?ENDDEFINE?
?DEFINE uniManyForeignKey FOR Reference-?
?IF "list" == getCollectionType()-?
?getDatabaseName()?_INDEX INTEGER,
?ENDIF-?
- ?from.getDatabaseName()? ?from.getForeignKeyType()?,
- FOREIGN KEY (?from.getDatabaseName()?) REFERENCES ?from.getDatabaseName()?(?from.getIdAttribute().getDatabaseName()?)?ENDDEFINE?
+ ?from.getDatabaseName()? ?from.getForeignKeyType()-?
+?ENDDEFINE?
+
+?DEFINE uniManyForeignKeyAlter FOR Reference-?
+-- Entity ?to.name? inverse referenced from ?from.name?.?name?
+ALTER TABLE ?to.getDatabaseName()? ADD CONSTRAINT FK_?truncateLongDatabaseName(to.getDatabaseName() + "_" + from.getDatabaseName())?
+ FOREIGN KEY (?from.getDatabaseName()?) REFERENCES ?from.getRootExtends().getDatabaseName()?(?from.getRootExtends().getIdAttribute().getDatabaseName()?);
+?ENDDEFINE?
?DEFINE uniqueConstraint FOR DomainObject-?
?IF getNaturalKeyReference() != null -?
@@ -119,4 +154,3 @@
?ELSE -?
CONSTRAINT UNIQUE (?FOREACH attributes.select(a | a.naturalKey || a.name == "uuid") AS a SEPARATOR ", "??a.getDatabaseName()??ENDFOREACH?)
?ENDIF??ENDDEFINE?
-
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Fornax-developer mailing list
Fornax-developer@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fornax-developer