mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Checking record security locks that are more than 1 join away.
This commit is contained in:
@ -47,6 +47,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.Aggregate;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.GroupBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByGroupBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.ImplicitQueryJoinForSecurityLock;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
@ -218,7 +219,7 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
String baseTableName = Objects.requireNonNullElse(joinsContext.resolveTableNameOrAliasToTableName(queryJoin.getBaseTableOrAlias()), tableName);
|
||||
QJoinMetaData joinMetaData = Objects.requireNonNullElseGet(queryJoin.getJoinMetaData(), () ->
|
||||
{
|
||||
QJoinMetaData found = findJoinMetaData(instance, joinsContext, baseTableName, queryJoin.getJoinTable());
|
||||
QJoinMetaData found = joinsContext.findJoinMetaData(instance, baseTableName, queryJoin.getJoinTable());
|
||||
if(found == null)
|
||||
{
|
||||
throw (new RuntimeException("Could not find a join between tables [" + baseTableName + "][" + queryJoin.getJoinTable() + "]"));
|
||||
@ -263,69 +264,6 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private QJoinMetaData findJoinMetaData(QInstance instance, JoinsContext joinsContext, String baseTableName, String joinTableName)
|
||||
{
|
||||
List<QJoinMetaData> matches = new ArrayList<>();
|
||||
if(baseTableName != null)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// if query specified a left-table, look for a join between left & right //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
for(QJoinMetaData join : instance.getJoins().values())
|
||||
{
|
||||
if(join.getLeftTable().equals(baseTableName) && join.getRightTable().equals(joinTableName))
|
||||
{
|
||||
matches.add(join);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// look in both directions! //
|
||||
//////////////////////////////
|
||||
if(join.getRightTable().equals(baseTableName) && join.getLeftTable().equals(joinTableName))
|
||||
{
|
||||
matches.add(join.flip());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// if query didn't specify a left-table, then look for any join to the right table //
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
for(QJoinMetaData join : instance.getJoins().values())
|
||||
{
|
||||
if(join.getRightTable().equals(joinTableName) && joinsContext.hasTable(join.getLeftTable()))
|
||||
{
|
||||
matches.add(join);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// look in both directions! //
|
||||
//////////////////////////////
|
||||
if(join.getLeftTable().equals(joinTableName) && joinsContext.hasTable(join.getRightTable()))
|
||||
{
|
||||
matches.add(join.flip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(matches.size() == 1)
|
||||
{
|
||||
return (matches.get(0));
|
||||
}
|
||||
else if(matches.size() > 1)
|
||||
{
|
||||
throw (new RuntimeException("More than 1 join was found between [" + baseTableName + "] and [" + joinTableName + "]. Specify which one in your QueryJoin."));
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** method that sub-classes should call to make a full WHERE clause, including
|
||||
** security clauses.
|
||||
@ -403,6 +341,16 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
|
||||
for(QueryJoin queryJoin : CollectionUtils.nonNullList(joinsContext.getQueryJoins()))
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// for user-added joins, we want to add their security-locks to the query //
|
||||
// but if a join was implicitly added because it's needed to find a security lock on table being queried, //
|
||||
// don't add additional layers of locks for each join table. that's the idea here at least. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(queryJoin instanceof ImplicitQueryJoinForSecurityLock)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QTableMetaData joinTable = instance.getTable(queryJoin.getJoinTable());
|
||||
for(RecordSecurityLock recordSecurityLock : CollectionUtils.nonNullList(joinTable.getRecordSecurityLocks()))
|
||||
{
|
||||
@ -436,43 +384,10 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
}
|
||||
}
|
||||
|
||||
String fieldName = tableNameOrAlias + "." + recordSecurityLock.getFieldName();
|
||||
String fieldNameWithoutTablePrefix = recordSecurityLock.getFieldName().replaceFirst(".*\\.", "");
|
||||
String fieldNameTablePrefix = recordSecurityLock.getFieldName().replaceFirst("\\..*", "");
|
||||
String fieldName = tableNameOrAlias + "." + recordSecurityLock.getFieldName();
|
||||
if(CollectionUtils.nullSafeHasContents(recordSecurityLock.getJoinNameChain()))
|
||||
{
|
||||
for(String joinName : recordSecurityLock.getJoinNameChain())
|
||||
{
|
||||
QJoinMetaData joinMetaData = instance.getJoin(joinName);
|
||||
|
||||
/*
|
||||
for(QueryJoin queryJoin : joinsContext.getQueryJoins())
|
||||
{
|
||||
if(queryJoin.getJoinMetaData().getName().equals(joinName))
|
||||
{
|
||||
joinMetaData = queryJoin.getJoinMetaData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if(joinMetaData == null)
|
||||
{
|
||||
throw (new RuntimeException("Could not find joinMetaData for recordSecurityLock with joinChain member [" + joinName + "]"));
|
||||
}
|
||||
|
||||
if(fieldNameTablePrefix.equals(joinMetaData.getLeftTable()))
|
||||
{
|
||||
table = instance.getTable(joinMetaData.getLeftTable());
|
||||
}
|
||||
else
|
||||
{
|
||||
table = instance.getTable(joinMetaData.getRightTable());
|
||||
}
|
||||
|
||||
tableNameOrAlias = table.getName();
|
||||
fieldName = tableNameOrAlias + "." + fieldNameWithoutTablePrefix;
|
||||
}
|
||||
fieldName = recordSecurityLock.getFieldName();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -481,7 +396,19 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
QQueryFilter lockFilter = new QQueryFilter();
|
||||
List<QFilterCriteria> lockCriteria = new ArrayList<>();
|
||||
lockFilter.setCriteria(lockCriteria);
|
||||
List<Serializable> securityKeyValues = session.getSecurityKeyValues(recordSecurityLock.getSecurityKeyType(), table.getField(fieldNameWithoutTablePrefix).getType());
|
||||
|
||||
QFieldType type = QFieldType.INTEGER;
|
||||
try
|
||||
{
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(fieldName);
|
||||
type = fieldAndTableNameOrAlias.field().getType();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.debug("Error getting field type... Trying Integer", e);
|
||||
}
|
||||
|
||||
List<Serializable> securityKeyValues = session.getSecurityKeyValues(recordSecurityLock.getSecurityKeyType(), type);
|
||||
if(CollectionUtils.nullSafeIsEmpty(securityKeyValues))
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -82,7 +82,7 @@ public class RDBMSInsertAction extends AbstractRDBMSAction implements InsertInte
|
||||
.toList();
|
||||
|
||||
String columns = insertableFields.stream()
|
||||
.map(this::getColumnName)
|
||||
.map(f -> "`" + getColumnName(f) + "`")
|
||||
.collect(Collectors.joining(", "));
|
||||
String questionMarks = insertableFields.stream()
|
||||
.map(x -> "?")
|
||||
|
@ -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