diff --git a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/specs/v1/utils/QuerySpecUtils.java b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/specs/v1/utils/QuerySpecUtils.java index bc50547d..a6b3cfc1 100644 --- a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/specs/v1/utils/QuerySpecUtils.java +++ b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/middleware/javalin/specs/v1/utils/QuerySpecUtils.java @@ -30,7 +30,6 @@ import java.util.Map; import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin; -import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData; import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.middleware.javalin.specs.v1.responses.components.TableVariant; import com.kingsrook.qqq.openapi.model.Content; @@ -101,7 +100,7 @@ public class QuerySpecUtils ***************************************************************************/ public static List getJoinsFromRequestBody(JSONObject requestBody) throws IOException { - if(requestBody.has("joins")) + if(requestBody.has("joins") && !requestBody.isNull("joins")) { Object joinsFromJson = requestBody.get("joins"); if(joinsFromJson instanceof JSONArray joinsJsonArray) @@ -109,19 +108,33 @@ public class QuerySpecUtils List joins = new ArrayList<>(); for(int i = 0; i < joinsJsonArray.length(); i++) { - JSONObject joinJsonObject = joinsJsonArray.getJSONObject(i); - QJoinMetaData joinMetaData = null; - if(joinJsonObject.has("joinName")) + JSONObject joinJsonObject = joinsJsonArray.getJSONObject(i); + QueryJoin queryJoin = new QueryJoin(); + joins.add(queryJoin); + + queryJoin.setJoinTable(joinJsonObject.optString("joinTable")); + + if(joinJsonObject.has("baseTableOrAlias") && !joinJsonObject.isNull("baseTableOrAlias")) { - String joinName = joinJsonObject.getString("joinName"); - joinMetaData = QContext.getQInstance().getJoin(joinName); - joinJsonObject.remove("joinName"); + queryJoin.setBaseTableOrAlias(joinJsonObject.optString("baseTableOrAlias")); } - QueryJoin queryJoin = JsonUtils.toObject(joinJsonObject.toString(), QueryJoin.class); - queryJoin.setJoinMetaData(joinMetaData); + if(joinJsonObject.has("alias") && !joinJsonObject.isNull("alias")) + { + queryJoin.setAlias(joinJsonObject.optString("alias")); + } - joins.add(queryJoin); + queryJoin.setSelect(joinJsonObject.optBoolean("select")); + + if(joinJsonObject.has("type") && !joinJsonObject.isNull("type")) + { + queryJoin.setType(QueryJoin.Type.valueOf(joinJsonObject.getString("type"))); + } + + if(joinJsonObject.has("joinName") && !joinJsonObject.isNull("joinName")) + { + queryJoin.setJoinMetaData(QContext.getQInstance().getJoin(joinJsonObject.getString("joinName"))); + } } return (joins); } diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java index 61e4cdaa..2fc49231 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java @@ -86,6 +86,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView; import com.kingsrook.qqq.backend.core.model.metadata.reporting.ReportType; import com.kingsrook.qqq.backend.core.model.metadata.tables.AssociatedScript; import com.kingsrook.qqq.backend.core.model.metadata.tables.Association; +import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.variants.BackendVariantsConfig; import com.kingsrook.qqq.backend.core.model.savedviews.SavedViewsMetaDataProvider; @@ -120,6 +121,9 @@ public class TestUtils public static final String TABLE_NAME_MEMORY_VARIANT_OPTIONS = "memoryVariantOptions"; public static final String TABLE_NAME_MEMORY_VARIANT_DATA = "memoryVariantData"; + private static final String PERSON_JOIN_PET = "personJoinPet"; + private static final String PERSON_JOIN_PARTNER_PERSON = "PersonJoinPartnerPerson"; + public static final String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive"; public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep"; public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow"; @@ -401,7 +405,9 @@ public class TestUtils .withField(new QFieldMetaData("photoFileName", QFieldType.STRING).withBackendName("photo_file_name")) .withField(new QFieldMetaData("licenseScanPdfUrl", QFieldType.STRING).withBackendName("license_scan_pdf_url")) - .withAssociation(new Association().withName("pets").withJoinName("personJoinPet").withAssociatedTableName(TABLE_NAME_PET)) + .withExposedJoin(new ExposedJoin().withJoinTable(TABLE_NAME_PET).withLabel("Pets").withJoinPath(List.of(PERSON_JOIN_PET))) + + .withAssociation(new Association().withName("pets").withJoinName(PERSON_JOIN_PET).withAssociatedTableName(TABLE_NAME_PET)) .withAssociatedScript(new AssociatedScript() .withFieldName("testScriptId") .withScriptTypeId(1) @@ -509,7 +515,7 @@ public class TestUtils .withLeftTable(TABLE_NAME_PERSON) .withRightTable(TABLE_NAME_PERSON) .withType(JoinType.MANY_TO_ONE) - .withName("PersonJoinPartnerPerson") + .withName(PERSON_JOIN_PARTNER_PERSON) .withJoinOn(new JoinOn("partnerPersonId", "id"))); } @@ -524,7 +530,7 @@ public class TestUtils .withLeftTable(TABLE_NAME_PERSON) .withRightTable(TABLE_NAME_PET) .withType(JoinType.ONE_TO_MANY) - .withName("personJoinPet") + .withName(PERSON_JOIN_PET) .withJoinOn(new JoinOn("id", "ownerPersonId"))); } diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/specs/v1/TableQuerySpecV1Test.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/specs/v1/TableQuerySpecV1Test.java index 07b120fb..f5d06edc 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/specs/v1/TableQuerySpecV1Test.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/middleware/javalin/specs/v1/TableQuerySpecV1Test.java @@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.session.QSystemUserSession; import com.kingsrook.qqq.backend.core.utils.JsonUtils; +import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder; import com.kingsrook.qqq.backend.javalin.TestUtils; import com.kingsrook.qqq.middleware.javalin.specs.AbstractEndpointSpec; import com.kingsrook.qqq.middleware.javalin.specs.SpecTestBase; @@ -102,6 +103,42 @@ class TableQuerySpecV1Test extends SpecTestBase + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testJoin() + { + HttpResponse response = Unirest.post(getBaseUrlAndPath() + "/table/person/query") + .contentType(ContentType.APPLICATION_JSON.getMimeType()) + .body(JsonUtils.toJson(Map.of( + "filter", new QQueryFilter(new QFilterCriteria("lastName", QCriteriaOperator.EQUALS, "Kelkhoff")), + "joins", List.of(MapBuilder.of( + "joinTable", TestUtils.TABLE_NAME_PET, + "select", true, + "type", "LEFT", + "alias", null, + "joinName", null, + "baseTableOrAlias", null + )) + ))) + .asString(); + + assertEquals(200, response.getStatus()); + JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody()); + JSONArray records = jsonObject.getJSONArray("records"); + assertThat(records.length()).isGreaterThanOrEqualTo(3); + + JSONObject record = records.getJSONObject(0); + assertThat(record.getString("recordLabel")).contains("Kelkhoff"); + assertThat(record.getString("tableName")).isEqualTo("person"); + assertThat(record.getJSONObject("values").getString("lastName")).isEqualTo("Kelkhoff"); + assertThat(record.getJSONObject("displayValues").getString("lastName")).isEqualTo("Kelkhoff"); + assertThat(record.getJSONObject("displayValues").getString("pet.name")).isIn(List.of("Chester", "Lucy")); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -226,7 +263,6 @@ class TableQuerySpecV1Test extends SpecTestBase assertEquals(500, response.getStatus()); jsonObject = JsonUtils.toJSONObject(response.getBody()); assertEquals("Could not find Backend Variant in table memoryVariantOptions with id '3'", jsonObject.getString("error")); - } } \ No newline at end of file