Open signedav opened 2 years ago
Before I knock on the ili2db door I first ask for any experience on that, since I think if it's an issue you might have encountered it already @zigertiger @romefi Maybe I just made something wrong on schema create or modelling.
In case it's something ili2db cannot handle, we might want to think about a Model Baker solution.
Is there something missing on the described use case (model or command) or is it just not supported the way it is @claeis? Are there any suggestions how to handle it?
While ordinary one-to-many associations works like expected: ili:0
[...]
ASSOCIATION Asset_Publication =
Asset -- {1} Asset;
Publication -- {0..*} Publication;
END Asset_Publication;
[...]
sql:
[...]
asset bigint NOT NULL,
CONSTRAINT publication_asset_fkey FOREIGN KEY (asset)
[...]
This might be a weakness in ili2db but as far as I understood @claeis is not that easy solvable since in other situation these fields need to be NULL. I think that it cannot be built in the physical database with a NOT NULL constraint.
Ok, makes sense to me. Do you see a chance to solve that on Model Baker without the NOT NULL in the database? Or shall we leave it to:
I do not know whether it is the right place to add those thoughts. If not please feel free to move this to a new issue or discussion.
Is there a general concept about the use of ModelBaker? Is it ...
I think depeding on what I want to do I would want MANDATORY constraints checked or not. Or set flags like --disablevalidation on or off (see https://github.com/claeis/ili2db/blob/master/docs/ili2db.rst#fehlerhafte-daten).
When I look at the development of the last months there have been beeen various tasks added and you can use it for all three purposes above and even more. But it would need other default settings depending on what you want to do. May be it would be wise to display this also in the ModelBaker wizzard?
Thanks for your inputs.
There are the ili2db.ili.attrCardinalityMin
entries for each attribute. I didn't checked it 100% but I guess this could be a stable initiator that this value should not be NULL. So I see a chance that Model Baker can handle it without NOT NULL in the database @romefi
@sjib Yes, Model Baker can handle all of your mentioned workflows. I think, the reason to be able to import invalid data could be just to visualize them or to correct them as well. Anyway the constraints should be - as much as possible - like in the model.
The case that a user wants to produce invalid data by having no constraints (maybe to be quick and fix it later on) is more a side case that can be managed by removing the constraints from the project manually.
@sjib Model Baker should cover all these use cases. It's worth a thought to add more usecases in the wizzard and have the propper settings depending on the use case. Thanks for the input. We'll discuss it in the project steeriing group.
For now the focus lays on helping people collecting new data, so all constraints should be covered if ever possible. @signedav as it's not high priority I suggest we discuss this issue at the next meeting.
Note: Be aware of inheritances.
INTERLIS 2.3;
MODEL Gebaeude (de)
AT "https://signedav.github.io/usabilitydave/"
VERSION "2021-12-21" =
IMPORTS CatalogueObjects_V1;
TOPIC Katalog =
CLASS MaterialItem
EXTENDS CatalogueObjects_V1.Catalogues.Item =
Code : MANDATORY TEXT;
Bezeichnung : TEXT;
END MaterialItem;
STRUCTURE MaterialItemRef
EXTENDS CatalogueObjects_V1.Catalogues.MandatoryCatalogueReference =
/* Reference is MANDATORY because it extends mandatory Rerference in MandatoryCatalogueReference */
Reference (EXTENDED) : REFERENCE TO (EXTERNAL) MaterialItem;
END MaterialItemRef;
END Katalog;
TOPIC Gebaeude =
DEPENDS ON Gebaeude.Katalog;
CLASS Objekt =
Name: MANDATORY TEXT;
END Objekt;
/* In diesem Fall ist Material in der DB nullable und muss es wohl auch sein bei Smart Inheritance 1*/
CLASS Haus EXTENDS Objekt=
Material : MANDATORY Gebaeude.Katalog.MaterialItemRef;
END Haus;
CLASS Statue EXTENDS Objekt =
Thema: MANDATORY TEXT;
END Statue;
END Gebaeude;
END Gebaeude.
Here we have in object
mandatory name
, in haus
mandatory Material
and in statue
mandatory thema
. But when using smart inheritance 1 it will make a super class called object
having all those attributes and a type
. So some of them needs to be nullable.
CREATE TABLE IF NOT EXISTS gebauede_smart_1.objekt
(
t_id bigint NOT NULL DEFAULT nextval('gebauede_smart_1.t_ili2db_seq'::regclass),
t_basket bigint NOT NULL,
t_type character varying(60) COLLATE pg_catalog."default" NOT NULL,
t_ili_tid character varying(200) COLLATE pg_catalog."default",
aname text COLLATE pg_catalog."default" NOT NULL,
material bigint,
thema text COLLATE pg_catalog."default",
CONSTRAINT objekt_pkey PRIMARY KEY (t_id),
CONSTRAINT objekt_material_fkey FOREIGN KEY (material)
REFERENCES gebauede_smart_1.materialitem (t_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED,
CONSTRAINT objekt_t_type_check CHECK (t_type::text = ANY (ARRAY['haus'::character varying, 'objekt'::character varying, 'statue'::character varying]::text[]))
)
As well as Smart1Inheritance with SuperClass having attributes optional and subclasses are extending mandatory
TOPIC Gebaeude =
DEPENDS ON Gebaeude.Katalog;
CLASS Objekt =
Name: MANDATORY TEXT;
Material : Gebaeude.Katalog.MaterialItemRef;
END Objekt;
/* In diesem Fall ist Material in der DB nullable und muss es wohl auch sein bei Smart Inheritance 1*/
CLASS Haus EXTENDS Objekt=
Material (EXTENDED): MANDATORY Gebaeude.Katalog.MaterialItemRef;
END Haus;
CLASS Statue EXTENDS Objekt =
Thema: MANDATORY TEXT;
END Statue;
END Gebaeude;
t_ili2db_meta_attrs | ilielement | attr_name | attr_value |
---|---|---|---|
[...] | [...] | [...] | |
"Gebaeude.Gebaeude.Haus.Material" | "ili2db.ili.attrCardinalityMax" | "1" | |
"Gebaeude.Gebaeude.Haus.Material" | "ili2db.ili.attrCardinalityMin" | "1" | |
[...] | [...] | [...] |
We do have ili2db.ili.attrCardinalityMin
in t_ili2db_meta_attrs
for the current tables class, but as well we might need to check t_ili2db_trafo
if the current class is built as superClass
.
t_ili2db_trafo | iliname | tag | setting |
---|---|---|---|
"Gebaeude.Katalog.MaterialItem" | "ch.ehi.ili2db.inheritance" | "newClass" | |
"Gebaeude.Gebaeude.Haus.Material" | "ch.ehi.ili2db.catalogueRefTrafo" | "coalesce" | |
"Gebaeude.Gebaeude.Statue" | "ch.ehi.ili2db.inheritance" | "superClass" | |
"CatalogueObjects_V1.Catalogues.CatalogueReference" | "ch.ehi.ili2db.inheritance" | "subClass" | |
"Gebaeude.Katalog.MaterialItemRef" | "ch.ehi.ili2db.inheritance" | "newClass" | |
"Gebaeude.Gebaeude.Haus" | "ch.ehi.ili2db.inheritance" | "superClass" | |
"CatalogueObjects_V1.Catalogues.MandatoryCatalogueReference" | "ch.ehi.ili2db.inheritance" | "subClass" | |
"CatalogueObjects_V1.Catalogues.Item" | "ch.ehi.ili2db.inheritance" | "subClass" | |
"Gebaeude.Gebaeude.Objekt" | "ch.ehi.ili2db.inheritance" | "newClass" |
Another situation (not making big sense in catalogues but a fair construct):
INTERLIS 2.3;
MODEL Gebaeude (de)
AT "https://signedav.github.io/usabilitydave/"
VERSION "2021-12-21" =
IMPORTS CatalogueObjects_V1;
TOPIC Katalog =
CLASS MaterialItem
EXTENDS CatalogueObjects_V1.Catalogues.Item =
Code : MANDATORY TEXT;
Bezeichnung : TEXT;
END MaterialItem;
CLASS MaterialItem1
EXTENDS MaterialItem=
Value : TEXT;
END MaterialItem1;
STRUCTURE MaterialItemRef
EXTENDS CatalogueObjects_V1.Catalogues.MandatoryCatalogueReference =
/* Reference is MANDATORY because it extends mandatory Rerference in MandatoryCatalogueReference */
Reference (EXTENDED) : REFERENCE TO (EXTERNAL) MaterialItem;
END MaterialItemRef;
END Katalog;
TOPIC Gebaeude =
DEPENDS ON Gebaeude.Katalog;
CLASS Haus =
Name: TEXT;
Material : MANDATORY Gebaeude.Katalog.MaterialItemRef;
END Haus;
END Gebaeude;
END Gebaeude.
When using smart inheritance 2 it will make a super class called MaterialItem
and MaterialItem1
and it will have two references in materialitemref
and two links in haus
. They need to be nullable.
CREATE TABLE IF NOT EXISTS gebauede_smart2.materialitemref
(
t_id bigint NOT NULL DEFAULT nextval('gebauede_smart2.t_ili2db_seq'::regclass),
t_ili_tid character varying(200) COLLATE pg_catalog."default",
t_seq bigint,
reference_materialitem bigint,
reference_materialitem1 bigint,
CONSTRAINT materialitemref_pkey PRIMARY KEY (t_id),
CONSTRAINT materialitemref_reference_materialitem1_fkey FOREIGN KEY (reference_materialitem1)
REFERENCES gebauede_smart2.materialitem1 (t_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED,
CONSTRAINT materialitemref_reference_materialitem_fkey FOREIGN KEY (reference_materialitem)
REFERENCES gebauede_smart2.materialitem (t_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED
)
and
CREATE TABLE IF NOT EXISTS gebauede_smart2.haus
(
t_id bigint NOT NULL DEFAULT nextval('gebauede_smart2.t_ili2db_seq'::regclass),
t_basket bigint NOT NULL,
t_ili_tid character varying(200) COLLATE pg_catalog."default",
aname text COLLATE pg_catalog."default",
material_materialitem bigint,
material_materialitem1 bigint,
CONSTRAINT haus_pkey PRIMARY KEY (t_id),
CONSTRAINT haus_material_materialitem1_fkey FOREIGN KEY (material_materialitem1)
REFERENCES gebauede_smart2.materialitem1 (t_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED,
CONSTRAINT haus_material_materialitem_fkey FOREIGN KEY (material_materialitem)
REFERENCES gebauede_smart2.materialitem (t_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED
)
t_ili2db_meta_attrs | ilielement | attr_name | attr_value |
---|---|---|---|
[...] | [...] | [...] | |
"Gebaeude.Gebaeude.Haus.Material" | "ili2db.ili.attrCardinalityMax" | "1" | |
"Gebaeude.Gebaeude.Haus.Material" | "ili2db.ili.attrCardinalityMin" | "1" | |
[...] | [...] | [...] |
We do have ili2db.ili.attrCardinalityMin
in t_ili2db_meta_attrs
for the current tables class, but as well we might need to check t_ili2db_trafo
for ... hm... I don't know...
t_ili2db_trafo | iliname | tag | setting |
---|---|---|---|
"Gebaeude.Katalog.MaterialItem" | "ch.ehi.ili2db.inheritance" | "newAndSubClass" | |
"Gebaeude.Gebaeude.Haus.Material" | "ch.ehi.ili2db.catalogueRefTrafo" | "coalesce" | |
"CatalogueObjects_V1.Catalogues.CatalogueReference" | "ch.ehi.ili2db.inheritance" | "subClass" | |
"Gebaeude.Katalog.MaterialItemRef" | "ch.ehi.ili2db.inheritance" | "newAndSubClass" | |
"Gebaeude.Gebaeude.Haus" | "ch.ehi.ili2db.inheritance" | "newAndSubClass" | |
"Gebaeude.Katalog.MaterialItem1" | "ch.ehi.ili2db.inheritance" | "newAndSubClass" | |
"CatalogueObjects_V1.Catalogues.MandatoryCatalogueReference" | "ch.ehi.ili2db.inheritance" | "subClass" | |
"CatalogueObjects_V1.Catalogues.Item" | "ch.ehi.ili2db.inheritance" | "subClass" |
@romefi With 7.4.0 (using ili2db 4.10) this should be solved. Needs to be tested and then we can close this.
Just tested with SH_Pflegeplanung_Fliessgewaesser_V1_0.zip
E..g. Fauna > Objekt is a MANDATORY reference to CatalogueObject. In the formular Objekt is still optional:
Unless the INTERLIS-model is wrong for the use case, it doesn't seem to work.
I can confirm. Tested it again myself and added a comment here https://github.com/claeis/ili2db/issues/475#issuecomment-1422312630
When I have a model using
CatalogueObjects_V1
as catalogue base and I extend (1) theMandatoryCatalogueReference
and (2) set the attribute referencing it to MANDATORY it still creates me a table without any NOT NULL constraint on those attributes.Running this:
Creates in PostgreSQL:
t_ili2db_trafo at smart1