Fix parsing of joins in query posts for api middleware v1

This commit is contained in:
2025-07-17 15:00:07 -05:00
parent 78b893616b
commit b2861b1567
3 changed files with 70 additions and 15 deletions

View File

@ -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<QueryJoin> 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<QueryJoin> 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);
}

View File

@ -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")));
}

View File

@ -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<String> 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"));
}
}