mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-19 05:30:43 +00:00
Checking record security locks that are more than 1 join away.
This commit is contained in:
@ -25,6 +25,11 @@ package com.kingsrook.qqq.backend.module.rdbms;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.authentication.QAuthenticationMetaData;
|
||||
@ -38,6 +43,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleVal
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSActionTest;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager;
|
||||
@ -61,6 +67,7 @@ public class TestUtils
|
||||
public static final String TABLE_NAME_ORDER = "order";
|
||||
public static final String TABLE_NAME_ITEM = "item";
|
||||
public static final String TABLE_NAME_ORDER_LINE = "orderLine";
|
||||
public static final String TABLE_NAME_LINE_ITEM_EXTRINSIC = "orderLineExtrinsic";
|
||||
public static final String TABLE_NAME_WAREHOUSE = "warehouse";
|
||||
public static final String TABLE_NAME_WAREHOUSE_STORE_INT = "warehouseStoreInt";
|
||||
|
||||
@ -231,6 +238,7 @@ public class TestUtils
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_ORDER, "order")
|
||||
.withRecordSecurityLock(new RecordSecurityLock().withSecurityKeyType(TABLE_NAME_STORE).withFieldName("storeId"))
|
||||
.withAssociation(new Association().withName("orderLine").withAssociatedTableName(TABLE_NAME_ORDER_LINE).withJoinName("orderJoinOrderLine"))
|
||||
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id").withPossibleValueSourceName(TABLE_NAME_STORE))
|
||||
.withField(new QFieldMetaData("billToPersonId", QFieldType.INTEGER).withBackendName("bill_to_person_id").withPossibleValueSourceName(TABLE_NAME_PERSON))
|
||||
.withField(new QFieldMetaData("shipToPersonId", QFieldType.INTEGER).withBackendName("ship_to_person_id").withPossibleValueSourceName(TABLE_NAME_PERSON))
|
||||
@ -243,13 +251,28 @@ public class TestUtils
|
||||
);
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_ORDER_LINE, "order_line")
|
||||
.withRecordSecurityLock(new RecordSecurityLock().withSecurityKeyType(TABLE_NAME_STORE).withFieldName("storeId"))
|
||||
.withRecordSecurityLock(new RecordSecurityLock()
|
||||
.withSecurityKeyType(TABLE_NAME_STORE)
|
||||
.withFieldName("order.storeId")
|
||||
.withJoinNameChain(List.of("orderJoinOrderLine")))
|
||||
.withAssociation(new Association().withName("extrinsics").withAssociatedTableName(TABLE_NAME_LINE_ITEM_EXTRINSIC).withJoinName("orderLineJoinLineItemExtrinsic"))
|
||||
.withField(new QFieldMetaData("orderId", QFieldType.INTEGER).withBackendName("order_id"))
|
||||
.withField(new QFieldMetaData("sku", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id").withPossibleValueSourceName(TABLE_NAME_STORE))
|
||||
.withField(new QFieldMetaData("quantity", QFieldType.INTEGER))
|
||||
);
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_LINE_ITEM_EXTRINSIC, "line_item_extrinsic")
|
||||
.withRecordSecurityLock(new RecordSecurityLock()
|
||||
.withSecurityKeyType(TABLE_NAME_STORE)
|
||||
.withFieldName("order.storeId")
|
||||
.withJoinNameChain(List.of("orderJoinOrderLine", "orderLineJoinLineItemExtrinsic")))
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("orderLineId", QFieldType.INTEGER).withBackendName("order_line_id"))
|
||||
.withField(new QFieldMetaData("key", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("value", QFieldType.STRING))
|
||||
);
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_WAREHOUSE_STORE_INT, "warehouse_store_int")
|
||||
.withField(new QFieldMetaData("warehouseId", QFieldType.INTEGER).withBackendName("warehouse_id"))
|
||||
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id"))
|
||||
@ -321,6 +344,14 @@ public class TestUtils
|
||||
.withJoinOn(new JoinOn("storeId", "storeId"))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("orderLineJoinLineItemExtrinsic")
|
||||
.withLeftTable(TABLE_NAME_ORDER_LINE)
|
||||
.withRightTable(TABLE_NAME_LINE_ITEM_EXTRINSIC)
|
||||
.withType(JoinType.ONE_TO_MANY)
|
||||
.withJoinOn(new JoinOn("id", "orderLineId"))
|
||||
);
|
||||
|
||||
qInstance.addPossibleValueSource(new QPossibleValueSource()
|
||||
.withName("store")
|
||||
.withType(QPossibleValueSourceType.TABLE)
|
||||
@ -349,4 +380,16 @@ public class TestUtils
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static List<QRecord> queryTable(String tableName) throws QException
|
||||
{
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(tableName);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
return (queryOutput.getRecords());
|
||||
}
|
||||
}
|
||||
|
@ -329,8 +329,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1));
|
||||
aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
aggregateResult = aggregateOutput.getResults().get(0);
|
||||
// note - this would be 33, except for that one order line that has a contradictory store id...
|
||||
Assertions.assertEquals(32, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
Assertions.assertEquals(33, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,6 +24,9 @@ package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
||||
@ -34,6 +37,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -140,6 +144,50 @@ public class RDBMSInsertActionTest extends RDBMSActionTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInsertAssociations() throws QException
|
||||
{
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1);
|
||||
|
||||
int originalNoOfOrderLineExtrinsics = TestUtils.queryTable(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC).size();
|
||||
int originalNoOfOrderLines = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER_LINE).size();
|
||||
int originalNoOfOrders = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).size();
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
insertInput.setRecords(List.of(
|
||||
new QRecord().withValue("storeId", 1).withValue("billToPersonId", 100).withValue("shipToPersonId", 200)
|
||||
|
||||
.withAssociatedRecord("orderLine", new QRecord().withValue("sku", "BASIC1").withValue("quantity", 1)
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "LINE-EXT-1.1").withValue("value", "LINE-VAL-1")))
|
||||
|
||||
.withAssociatedRecord("orderLine", new QRecord().withValue("sku", "BASIC2").withValue("quantity", 2)
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "LINE-EXT-2.1").withValue("value", "LINE-VAL-2"))
|
||||
.withAssociatedRecord("extrinsics", new QRecord().withValue("key", "LINE-EXT-2.2").withValue("value", "LINE-VAL-3")))
|
||||
));
|
||||
new InsertAction().execute(insertInput);
|
||||
|
||||
List<QRecord> orders = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER);
|
||||
assertEquals(originalNoOfOrders + 1, orders.size());
|
||||
assertTrue(orders.stream().anyMatch(r -> Objects.equals(r.getValue("billToPersonId"), 100) && Objects.equals(r.getValue("shipToPersonId"), 200)));
|
||||
|
||||
List<QRecord> orderLines = TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER_LINE);
|
||||
assertEquals(originalNoOfOrderLines + 2, orderLines.size());
|
||||
assertTrue(orderLines.stream().anyMatch(r -> Objects.equals(r.getValue("sku"), "BASIC1") && Objects.equals(r.getValue("quantity"), 1)));
|
||||
assertTrue(orderLines.stream().anyMatch(r -> Objects.equals(r.getValue("sku"), "BASIC2") && Objects.equals(r.getValue("quantity"), 2)));
|
||||
|
||||
List<QRecord> lineItemExtrinsics = TestUtils.queryTable(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
|
||||
assertEquals(originalNoOfOrderLineExtrinsics + 3, lineItemExtrinsics.size());
|
||||
assertTrue(lineItemExtrinsics.stream().anyMatch(r -> Objects.equals(r.getValue("key"), "LINE-EXT-1.1") && Objects.equals(r.getValue("value"), "LINE-VAL-1")));
|
||||
assertTrue(lineItemExtrinsics.stream().anyMatch(r -> Objects.equals(r.getValue("key"), "LINE-EXT-2.1") && Objects.equals(r.getValue("value"), "LINE-VAL-2")));
|
||||
assertTrue(lineItemExtrinsics.stream().anyMatch(r -> Objects.equals(r.getValue("key"), "LINE-EXT-2.2") && Objects.equals(r.getValue("value"), "LINE-VAL-3")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void assertAnInsertedPersonRecord(String firstName, String lastName, Integer id) throws Exception
|
||||
{
|
||||
runTestSql("SELECT * FROM person WHERE last_name = '" + lastName + "'", (rs -> {
|
||||
|
@ -30,6 +30,7 @@ import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||
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.QInstance;
|
||||
@ -162,6 +163,7 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
|
||||
.withDataSource(new QReportDataSource()
|
||||
.withSourceTable(TestUtils.TABLE_NAME_ORDER_LINE)
|
||||
.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ITEM).withAlias("i").withSelect(true))
|
||||
.withQueryFilter(new QQueryFilter().withOrderBy(new QFilterOrderBy("id")))
|
||||
)
|
||||
.withView(new QReportView()
|
||||
.withType(ReportType.TABLE)
|
||||
@ -179,13 +181,13 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
|
||||
assertEquals("""
|
||||
"Line Item Id","Item SKU","Item Store Id","Item Store Name"
|
||||
"1","QM-1","1","Q-Mart"
|
||||
"5","QM-1","1","Q-Mart"
|
||||
"2","QM-2","1","Q-Mart"
|
||||
"3","QM-3","1","Q-Mart"
|
||||
"4","QRU-1","2","QQQ 'R' Us"
|
||||
"5","QM-1","1","Q-Mart"
|
||||
"6","QRU-1","2","QQQ 'R' Us"
|
||||
"8","QRU-1","2","QQQ 'R' Us"
|
||||
"7","QRU-2","2","QQQ 'R' Us"
|
||||
"8","QRU-1","2","QQQ 'R' Us"
|
||||
"9","QD-1","3","QDepot"
|
||||
"10","QD-1","3","QDepot"
|
||||
"11","QD-1","3","QDepot"
|
||||
|
@ -79,6 +79,7 @@ INSERT INTO carrier (id, name, company_code, service_level) VALUES (9, 'USPS Sup
|
||||
INSERT INTO carrier (id, name, company_code, service_level) VALUES (10, 'DHL International', 'DHL', 'I');
|
||||
INSERT INTO carrier (id, name, company_code, service_level) VALUES (11, 'GSO', 'GSO', 'G');
|
||||
|
||||
DROP TABLE IF EXISTS line_item_extrinsic;
|
||||
DROP TABLE IF EXISTS order_line;
|
||||
DROP TABLE IF EXISTS item;
|
||||
DROP TABLE IF EXISTS `order`;
|
||||
@ -138,7 +139,7 @@ CREATE TABLE order_line
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
order_id INT REFERENCES `order`,
|
||||
sku VARCHAR(80),
|
||||
store_id INT REFERENCES store, -- todo - as a challenge, if this field wasn't here, so we had to join through order...
|
||||
store_id INT REFERENCES store,
|
||||
quantity INT
|
||||
);
|
||||
|
||||
@ -177,3 +178,12 @@ CREATE TABLE warehouse_store_int
|
||||
INSERT INTO warehouse_store_int (warehouse_id, store_id) VALUES (1, 1);
|
||||
INSERT INTO warehouse_store_int (warehouse_id, store_id) VALUES (1, 2);
|
||||
INSERT INTO warehouse_store_int (warehouse_id, store_id) VALUES (1, 3);
|
||||
|
||||
CREATE TABLE line_item_extrinsic
|
||||
(
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
order_line_id INT REFERENCES order_line,
|
||||
`key` VARCHAR(80),
|
||||
`value` VARCHAR(80)
|
||||
);
|
||||
|
||||
|
Reference in New Issue
Block a user