diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_IncludeIT.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_IncludeIT.java index 20400cdc7..8e81d74a1 100644 --- a/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_IncludeIT.java +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_IncludeIT.java @@ -13,7 +13,10 @@ import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; -import javax.ws.rs.core.*; +import javax.ws.rs.core.Configuration; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; public class GET_IncludeIT extends DbTest { diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_Related_IT.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_Related_IT.java index 33443a982..fdb75449a 100644 --- a/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_Related_IT.java +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/GET_Related_IT.java @@ -9,9 +9,12 @@ import io.agrest.cayenne.cayenne.main.E18; import io.agrest.cayenne.cayenne.main.E2; import io.agrest.cayenne.cayenne.main.E3; +import io.agrest.cayenne.cayenne.main.E32; +import io.agrest.cayenne.cayenne.main.E33; import io.agrest.cayenne.unit.AgCayenneTester; import io.agrest.cayenne.unit.DbTest; import io.bootique.junit5.BQTestTool; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import javax.ws.rs.GET; @@ -28,8 +31,7 @@ public class GET_Related_IT extends DbTest { @BQTestTool static final AgCayenneTester tester = tester(Resource.class) - .entities(E2.class, E3.class, E17.class, E18.class) - .entitiesAndDependencies(E12.class, E13.class) + .entitiesAndDependencies(E2.class, E3.class, E17.class, E18.class, E12.class, E13.class, E32.class, E33.class) .build(); @Test @@ -134,6 +136,26 @@ public void testToManyJoin() { .bodyEquals(1, "{\"id\":{\"e12_id\":12,\"e13_id\":16},\"e12\":{\"id\":12},\"e13\":{\"id\":16}}"); } + @Test + @Disabled("This is a problem in 4.x, that was fixed in 5.x") + public void testCompoundRootKey() { + + tester.e33().insertColumns("p_id", "name") + .values(11, "n33_1") + .values(12, "n33_2").exec(); + + tester.e32().insertColumns("p_id", "s_id", "t_id", "name") + .values(11, 101, 1001, "n32_1") + .values(12, 102, 1002, "n32_2").exec(); + + tester.target("/e32") + .queryParam("include", "e33") + .get() + .wasOk() + .bodyEquals(2, "{\"id\":{\"p_id\":11,\"s_id\":101,\"t_id\":1001},\"e33\":{},\"name\":\"n32_1\"}," + + "{\"id\":{\"p_id\":12,\"s_id\":102,\"t_id\":1002},\"e33\":{},\"name\":\"n32_2\"}"); + } + @Path("") public static class Resource { @@ -183,5 +205,11 @@ public DataResponse getChildren( return Ag.select(E18.class, config).parent(E17.class, parentIds, E17.E18S.getName()).uri(uriInfo).get(); } + + @GET + @Path("e32") + public DataResponse getE32(@Context UriInfo uriInfo) { + return Ag.select(E32.class, config).uri(uriInfo).get(); + } } } diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/E32.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/E32.java new file mode 100644 index 000000000..c4dc10f12 --- /dev/null +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/E32.java @@ -0,0 +1,9 @@ +package io.agrest.cayenne.cayenne.main; + +import io.agrest.cayenne.cayenne.main.auto._E32; + +public class E32 extends _E32 { + + private static final long serialVersionUID = 1L; + +} diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/E33.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/E33.java new file mode 100644 index 000000000..690dbef12 --- /dev/null +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/E33.java @@ -0,0 +1,9 @@ +package io.agrest.cayenne.cayenne.main; + +import io.agrest.cayenne.cayenne.main.auto._E33; + +public class E33 extends _E33 { + + private static final long serialVersionUID = 1L; + +} diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/auto/_E32.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/auto/_E32.java new file mode 100644 index 000000000..2dd38a5cb --- /dev/null +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/auto/_E32.java @@ -0,0 +1,109 @@ +package io.agrest.cayenne.cayenne.main.auto; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.apache.cayenne.BaseDataObject; +import org.apache.cayenne.exp.property.EntityProperty; +import org.apache.cayenne.exp.property.PropertyFactory; +import org.apache.cayenne.exp.property.StringProperty; + +import io.agrest.cayenne.cayenne.main.E33; + +/** + * Class _E32 was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public abstract class _E32 extends BaseDataObject { + + private static final long serialVersionUID = 1L; + + public static final String S_ID_PK_COLUMN = "s_id"; + public static final String P_ID_PK_COLUMN = "p_id"; + public static final String T_ID_PK_COLUMN = "t_id"; + + public static final StringProperty NAME = PropertyFactory.createString("name", String.class); + public static final EntityProperty E33 = PropertyFactory.createEntity("e33", E33.class); + + protected String name; + + protected Object e33; + + public void setName(String name) { + beforePropertyWrite("name", this.name, name); + this.name = name; + } + + public String getName() { + beforePropertyRead("name"); + return this.name; + } + + public void setE33(E33 e33) { + setToOneTarget("e33", e33, true); + } + + public E33 getE33() { + return (E33)readProperty("e33"); + } + + @Override + public Object readPropertyDirectly(String propName) { + if(propName == null) { + throw new IllegalArgumentException(); + } + + switch(propName) { + case "name": + return this.name; + case "e33": + return this.e33; + default: + return super.readPropertyDirectly(propName); + } + } + + @Override + public void writePropertyDirectly(String propName, Object val) { + if(propName == null) { + throw new IllegalArgumentException(); + } + + switch (propName) { + case "name": + this.name = (String)val; + break; + case "e33": + this.e33 = val; + break; + default: + super.writePropertyDirectly(propName, val); + } + } + + private void writeObject(ObjectOutputStream out) throws IOException { + writeSerialized(out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + readSerialized(in); + } + + @Override + protected void writeState(ObjectOutputStream out) throws IOException { + super.writeState(out); + out.writeObject(this.name); + out.writeObject(this.e33); + } + + @Override + protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException { + super.readState(in); + this.name = (String)in.readObject(); + this.e33 = in.readObject(); + } + +} diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/auto/_E33.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/auto/_E33.java new file mode 100644 index 000000000..44d197be7 --- /dev/null +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/cayenne/main/auto/_E33.java @@ -0,0 +1,87 @@ +package io.agrest.cayenne.cayenne.main.auto; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.apache.cayenne.BaseDataObject; +import org.apache.cayenne.exp.property.PropertyFactory; +import org.apache.cayenne.exp.property.StringProperty; + +/** + * Class _E33 was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public abstract class _E33 extends BaseDataObject { + + private static final long serialVersionUID = 1L; + + public static final String P_ID_PK_COLUMN = "p_id"; + + public static final StringProperty NAME = PropertyFactory.createString("name", String.class); + + protected String name; + + + public void setName(String name) { + beforePropertyWrite("name", this.name, name); + this.name = name; + } + + public String getName() { + beforePropertyRead("name"); + return this.name; + } + + @Override + public Object readPropertyDirectly(String propName) { + if(propName == null) { + throw new IllegalArgumentException(); + } + + switch(propName) { + case "name": + return this.name; + default: + return super.readPropertyDirectly(propName); + } + } + + @Override + public void writePropertyDirectly(String propName, Object val) { + if(propName == null) { + throw new IllegalArgumentException(); + } + + switch (propName) { + case "name": + this.name = (String)val; + break; + default: + super.writePropertyDirectly(propName, val); + } + } + + private void writeObject(ObjectOutputStream out) throws IOException { + writeSerialized(out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + readSerialized(in); + } + + @Override + protected void writeState(ObjectOutputStream out) throws IOException { + super.writeState(out); + out.writeObject(this.name); + } + + @Override + protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException { + super.readState(in); + this.name = (String)in.readObject(); + } + +} diff --git a/agrest-cayenne/src/test/java/io/agrest/cayenne/unit/AgCayenneTester.java b/agrest-cayenne/src/test/java/io/agrest/cayenne/unit/AgCayenneTester.java index 8da7a5d2e..ba316bf74 100644 --- a/agrest-cayenne/src/test/java/io/agrest/cayenne/unit/AgCayenneTester.java +++ b/agrest-cayenne/src/test/java/io/agrest/cayenne/unit/AgCayenneTester.java @@ -222,6 +222,14 @@ public Table e31() { return db.getTable("e31"); } + public Table e32() { + return db.getTable("e32"); + } + + public Table e33() { + return db.getTable("e33"); + } + protected CayenneTester getCayenneInScope() { return Objects.requireNonNull(cayenneInScope, "Not in test scope"); } diff --git a/agrest-cayenne/src/test/resources/datamap.map.xml b/agrest-cayenne/src/test/resources/datamap.map.xml index 90941aed4..892647d0f 100644 --- a/agrest-cayenne/src/test/resources/datamap.map.xml +++ b/agrest-cayenne/src/test/resources/datamap.map.xml @@ -158,6 +158,16 @@ + + + + + + + + + + @@ -299,6 +309,12 @@ + + + + + + @@ -402,6 +418,12 @@ + + + + + + @@ -442,17 +464,35 @@ + + + + TABLE + VIEW + + false + false + org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator + false + false + false + true + ../java entity templates/v4_1/superclass.vm + templates/v4_1/embeddable-subclass.vm + templates/v4_1/embeddable-superclass.vm + templates/v4_1/datamap-subclass.vm + templates/v4_1/datamap-superclass.vm *.java true true diff --git a/agrest-cayenne/src/test/resources/schema-derby.sql b/agrest-cayenne/src/test/resources/schema-derby.sql index 389701eba..efea5b638 100644 --- a/agrest-cayenne/src/test/resources/schema-derby.sql +++ b/agrest-cayenne/src/test/resources/schema-derby.sql @@ -100,6 +100,13 @@ CREATE TABLE "e29" ("id1" INTEGER NOT NULL, "id2" INTEGER NOT NULL, PRIMARY KE CREATE TABLE "e31" ("id" INTEGER NOT NULL, "name" VARCHAR(100) , PRIMARY KEY ("id")) ; +CREATE TABLE "e33" ("name" VARCHAR (100), "p_id" INTEGER NOT NULL, PRIMARY KEY ("p_id")) +; + +CREATE TABLE "e32" ("s_id" INTEGER NOT NULL, "p_id" INTEGER NOT NULL, "t_id" INTEGER NOT NULL, "name" VARCHAR (100), PRIMARY KEY ("s_id", "p_id", "t_id")) +; + + ALTER TABLE "e14" ADD FOREIGN KEY ("e15_id") REFERENCES "e15" ("long_id") ; @@ -148,6 +155,9 @@ ALTER TABLE "e3" ADD FOREIGN KEY ("e2_id") REFERENCES "e2" ("id_") ALTER TABLE "e3" ADD FOREIGN KEY ("e5_id") REFERENCES "e5" ("id") ; +ALTER TABLE "e32" ADD FOREIGN KEY ("p_id") REFERENCES "e33" ("p_id") +; + CREATE SEQUENCE "PK_E1" AS BIGINT START WITH 200 INCREMENT BY 20 NO MAXVALUE NO CYCLE ; @@ -226,6 +236,12 @@ CREATE SEQUENCE "PK_E8" AS BIGINT START WITH 200 INCREMENT BY 20 NO MAXVALUE NO CREATE SEQUENCE "PK_E28" AS BIGINT START WITH 200 INCREMENT BY 20 NO MAXVALUE NO CYCLE ; +CREATE SEQUENCE "PK_E33" AS BIGINT START WITH 200 INCREMENT BY 20 NO MAXVALUE NO CYCLE +; + +CREATE SEQUENCE "PK_E32" AS BIGINT START WITH 200 INCREMENT BY 20 NO MAXVALUE NO CYCLE +; + -- iso CREATE TABLE "SQL_DATE_TEST" ("Date" DATE , "ID" INTEGER NOT NULL, "Time" TIME , "Timestamp" TIMESTAMP , PRIMARY KEY ("ID")) ;