mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Much implementation of joins for RDBMS
This commit is contained in:
@ -27,7 +27,9 @@ import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
||||
@ -36,12 +38,17 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.Aggregate;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||
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.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
@ -168,9 +175,88 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
protected String makeWhereClause(QTableMetaData table, QQueryFilter filter, List<Serializable> params) throws IllegalArgumentException
|
||||
protected String makeFromClause(QInstance instance, String tableName, JoinsContext joinsContext) throws QException
|
||||
{
|
||||
String clause = makeWhereClause(table, filter.getCriteria(), filter.getBooleanOperator(), params);
|
||||
StringBuilder rs = new StringBuilder(escapeIdentifier(getTableName(instance.getTable(tableName))) + " AS " + escapeIdentifier(tableName));
|
||||
|
||||
for(QueryJoin queryJoin : joinsContext.getQueryJoins())
|
||||
{
|
||||
QTableMetaData joinTable = instance.getTable(queryJoin.getRightTable());
|
||||
String tableNameOrAlias = queryJoin.getAliasOrRightTable();
|
||||
|
||||
rs.append(" ").append(queryJoin.getType()).append(" JOIN ")
|
||||
.append(escapeIdentifier(getTableName(joinTable)))
|
||||
.append(" AS ").append(escapeIdentifier(tableNameOrAlias));
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// find the join in the instance, to see the 'on' clause //
|
||||
////////////////////////////////////////////////////////////
|
||||
List<String> joinClauseList = new ArrayList<>();
|
||||
String leftTableName = joinsContext.resolveTableNameOrAliasToTableName(queryJoin.getLeftTableOrAlias());
|
||||
QJoinMetaData joinMetaData = Objects.requireNonNullElseGet(queryJoin.getJoinMetaData(), () -> findJoinMetaData(instance, leftTableName, queryJoin.getRightTable()));
|
||||
for(JoinOn joinOn : joinMetaData.getJoinOns())
|
||||
{
|
||||
QTableMetaData leftTable = instance.getTable(joinMetaData.getLeftTable());
|
||||
QTableMetaData rightTable = instance.getTable(joinMetaData.getRightTable());
|
||||
|
||||
String leftTableOrAlias = queryJoin.getLeftTableOrAlias();
|
||||
String aliasOrRightTable = queryJoin.getAliasOrRightTable();
|
||||
|
||||
joinClauseList.add(escapeIdentifier(leftTableOrAlias)
|
||||
+ "." + escapeIdentifier(getColumnName(leftTable.getField(joinOn.getLeftField())))
|
||||
+ " = " + escapeIdentifier(aliasOrRightTable)
|
||||
+ "." + escapeIdentifier(getColumnName((rightTable.getField(joinOn.getRightField())))));
|
||||
}
|
||||
rs.append(" ON ").append(StringUtils.join(" AND ", joinClauseList));
|
||||
}
|
||||
|
||||
return (rs.toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private QJoinMetaData findJoinMetaData(QInstance instance, String leftTable, String rightTable)
|
||||
{
|
||||
List<QJoinMetaData> matches = new ArrayList<>();
|
||||
for(QJoinMetaData join : instance.getJoins().values())
|
||||
{
|
||||
if(join.getLeftTable().equals(leftTable) && join.getRightTable().equals(rightTable))
|
||||
{
|
||||
matches.add(join);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// look in both directions! //
|
||||
//////////////////////////////
|
||||
if(join.getRightTable().equals(leftTable) && join.getLeftTable().equals(rightTable))
|
||||
{
|
||||
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 [" + leftTable + "] and [" + rightTable + "]. Specify which one in your QueryJoin."));
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
protected String makeWhereClause(QInstance instance, QTableMetaData table, JoinsContext joinsContext, QQueryFilter filter, List<Serializable> params) throws IllegalArgumentException, QException
|
||||
{
|
||||
String clause = makeSimpleWhereClause(instance, table, joinsContext, filter.getCriteria(), filter.getBooleanOperator(), params);
|
||||
if(!CollectionUtils.nullSafeHasContents(filter.getSubFilters()))
|
||||
{
|
||||
///////////////////////////////////////////////////////////////
|
||||
@ -189,7 +275,7 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
}
|
||||
for(QQueryFilter subFilter : filter.getSubFilters())
|
||||
{
|
||||
String subClause = makeWhereClause(table, subFilter, params);
|
||||
String subClause = makeWhereClause(instance, table, joinsContext, subFilter, params);
|
||||
if(StringUtils.hasContent(subClause))
|
||||
{
|
||||
clauses.add("(" + subClause + ")");
|
||||
@ -203,14 +289,16 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String makeWhereClause(QTableMetaData table, List<QFilterCriteria> criteria, QQueryFilter.BooleanOperator booleanOperator, List<Serializable> params) throws IllegalArgumentException
|
||||
private String makeSimpleWhereClause(QInstance instance, QTableMetaData table, JoinsContext joinsContext, List<QFilterCriteria> criteria, QQueryFilter.BooleanOperator booleanOperator, List<Serializable> params) throws IllegalArgumentException
|
||||
{
|
||||
List<String> clauses = new ArrayList<>();
|
||||
for(QFilterCriteria criterion : criteria)
|
||||
{
|
||||
QFieldMetaData field = table.getField(criterion.getFieldName());
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(criterion.getFieldName());
|
||||
|
||||
List<Serializable> values = criterion.getValues() == null ? new ArrayList<>() : new ArrayList<>(criterion.getValues());
|
||||
String column = getColumnName(field);
|
||||
QFieldMetaData field = fieldAndTableNameOrAlias.field();
|
||||
String column = escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(field));
|
||||
String clause = column;
|
||||
Integer expectedNoOfParams = null;
|
||||
switch(criterion.getOperator())
|
||||
@ -360,15 +448,29 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
throw new IllegalArgumentException("Unexpected operator: " + criterion.getOperator());
|
||||
}
|
||||
}
|
||||
clauses.add("(" + clause + ")");
|
||||
|
||||
if(expectedNoOfParams != null)
|
||||
{
|
||||
if(!expectedNoOfParams.equals(values.size()))
|
||||
if(expectedNoOfParams.equals(1) && StringUtils.hasContent(criterion.getOtherFieldName()))
|
||||
{
|
||||
JoinsContext.FieldAndTableNameOrAlias otherFieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(criterion.getOtherFieldName());
|
||||
|
||||
String otherColumn = escapeIdentifier(otherFieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(otherFieldAndTableNameOrAlias.field()));
|
||||
clause = clause.replace("?", otherColumn);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// make sure we don't add any values in this case, just in case... //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
values = Collections.emptyList();
|
||||
}
|
||||
else if(!expectedNoOfParams.equals(values.size()))
|
||||
{
|
||||
throw new IllegalArgumentException("Incorrect number of values given for criteria [" + field.getName() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
clauses.add("(" + clause + ")");
|
||||
|
||||
params.addAll(values);
|
||||
}
|
||||
|
||||
@ -470,7 +572,7 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
protected String makeOrderByClause(QTableMetaData table, List<QFilterOrderBy> orderBys)
|
||||
protected String makeOrderByClause(QTableMetaData table, List<QFilterOrderBy> orderBys, JoinsContext joinsContext)
|
||||
{
|
||||
List<String> clauses = new ArrayList<>();
|
||||
|
||||
@ -485,9 +587,11 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
||||
}
|
||||
else
|
||||
{
|
||||
QFieldMetaData field = table.getField(orderBy.getFieldName());
|
||||
String column = escapeIdentifier(getColumnName(field));
|
||||
clauses.add(column + " " + ascOrDesc);
|
||||
JoinsContext.FieldAndTableNameOrAlias otherFieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(orderBy.getFieldName());
|
||||
|
||||
QFieldMetaData field = otherFieldAndTableNameOrAlias.field();
|
||||
String column = getColumnName(field);
|
||||
clauses.add(escapeIdentifier(otherFieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(column) + " " + ascOrDesc);
|
||||
}
|
||||
}
|
||||
return (String.join(", ", clauses));
|
||||
|
@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateIn
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateResult;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
@ -61,29 +62,30 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
||||
{
|
||||
try
|
||||
{
|
||||
QTableMetaData table = aggregateInput.getTable();
|
||||
String tableName = getTableName(table);
|
||||
QTableMetaData table = aggregateInput.getTable();
|
||||
|
||||
List<String> selectClauses = buildSelectClauses(aggregateInput);
|
||||
JoinsContext joinsContext = new JoinsContext(aggregateInput.getInstance(), table.getName(), aggregateInput.getQueryJoins());
|
||||
String fromClause = makeFromClause(aggregateInput.getInstance(), table.getName(), joinsContext);
|
||||
List<String> selectClauses = buildSelectClauses(aggregateInput, joinsContext);
|
||||
|
||||
String sql = "SELECT " + StringUtils.join(", ", selectClauses)
|
||||
+ " FROM " + escapeIdentifier(tableName);
|
||||
+ " FROM " + fromClause;
|
||||
|
||||
QQueryFilter filter = aggregateInput.getFilter();
|
||||
List<Serializable> params = new ArrayList<>();
|
||||
if(filter != null && filter.hasAnyCriteria())
|
||||
{
|
||||
sql += " WHERE " + makeWhereClause(table, filter, params);
|
||||
sql += " WHERE " + makeWhereClause(aggregateInput.getInstance(), table, joinsContext, filter, params);
|
||||
}
|
||||
|
||||
if(CollectionUtils.nullSafeHasContents(aggregateInput.getGroupByFieldNames()))
|
||||
{
|
||||
sql += " GROUP BY " + makeGroupByClause(aggregateInput);
|
||||
sql += " GROUP BY " + makeGroupByClause(aggregateInput, joinsContext);
|
||||
}
|
||||
|
||||
if(filter != null && CollectionUtils.nullSafeHasContents(filter.getOrderBys()))
|
||||
{
|
||||
sql += " ORDER BY " + makeOrderByClause(table, filter.getOrderBys());
|
||||
sql += " ORDER BY " + makeOrderByClause(table, filter.getOrderBys(), joinsContext);
|
||||
}
|
||||
|
||||
// todo sql customization - can edit sql and/or param list
|
||||
@ -105,13 +107,16 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
||||
int selectionIndex = 1;
|
||||
for(String groupByFieldName : CollectionUtils.nonNullList(aggregateInput.getGroupByFieldNames()))
|
||||
{
|
||||
Serializable value = getFieldValueFromResultSet(table.getField(groupByFieldName), resultSet, selectionIndex++);
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupByFieldName);
|
||||
Serializable value = getFieldValueFromResultSet(fieldAndTableNameOrAlias.field(), resultSet, selectionIndex++);
|
||||
result.withGroupByValue(groupByFieldName, value);
|
||||
}
|
||||
|
||||
for(Aggregate aggregate : aggregateInput.getAggregates())
|
||||
{
|
||||
QFieldMetaData field = table.getField(aggregate.getFieldName());
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(aggregate.getFieldName());
|
||||
QFieldMetaData field = fieldAndTableNameOrAlias.field();
|
||||
|
||||
if(field.getType().equals(QFieldType.INTEGER) && aggregate.getOperator().equals(AggregateOperator.AVG))
|
||||
{
|
||||
field = new QFieldMetaData().withType(QFieldType.DECIMAL);
|
||||
@ -139,19 +144,20 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private List<String> buildSelectClauses(AggregateInput aggregateInput)
|
||||
private List<String> buildSelectClauses(AggregateInput aggregateInput, JoinsContext joinsContext)
|
||||
{
|
||||
QTableMetaData table = aggregateInput.getTable();
|
||||
List<String> rs = new ArrayList<>();
|
||||
List<String> rs = new ArrayList<>();
|
||||
|
||||
for(String groupByFieldName : CollectionUtils.nonNullList(aggregateInput.getGroupByFieldNames()))
|
||||
{
|
||||
rs.add(escapeIdentifier(getColumnName(table.getField(groupByFieldName))));
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupByFieldName);
|
||||
rs.add(escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(fieldAndTableNameOrAlias.field())));
|
||||
}
|
||||
|
||||
for(Aggregate aggregate : aggregateInput.getAggregates())
|
||||
{
|
||||
rs.add(aggregate.getOperator() + "(" + escapeIdentifier(getColumnName(table.getField(aggregate.getFieldName()))) + ")");
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(aggregate.getFieldName());
|
||||
rs.add(aggregate.getOperator() + "(" + escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(fieldAndTableNameOrAlias.field())) + ")");
|
||||
}
|
||||
return (rs);
|
||||
}
|
||||
@ -161,13 +167,13 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String makeGroupByClause(AggregateInput aggregateInput)
|
||||
private String makeGroupByClause(AggregateInput aggregateInput, JoinsContext joinsContext)
|
||||
{
|
||||
QTableMetaData table = aggregateInput.getTable();
|
||||
List<String> columns = new ArrayList<>();
|
||||
List<String> columns = new ArrayList<>();
|
||||
for(String groupByFieldName : aggregateInput.getGroupByFieldNames())
|
||||
{
|
||||
columns.add(escapeIdentifier(getColumnName(table.getField(groupByFieldName))));
|
||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupByFieldName);
|
||||
columns.add(escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(fieldAndTableNameOrAlias.field())));
|
||||
}
|
||||
|
||||
return (StringUtils.join(",", columns));
|
||||
|
@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.CountInterface;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager;
|
||||
@ -54,16 +55,18 @@ public class RDBMSCountAction extends AbstractRDBMSAction implements CountInterf
|
||||
{
|
||||
try
|
||||
{
|
||||
QTableMetaData table = countInput.getTable();
|
||||
String tableName = getTableName(table);
|
||||
QTableMetaData table = countInput.getTable();
|
||||
|
||||
String sql = "SELECT count(*) as record_count FROM " + escapeIdentifier(tableName);
|
||||
JoinsContext joinsContext = new JoinsContext(countInput.getInstance(), countInput.getTableName(), countInput.getQueryJoins());
|
||||
|
||||
String sql = "SELECT count(*) as record_count FROM "
|
||||
+ makeFromClause(countInput.getInstance(), table.getName(), joinsContext);
|
||||
|
||||
QQueryFilter filter = countInput.getFilter();
|
||||
List<Serializable> params = new ArrayList<>();
|
||||
if(filter != null && filter.hasAnyCriteria())
|
||||
{
|
||||
sql += " WHERE " + makeWhereClause(table, filter, params);
|
||||
sql += " WHERE " + makeWhereClause(countInput.getInstance(), table, joinsContext, filter, params);
|
||||
}
|
||||
|
||||
// todo sql customization - can edit sql and/or param list
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
||||
@ -32,6 +33,7 @@ import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||
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.metadata.tables.QTableMetaData;
|
||||
@ -258,8 +260,9 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte
|
||||
List<Serializable> params = new ArrayList<>();
|
||||
QTableMetaData table = deleteInput.getTable();
|
||||
|
||||
String tableName = getTableName(table);
|
||||
String whereClause = makeWhereClause(table, filter, params);
|
||||
String tableName = getTableName(table);
|
||||
JoinsContext joinsContext = new JoinsContext(deleteInput.getInstance(), table.getName(), Collections.emptyList());
|
||||
String whereClause = makeWhereClause(deleteInput.getInstance(), table, joinsContext, filter, params);
|
||||
|
||||
// todo sql customization - can edit sql and/or param list?
|
||||
String sql = "DELETE FROM "
|
||||
|
@ -34,10 +34,13 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.actions.interfaces.QueryInterface;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||
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.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
@ -64,35 +67,34 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
|
||||
try
|
||||
{
|
||||
QTableMetaData table = queryInput.getTable();
|
||||
String tableName = getTableName(table);
|
||||
String tableName = queryInput.getTableName();
|
||||
|
||||
List<QFieldMetaData> fieldList = new ArrayList<>(table.getFields().values());
|
||||
String columns = fieldList.stream()
|
||||
.map(this::getColumnName)
|
||||
.collect(Collectors.joining(", "));
|
||||
StringBuilder sql = new StringBuilder("SELECT ").append(makeSelectClause(queryInput.getInstance(), tableName, queryInput.getQueryJoins()));
|
||||
|
||||
String sql = "SELECT " + columns + " FROM " + escapeIdentifier(tableName);
|
||||
JoinsContext joinsContext = new JoinsContext(queryInput.getInstance(), tableName, queryInput.getQueryJoins());
|
||||
sql.append(" FROM ").append(makeFromClause(queryInput.getInstance(), tableName, joinsContext));
|
||||
|
||||
QQueryFilter filter = queryInput.getFilter();
|
||||
List<Serializable> params = new ArrayList<>();
|
||||
|
||||
if(filter != null && filter.hasAnyCriteria())
|
||||
{
|
||||
sql += " WHERE " + makeWhereClause(table, filter, params);
|
||||
sql.append(" WHERE ").append(makeWhereClause(queryInput.getInstance(), table, joinsContext, filter, params));
|
||||
}
|
||||
|
||||
if(filter != null && CollectionUtils.nullSafeHasContents(filter.getOrderBys()))
|
||||
{
|
||||
sql += " ORDER BY " + makeOrderByClause(table, filter.getOrderBys());
|
||||
sql.append(" ORDER BY ").append(makeOrderByClause(table, filter.getOrderBys(), joinsContext));
|
||||
}
|
||||
|
||||
if(queryInput.getLimit() != null)
|
||||
{
|
||||
sql += " LIMIT " + queryInput.getLimit();
|
||||
sql.append(" LIMIT ").append(queryInput.getLimit());
|
||||
|
||||
if(queryInput.getSkip() != null)
|
||||
{
|
||||
// todo - other sql grammars?
|
||||
sql += " OFFSET " + queryInput.getSkip();
|
||||
sql.append(" OFFSET ").append(queryInput.getSkip());
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,10 +113,31 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
|
||||
needToCloseConnection = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// build the list of fields that will be processed in the result-set loop //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
List<QFieldMetaData> fieldList = new ArrayList<>(table.getFields().values());
|
||||
for(QueryJoin queryJoin : CollectionUtils.nonNullList(queryInput.getQueryJoins()))
|
||||
{
|
||||
if(queryJoin.getSelect())
|
||||
{
|
||||
QTableMetaData joinTable = queryInput.getInstance().getTable(queryJoin.getRightTable());
|
||||
String tableNameOrAlias = queryJoin.getAliasOrRightTable();
|
||||
for(QFieldMetaData joinField : joinTable.getFields().values())
|
||||
{
|
||||
fieldList.add(joinField.clone().withName(tableNameOrAlias + "." + joinField.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
QueryOutput queryOutput = new QueryOutput(queryInput);
|
||||
PreparedStatement statement = createStatement(connection, sql, queryInput);
|
||||
//////////////////////////////////////////////
|
||||
// execute the query - iterate over results //
|
||||
//////////////////////////////////////////////
|
||||
QueryOutput queryOutput = new QueryOutput(queryInput);
|
||||
System.out.println(sql);
|
||||
PreparedStatement statement = createStatement(connection, sql.toString(), queryInput);
|
||||
QueryManager.executeStatement(statement, ((ResultSet resultSet) ->
|
||||
{
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
@ -162,6 +185,42 @@ public class RDBMSQueryAction extends AbstractRDBMSAction implements QueryInterf
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String makeSelectClause(QInstance instance, String tableName, List<QueryJoin> queryJoins) throws QException
|
||||
{
|
||||
QTableMetaData table = instance.getTable(tableName);
|
||||
List<QFieldMetaData> fieldList = new ArrayList<>(table.getFields().values());
|
||||
String columns = fieldList.stream()
|
||||
.map(field -> escapeIdentifier(tableName) + "." + escapeIdentifier(getColumnName(field)))
|
||||
.collect(Collectors.joining(", "));
|
||||
StringBuilder rs = new StringBuilder(columns);
|
||||
|
||||
for(QueryJoin queryJoin : CollectionUtils.nonNullList(queryJoins))
|
||||
{
|
||||
if(queryJoin.getSelect())
|
||||
{
|
||||
QTableMetaData joinTable = instance.getTable(queryJoin.getRightTable());
|
||||
String tableNameOrAlias = queryJoin.getAliasOrRightTable();
|
||||
if(joinTable == null)
|
||||
{
|
||||
throw new QException("Requested join table [" + queryJoin.getRightTable() + "] is not a defined table.");
|
||||
}
|
||||
|
||||
List<QFieldMetaData> joinFieldList = new ArrayList<>(joinTable.getFields().values());
|
||||
String joinColumns = joinFieldList.stream()
|
||||
.map(field -> escapeIdentifier(tableNameOrAlias) + "." + escapeIdentifier(getColumnName(field)))
|
||||
.collect(Collectors.joining(", "));
|
||||
rs.append(", ").append(joinColumns);
|
||||
}
|
||||
}
|
||||
|
||||
return (rs.toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -29,6 +29,9 @@ 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.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.authentication.metadata.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSActionTest;
|
||||
@ -45,9 +48,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
*******************************************************************************/
|
||||
public class TestUtils
|
||||
{
|
||||
|
||||
public static final String DEFAULT_BACKEND_NAME = "default";
|
||||
|
||||
public static final String TABLE_NAME_PERSON = "personTable";
|
||||
public static final String TABLE_NAME_PERSONAL_ID_CARD = "personalIdCard";
|
||||
public static final String TABLE_NAME_STORE = "store";
|
||||
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";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -81,6 +90,9 @@ public class TestUtils
|
||||
QInstance qInstance = new QInstance();
|
||||
qInstance.addBackend(defineBackend());
|
||||
qInstance.addTable(defineTablePerson());
|
||||
qInstance.addTable(defineTablePersonalIdCard());
|
||||
qInstance.addJoin(defineJoinPersonAndPersonalIdCard());
|
||||
addOmsTablesAndJoins(qInstance);
|
||||
qInstance.setAuthentication(defineAuthentication());
|
||||
return (qInstance);
|
||||
}
|
||||
@ -121,9 +133,9 @@ public class TestUtils
|
||||
public static QTableMetaData defineTablePerson()
|
||||
{
|
||||
return new QTableMetaData()
|
||||
.withName("a-person") // use this name, so it isn't the same as the actual database-table name (which must come from the backend details)
|
||||
.withName(TABLE_NAME_PERSON)
|
||||
.withLabel("Person")
|
||||
.withBackendName(defineBackend().getName())
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withBackendName("create_date"))
|
||||
@ -139,4 +151,136 @@ public class TestUtils
|
||||
.withTableName("person"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define a 1:1 table with Person.
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QTableMetaData defineTablePersonalIdCard()
|
||||
{
|
||||
return new QTableMetaData()
|
||||
.withName(TABLE_NAME_PERSONAL_ID_CARD)
|
||||
.withLabel("Personal Id Card")
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withBackendDetails(new RDBMSTableBackendDetails()
|
||||
.withTableName("personal_id_card"))
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withBackendName("create_date"))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME).withBackendName("modify_date"))
|
||||
.withField(new QFieldMetaData("personId", QFieldType.INTEGER).withBackendName("person_id"))
|
||||
.withField(new QFieldMetaData("idNumber", QFieldType.STRING).withBackendName("id_number"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QJoinMetaData defineJoinPersonAndPersonalIdCard()
|
||||
{
|
||||
return new QJoinMetaData()
|
||||
.withLeftTable(TABLE_NAME_PERSON)
|
||||
.withRightTable(TABLE_NAME_PERSONAL_ID_CARD)
|
||||
.withInferredName()
|
||||
.withType(JoinType.ONE_TO_ONE)
|
||||
.withJoinOn(new JoinOn("id", "personId"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void addOmsTablesAndJoins(QInstance qInstance)
|
||||
{
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_STORE, "store")
|
||||
.withField(new QFieldMetaData("name", QFieldType.STRING))
|
||||
);
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_ORDER, "order")
|
||||
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id"))
|
||||
.withField(new QFieldMetaData("billToPersonId", QFieldType.INTEGER).withBackendName("bill_to_person_id"))
|
||||
.withField(new QFieldMetaData("shipToPersonId", QFieldType.INTEGER).withBackendName("ship_to_person_id"))
|
||||
);
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_ITEM, "item")
|
||||
.withField(new QFieldMetaData("sku", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id"))
|
||||
);
|
||||
|
||||
qInstance.addTable(defineBaseTable(TABLE_NAME_ORDER_LINE, "order_line")
|
||||
.withField(new QFieldMetaData("orderId", QFieldType.INTEGER).withBackendName("order_id"))
|
||||
.withField(new QFieldMetaData("sku", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("storeId", QFieldType.INTEGER).withBackendName("store_id"))
|
||||
.withField(new QFieldMetaData("quantity", QFieldType.INTEGER))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("orderJoinStore")
|
||||
.withLeftTable(TABLE_NAME_ORDER)
|
||||
.withRightTable(TABLE_NAME_STORE)
|
||||
.withType(JoinType.MANY_TO_ONE)
|
||||
.withJoinOn(new JoinOn("storeId", "id"))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("orderJoinBillToPerson")
|
||||
.withLeftTable(TABLE_NAME_ORDER)
|
||||
.withRightTable(TABLE_NAME_PERSON)
|
||||
.withType(JoinType.MANY_TO_ONE)
|
||||
.withJoinOn(new JoinOn("billToPersonId", "id"))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("orderJoinShipToPerson")
|
||||
.withLeftTable(TABLE_NAME_ORDER)
|
||||
.withRightTable(TABLE_NAME_PERSON)
|
||||
.withType(JoinType.MANY_TO_ONE)
|
||||
.withJoinOn(new JoinOn("shipToPersonId", "id"))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("itemJoinStore")
|
||||
.withLeftTable(TABLE_NAME_ITEM)
|
||||
.withRightTable(TABLE_NAME_STORE)
|
||||
.withType(JoinType.MANY_TO_ONE)
|
||||
.withJoinOn(new JoinOn("storeId", "id"))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("orderJoinOrderLine")
|
||||
.withLeftTable(TABLE_NAME_ORDER)
|
||||
.withRightTable(TABLE_NAME_ORDER_LINE)
|
||||
.withType(JoinType.ONE_TO_MANY)
|
||||
.withJoinOn(new JoinOn("id", "orderId"))
|
||||
);
|
||||
|
||||
qInstance.addJoin(new QJoinMetaData()
|
||||
.withName("orderLineJoinItem")
|
||||
.withLeftTable(TABLE_NAME_ORDER_LINE)
|
||||
.withRightTable(TABLE_NAME_ITEM)
|
||||
.withType(JoinType.MANY_TO_ONE)
|
||||
.withJoinOn(new JoinOn("sku", "sku"))
|
||||
.withJoinOn(new JoinOn("storeId", "storeId"))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QTableMetaData defineBaseTable(String tableName, String backendTableName)
|
||||
{
|
||||
return new QTableMetaData()
|
||||
.withName(tableName)
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withBackendDetails(new RDBMSTableBackendDetails().withTableName(backendTableName))
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,13 +38,16 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperat
|
||||
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.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
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.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -294,6 +297,71 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOmsJoinAggregate() throws Exception
|
||||
{
|
||||
AggregateInput aggregateInput = new AggregateInput(TestUtils.defineInstance());
|
||||
Aggregate sumOfQuantity = new Aggregate(TestUtils.TABLE_NAME_ORDER_LINE + ".quantity", AggregateOperator.SUM);
|
||||
aggregateInput.setSession(new QSession());
|
||||
aggregateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
aggregateInput.withAggregate(sumOfQuantity);
|
||||
aggregateInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_ORDER_LINE));
|
||||
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals(43, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOmsJoinGroupBy() throws Exception
|
||||
{
|
||||
AggregateInput aggregateInput = new AggregateInput(TestUtils.defineInstance());
|
||||
Aggregate sumOfQuantity = new Aggregate(TestUtils.TABLE_NAME_ORDER_LINE + ".quantity", AggregateOperator.SUM);
|
||||
aggregateInput.setSession(new QSession());
|
||||
aggregateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
aggregateInput.withAggregate(sumOfQuantity);
|
||||
aggregateInput.withGroupByFieldName(TestUtils.TABLE_NAME_ORDER_LINE + ".sku");
|
||||
aggregateInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_ORDER_LINE));
|
||||
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
assertEquals(6, aggregateOutput.getResults().size());
|
||||
assertSkuQuantity("QM-1", 30, aggregateOutput.getResults());
|
||||
assertSkuQuantity("QM-2", 1, aggregateOutput.getResults());
|
||||
assertSkuQuantity("QM-3", 1, aggregateOutput.getResults());
|
||||
assertSkuQuantity("QRU-1", 3, aggregateOutput.getResults());
|
||||
assertSkuQuantity("QRU-2", 2, aggregateOutput.getResults());
|
||||
assertSkuQuantity("QD-1", 6, aggregateOutput.getResults());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertSkuQuantity(String sku, int quantity, List<AggregateResult> results)
|
||||
{
|
||||
for(AggregateResult result : results)
|
||||
{
|
||||
if(result.getGroupByValue("orderLine.sku").equals(sku))
|
||||
{
|
||||
assertEquals(quantity, result.getAggregateValues().values().iterator().next());
|
||||
return;
|
||||
}
|
||||
}
|
||||
fail("Didn't find SKU " + sku + " in aggregate results");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -23,16 +23,19 @@ package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
||||
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.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -60,7 +63,7 @@ public class RDBMSCountActionTest extends RDBMSActionTest
|
||||
{
|
||||
CountInput countInput = initCountRequest();
|
||||
CountOutput countOutput = new RDBMSCountAction().execute(countInput);
|
||||
Assertions.assertEquals(5, countOutput.getCount(), "Unfiltered query should find all rows");
|
||||
assertEquals(5, countOutput.getCount(), "Unfiltered query should find all rows");
|
||||
}
|
||||
|
||||
|
||||
@ -81,7 +84,7 @@ public class RDBMSCountActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(email)))
|
||||
);
|
||||
CountOutput countOutput = new RDBMSCountAction().execute(countInput);
|
||||
Assertions.assertEquals(1, countOutput.getCount(), "Expected # of rows");
|
||||
assertEquals(1, countOutput.getCount(), "Expected # of rows");
|
||||
}
|
||||
|
||||
|
||||
@ -102,7 +105,7 @@ public class RDBMSCountActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(email)))
|
||||
);
|
||||
CountOutput countOutput = new RDBMSCountAction().execute(countInput);
|
||||
Assertions.assertEquals(4, countOutput.getCount(), "Expected # of rows");
|
||||
assertEquals(4, countOutput.getCount(), "Expected # of rows");
|
||||
}
|
||||
|
||||
|
||||
@ -114,8 +117,66 @@ public class RDBMSCountActionTest extends RDBMSActionTest
|
||||
{
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setInstance(TestUtils.defineInstance());
|
||||
countInput.setSession(new QSession());
|
||||
countInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
return countInput;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneInnerJoinWithoutWhere() throws QException
|
||||
{
|
||||
CountInput countInput = initCountRequest();
|
||||
countInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD));
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
assertEquals(3, countOutput.getCount(), "Join count should find 3 rows");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneLeftJoinWithoutWhere() throws QException
|
||||
{
|
||||
CountInput countInput = initCountRequest();
|
||||
countInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withType(QueryJoin.Type.LEFT));
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
assertEquals(5, countOutput.getCount(), "Left Join count should find 5 rows");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneRightJoinWithoutWhere() throws QException
|
||||
{
|
||||
CountInput countInput = initCountRequest();
|
||||
countInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withType(QueryJoin.Type.RIGHT));
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
assertEquals(6, countOutput.getCount(), "Right Join count should find 6 rows");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneInnerJoinWithWhere() throws QException
|
||||
{
|
||||
CountInput countInput = initCountRequest();
|
||||
countInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withSelect(true));
|
||||
countInput.setFilter(new QQueryFilter(new QFilterCriteria(TestUtils.TABLE_NAME_PERSONAL_ID_CARD + ".idNumber", QCriteriaOperator.STARTS_WITH, "1980")));
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
assertEquals(2, countOutput.getCount(), "Right Join count should find 2 rows");
|
||||
}
|
||||
|
||||
}
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
@ -30,16 +31,21 @@ 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.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.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||
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.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -67,7 +73,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
{
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(5, queryOutput.getRecords().size(), "Unfiltered query should find all rows");
|
||||
assertEquals(5, queryOutput.getRecords().size(), "Unfiltered query should find all rows");
|
||||
}
|
||||
|
||||
|
||||
@ -88,8 +94,8 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(email)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertEquals(email, queryOutput.getRecords().get(0).getValueString("email"), "Should find expected email address");
|
||||
assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(email, queryOutput.getRecords().get(0).getValueString("email"), "Should find expected email address");
|
||||
}
|
||||
|
||||
|
||||
@ -110,7 +116,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(email)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueString("email").equals(email)), "Should NOT find expected email address");
|
||||
}
|
||||
|
||||
@ -130,7 +136,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(2, 4)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(2) || r.getValueInteger("id").equals(4)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -150,7 +156,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(2, 3, 4)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(1) || r.getValueInteger("id").equals(5)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -170,7 +176,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of("darin")))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueString("email").matches("darin.*")), "Should find matching email address");
|
||||
}
|
||||
|
||||
@ -190,7 +196,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of("kelkhoff")))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueString("email").matches(".*kelkhoff.*")), "Should find matching email address");
|
||||
}
|
||||
|
||||
@ -210,7 +216,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of("gmail.com")))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueString("email").matches(".*gmail.com")), "Should find matching email address");
|
||||
}
|
||||
|
||||
@ -230,7 +236,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of("darin")))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueString("email").matches("darin.*")), "Should find matching email address");
|
||||
}
|
||||
|
||||
@ -250,7 +256,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of("kelkhoff")))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueString("email").matches(".*kelkhoff.*")), "Should find matching email address");
|
||||
}
|
||||
|
||||
@ -270,7 +276,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of("gmail.com")))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(4, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().noneMatch(r -> r.getValueString("email").matches(".*gmail.com")), "Should find matching email address");
|
||||
}
|
||||
|
||||
@ -290,7 +296,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(3)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(1) || r.getValueInteger("id").equals(2)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -310,7 +316,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(2)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(1) || r.getValueInteger("id").equals(2)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -330,7 +336,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(3)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(4) || r.getValueInteger("id").equals(5)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -350,7 +356,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(4)))
|
||||
);
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(4) || r.getValueInteger("id").equals(5)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -369,7 +375,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withOperator(QCriteriaOperator.IS_BLANK)
|
||||
));
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(1, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValue("birthDate") == null), "Should find expected row");
|
||||
}
|
||||
|
||||
@ -388,7 +394,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withOperator(QCriteriaOperator.IS_NOT_BLANK)
|
||||
));
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(5, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(5, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValue("firstName") != null), "Should find expected rows");
|
||||
}
|
||||
|
||||
@ -408,7 +414,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(2, 4))
|
||||
));
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(3, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(3, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(2) || r.getValueInteger("id").equals(3) || r.getValueInteger("id").equals(4)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -428,7 +434,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withValues(List.of(2, 4))
|
||||
));
|
||||
QueryOutput queryOutput = new RDBMSQueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Expected # of rows");
|
||||
Assertions.assertTrue(queryOutput.getRecords().stream().allMatch(r -> r.getValueInteger("id").equals(1) || r.getValueInteger("id").equals(5)), "Should find expected ids");
|
||||
}
|
||||
|
||||
@ -441,7 +447,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
{
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setInstance(TestUtils.defineInstance());
|
||||
queryInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
queryInput.setSession(new QSession());
|
||||
return queryInput;
|
||||
}
|
||||
@ -459,7 +465,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.setShouldGenerateDisplayValues(true);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(5, queryOutput.getRecords().size(), "Unfiltered query should find all rows");
|
||||
assertEquals(5, queryOutput.getRecords().size(), "Unfiltered query should find all rows");
|
||||
|
||||
for(QRecord record : queryOutput.getRecords())
|
||||
{
|
||||
@ -479,7 +485,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
{
|
||||
InsertInput insertInput = new InsertInput(TestUtils.defineInstance());
|
||||
insertInput.setSession(new QSession());
|
||||
insertInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
insertInput.setTableName(TestUtils.TABLE_NAME_PERSON);
|
||||
|
||||
InsertAction insertAction = new InsertAction();
|
||||
QBackendTransaction transaction = insertAction.openTransaction(insertInput);
|
||||
@ -493,12 +499,12 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(5, queryOutput.getRecords().size(), "Query without the transaction should not see the new row.");
|
||||
assertEquals(5, queryOutput.getRecords().size(), "Query without the transaction should not see the new row.");
|
||||
|
||||
queryInput = initQueryRequest();
|
||||
queryInput.setTransaction(transaction);
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(6, queryOutput.getRecords().size(), "Query with the transaction should see the new row.");
|
||||
assertEquals(6, queryOutput.getRecords().size(), "Query with the transaction should see the new row.");
|
||||
|
||||
transaction.rollback();
|
||||
}
|
||||
@ -514,11 +520,11 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.setFilter(new QQueryFilter().withCriteria(new QFilterCriteria("firstName", QCriteriaOperator.IN, List.of())));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(0, queryOutput.getRecords().size(), "IN empty list should find nothing.");
|
||||
assertEquals(0, queryOutput.getRecords().size(), "IN empty list should find nothing.");
|
||||
|
||||
queryInput.setFilter(new QQueryFilter().withCriteria(new QFilterCriteria("firstName", QCriteriaOperator.NOT_IN, List.of())));
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(5, queryOutput.getRecords().size(), "NOT_IN empty list should find everything.");
|
||||
assertEquals(5, queryOutput.getRecords().size(), "NOT_IN empty list should find everything.");
|
||||
}
|
||||
|
||||
|
||||
@ -536,7 +542,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
.withCriteria(new QFilterCriteria("firstName", QCriteriaOperator.EQUALS, List.of("Tim")))
|
||||
);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "OR should find 2 rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "OR should find 2 rows");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Tim"));
|
||||
}
|
||||
@ -564,7 +570,7 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
))
|
||||
);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(2, queryOutput.getRecords().size(), "Complex query should find 2 rows");
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Complex query should find 2 rows");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("James") && r.getValueString("lastName").equals("Maes"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin") && r.getValueString("lastName").equals("Kelkhoff"));
|
||||
}
|
||||
@ -592,8 +598,322 @@ public class RDBMSQueryActionTest extends RDBMSActionTest
|
||||
))
|
||||
);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
Assertions.assertEquals(1, queryOutput.getRecords().size(), "Complex query should find 1 row");
|
||||
assertEquals(1, queryOutput.getRecords().size(), "Complex query should find 1 row");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Tim") && r.getValueString("lastName").equals("Chamberlain"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneInnerJoinWithoutWhere() throws QException
|
||||
{
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withSelect(true));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(3, queryOutput.getRecords().size(), "Join query should find 3 rows");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin") && r.getValueString("personalIdCard.idNumber").equals("19800531"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("James") && r.getValueString("personalIdCard.idNumber").equals("19800515"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Tim") && r.getValueString("personalIdCard.idNumber").equals("19760528"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneLeftJoinWithoutWhere() throws QException
|
||||
{
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withType(QueryJoin.Type.LEFT).withSelect(true));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(5, queryOutput.getRecords().size(), "Left Join query should find 5 rows");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin") && r.getValueString("personalIdCard.idNumber").equals("19800531"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("James") && r.getValueString("personalIdCard.idNumber").equals("19800515"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Tim") && r.getValueString("personalIdCard.idNumber").equals("19760528"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Garret") && r.getValue("personalIdCard.idNumber") == null);
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Tyler") && r.getValue("personalIdCard.idNumber") == null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneRightJoinWithoutWhere() throws QException
|
||||
{
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withType(QueryJoin.Type.RIGHT).withSelect(true));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(6, queryOutput.getRecords().size(), "Right Join query should find 6 rows");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin") && r.getValueString("personalIdCard.idNumber").equals("19800531"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("James") && r.getValueString("personalIdCard.idNumber").equals("19800515"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Tim") && r.getValueString("personalIdCard.idNumber").equals("19760528"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValue("firstName") == null && r.getValueString("personalIdCard.idNumber").equals("123123123"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValue("firstName") == null && r.getValueString("personalIdCard.idNumber").equals("987987987"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValue("firstName") == null && r.getValueString("personalIdCard.idNumber").equals("456456456"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneInnerJoinWithWhere() throws QException
|
||||
{
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_PERSON, TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withSelect(true));
|
||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(TestUtils.TABLE_NAME_PERSONAL_ID_CARD + ".idNumber", QCriteriaOperator.STARTS_WITH, "1980")));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(2, queryOutput.getRecords().size(), "Join query should find 2 rows");
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("Darin") && r.getValueString("personalIdCard.idNumber").equals("19800531"));
|
||||
assertThat(queryOutput.getRecords()).anyMatch(r -> r.getValueString("firstName").equals("James") && r.getValueString("personalIdCard.idNumber").equals("19800515"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOneToOneInnerJoinWithOrderBy() throws QException
|
||||
{
|
||||
QInstance qInstance = TestUtils.defineInstance();
|
||||
QueryInput queryInput = initQueryRequest();
|
||||
queryInput.withQueryJoin(new QueryJoin(qInstance.getJoin(TestUtils.TABLE_NAME_PERSON + "Join" + TestUtils.TABLE_NAME_PERSONAL_ID_CARD)).withSelect(true));
|
||||
queryInput.setFilter(new QQueryFilter().withOrderBy(new QFilterOrderBy(TestUtils.TABLE_NAME_PERSONAL_ID_CARD + ".idNumber")));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(3, queryOutput.getRecords().size(), "Join query should find 3 rows");
|
||||
List<String> idNumberListFromQuery = queryOutput.getRecords().stream().map(r -> r.getValueString(TestUtils.TABLE_NAME_PERSONAL_ID_CARD + ".idNumber")).toList();
|
||||
assertEquals(List.of("19760528", "19800515", "19800531"), idNumberListFromQuery);
|
||||
|
||||
/////////////////////////
|
||||
// repeat, sorted desc //
|
||||
/////////////////////////
|
||||
queryInput.setFilter(new QQueryFilter().withOrderBy(new QFilterOrderBy(TestUtils.TABLE_NAME_PERSONAL_ID_CARD + ".idNumber", false)));
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(3, queryOutput.getRecords().size(), "Join query should find 3 rows");
|
||||
idNumberListFromQuery = queryOutput.getRecords().stream().map(r -> r.getValueString(TestUtils.TABLE_NAME_PERSONAL_ID_CARD + ".idNumber")).toList();
|
||||
assertEquals(List.of("19800531", "19800515", "19760528"), idNumberListFromQuery);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** In the prime data, we've got 1 order line set up with an item from a different
|
||||
** store than its order. Write a query to find such a case.
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFiveTableOmsJoinFindMismatchedStoreId() throws Exception
|
||||
{
|
||||
QueryInput queryInput = new QueryInput(TestUtils.defineInstance(), new QSession());
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_STORE).withAlias("orderStore").withSelect(true));
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_ORDER_LINE).withSelect(true));
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER_LINE, TestUtils.TABLE_NAME_ITEM).withSelect(true));
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ITEM, TestUtils.TABLE_NAME_STORE).withAlias("itemStore").withSelect(true));
|
||||
|
||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria().withFieldName("orderStore.id").withOperator(QCriteriaOperator.NOT_EQUALS).withOtherFieldName("item.storeId")));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
QRecord qRecord = queryOutput.getRecords().get(0);
|
||||
assertEquals(2, qRecord.getValueInteger("id"));
|
||||
assertEquals(1, qRecord.getValueInteger("orderStore.id"));
|
||||
assertEquals(2, qRecord.getValueInteger("itemStore.id"));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// run the same setup, but this time, use the other-field-name as itemStore.id, instead of item.storeId //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
queryInput.setFilter(new QQueryFilter(new QFilterCriteria().withFieldName("orderStore.id").withOperator(QCriteriaOperator.NOT_EQUALS).withOtherFieldName("itemStore.id")));
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
qRecord = queryOutput.getRecords().get(0);
|
||||
assertEquals(2, qRecord.getValueInteger("id"));
|
||||
assertEquals(1, qRecord.getValueInteger("orderStore.id"));
|
||||
assertEquals(2, qRecord.getValueInteger("itemStore.id"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOmsQueryByOrderLines() throws Exception
|
||||
{
|
||||
AtomicInteger orderLineCount = new AtomicInteger();
|
||||
runTestSql("SELECT COUNT(*) from order_line", (rs) ->
|
||||
{
|
||||
rs.next();
|
||||
orderLineCount.set(rs.getInt(1));
|
||||
});
|
||||
|
||||
QueryInput queryInput = new QueryInput(TestUtils.defineInstance(), new QSession());
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER_LINE);
|
||||
queryInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER_LINE, TestUtils.TABLE_NAME_ORDER).withSelect(true));
|
||||
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(orderLineCount.get(), queryOutput.getRecords().size(), "# of rows found by query");
|
||||
assertEquals(3, queryOutput.getRecords().stream().filter(r -> r.getValueInteger("order.id").equals(1)).count());
|
||||
assertEquals(1, queryOutput.getRecords().stream().filter(r -> r.getValueInteger("order.id").equals(2)).count());
|
||||
assertEquals(1, queryOutput.getRecords().stream().filter(r -> r.getValueInteger("orderId").equals(3)).count());
|
||||
assertEquals(2, queryOutput.getRecords().stream().filter(r -> r.getValueInteger("orderId").equals(4)).count());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOmsQueryByPersons() throws Exception
|
||||
{
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
QueryInput queryInput = new QueryInput(instance, new QSession());
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// inner join on bill-to person should find 6 rows //
|
||||
/////////////////////////////////////////////////////
|
||||
queryInput.withQueryJoins(List.of(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_PERSON).withJoinMetaData(instance.getJoin("orderJoinBillToPerson")).withSelect(true)));
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(6, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// inner join on ship-to person should find 7 rows //
|
||||
/////////////////////////////////////////////////////
|
||||
queryInput.withQueryJoins(List.of(new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withSelect(true)));
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(7, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// inner join on both bill-to person and ship-to person should find 5 rows //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
queryInput.withQueryJoins(List.of(
|
||||
new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withAlias("shipToPerson").withSelect(true),
|
||||
new QueryJoin(instance.getJoin("orderJoinBillToPerson")).withAlias("billToPerson").withSelect(true)
|
||||
));
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(5, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// left join on both bill-to person and ship-to person should find 8 rows //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
queryInput.withQueryJoins(List.of(
|
||||
new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withType(QueryJoin.Type.LEFT).withAlias("shipToPerson").withSelect(true),
|
||||
new QueryJoin(instance.getJoin("orderJoinBillToPerson")).withType(QueryJoin.Type.LEFT).withAlias("billToPerson").withSelect(true)
|
||||
));
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(8, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// now join through to personalIdCard table too //
|
||||
//////////////////////////////////////////////////
|
||||
queryInput.withQueryJoins(List.of(
|
||||
new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withAlias("shipToPerson").withSelect(true),
|
||||
new QueryJoin(instance.getJoin("orderJoinBillToPerson")).withAlias("billToPerson").withSelect(true),
|
||||
new QueryJoin("billToPerson", TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withAlias("billToIdCard").withSelect(true),
|
||||
new QueryJoin("shipToPerson", TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withAlias("shipToIdCard").withSelect(true)
|
||||
));
|
||||
queryInput.setFilter(new QQueryFilter()
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// look for billToPersons w/ idNumber starting with 1980 - should only be James and Darin (assert on that below). //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
.withCriteria(new QFilterCriteria("billToIdCard.idNumber", QCriteriaOperator.STARTS_WITH, "1980"))
|
||||
);
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(3, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
assertThat(queryOutput.getRecords().stream().map(r -> r.getValueString("billToPerson.firstName")).toList()).allMatch(p -> p.equals("Darin") || p.equals("James"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOmsQueryByPersonsExtraKelkhoffOrder() throws Exception
|
||||
{
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
QueryInput queryInput = new QueryInput(instance, new QSession());
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// insert a second person w/ last name Kelkhoff, then an order for Darin Kelkhoff and this new Kelkhoff - //
|
||||
// then query for orders w/ bill to person & ship to person both lastname = Kelkhoff, but different ids. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Integer specialOrderId = 1701;
|
||||
runTestSql("INSERT INTO person (id, first_name, last_name, email) VALUES (6, 'Jimmy', 'Kelkhoff', 'dk@gmail.com')", null);
|
||||
runTestSql("INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (" + specialOrderId + ", 1, 1, 6)", null);
|
||||
queryInput.withQueryJoins(List.of(
|
||||
new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withType(QueryJoin.Type.LEFT).withAlias("shipToPerson").withSelect(true),
|
||||
new QueryJoin(instance.getJoin("orderJoinBillToPerson")).withType(QueryJoin.Type.LEFT).withAlias("billToPerson").withSelect(true)
|
||||
));
|
||||
queryInput.setFilter(new QQueryFilter()
|
||||
.withCriteria(new QFilterCriteria().withFieldName("shipToPerson.lastName").withOperator(QCriteriaOperator.EQUALS).withOtherFieldName("billToPerson.lastName"))
|
||||
.withCriteria(new QFilterCriteria().withFieldName("shipToPerson.id").withOperator(QCriteriaOperator.NOT_EQUALS).withOtherFieldName("billToPerson.id"))
|
||||
);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
assertEquals(specialOrderId, queryOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// re-run that query using personIds from the order table //
|
||||
////////////////////////////////////////////////////////////
|
||||
queryInput.setFilter(new QQueryFilter()
|
||||
.withCriteria(new QFilterCriteria().withFieldName("shipToPerson.lastName").withOperator(QCriteriaOperator.EQUALS).withOtherFieldName("billToPerson.lastName"))
|
||||
.withCriteria(new QFilterCriteria().withFieldName("order.shipToPersonId").withOperator(QCriteriaOperator.NOT_EQUALS).withOtherFieldName("order.billToPersonId"))
|
||||
);
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
assertEquals(specialOrderId, queryOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// re-run that query using personIds from the order table, but not specifying the table name //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
queryInput.setFilter(new QQueryFilter()
|
||||
.withCriteria(new QFilterCriteria().withFieldName("shipToPerson.lastName").withOperator(QCriteriaOperator.EQUALS).withOtherFieldName("billToPerson.lastName"))
|
||||
.withCriteria(new QFilterCriteria().withFieldName("shipToPersonId").withOperator(QCriteriaOperator.NOT_EQUALS).withOtherFieldName("billToPersonId"))
|
||||
);
|
||||
queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, queryOutput.getRecords().size(), "# of rows found by query");
|
||||
assertEquals(specialOrderId, queryOutput.getRecords().get(0).getValueInteger("id"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testDuplicateAliases()
|
||||
{
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
QueryInput queryInput = new QueryInput(instance, new QSession());
|
||||
queryInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||
|
||||
queryInput.withQueryJoins(List.of(
|
||||
new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withAlias("shipToPerson"),
|
||||
new QueryJoin(instance.getJoin("orderJoinBillToPerson")).withAlias("billToPerson"),
|
||||
new QueryJoin("billToPerson", TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withSelect(true),
|
||||
new QueryJoin("shipToPerson", TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withSelect(true) // w/o alias, should get exception here - dupe table.
|
||||
));
|
||||
assertThatThrownBy(() -> new QueryAction().execute(queryInput))
|
||||
.hasRootCauseMessage("Duplicate table name or alias: personalIdCard");
|
||||
|
||||
queryInput.withQueryJoins(List.of(
|
||||
new QueryJoin(instance.getJoin("orderJoinShipToPerson")).withAlias("shipToPerson"),
|
||||
new QueryJoin(instance.getJoin("orderJoinBillToPerson")).withAlias("billToPerson"),
|
||||
new QueryJoin("shipToPerson", TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withAlias("shipToPerson").withSelect(true), // dupe alias, should get exception here
|
||||
new QueryJoin("billToPerson", TestUtils.TABLE_NAME_PERSONAL_ID_CARD).withAlias("billToPerson").withSelect(true)
|
||||
));
|
||||
assertThatThrownBy(() -> new QueryAction().execute(queryInput))
|
||||
.hasRootCauseMessage("Duplicate table name or alias: shipToPerson");
|
||||
}
|
||||
|
||||
}
|
@ -41,6 +41,23 @@ INSERT INTO person (id, first_name, last_name, birth_date, email, is_employed, a
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email, is_employed, annual_salary, days_worked) VALUES (4, 'Tyler', 'Samples', NULL, 'tsamples@mmltholdings.com', 1, 30000, 99);
|
||||
INSERT INTO person (id, first_name, last_name, birth_date, email, is_employed, annual_salary, days_worked) VALUES (5, 'Garret', 'Richardson', '1981-01-01', 'grichardson@mmltholdings.com', 1, 1000000, 232);
|
||||
|
||||
DROP TABLE IF EXISTS personal_id_card;
|
||||
CREATE TABLE personal_id_card
|
||||
(
|
||||
id INT AUTO_INCREMENT primary key ,
|
||||
create_date TIMESTAMP DEFAULT now(),
|
||||
modify_date TIMESTAMP DEFAULT now(),
|
||||
person_id INTEGER,
|
||||
id_number VARCHAR(250)
|
||||
);
|
||||
|
||||
INSERT INTO personal_id_card (person_id, id_number) VALUES (1, '19800531');
|
||||
INSERT INTO personal_id_card (person_id, id_number) VALUES (2, '19800515');
|
||||
INSERT INTO personal_id_card (person_id, id_number) VALUES (3, '19760528');
|
||||
INSERT INTO personal_id_card (person_id, id_number) VALUES (6, '123123123');
|
||||
INSERT INTO personal_id_card (person_id, id_number) VALUES (null, '987987987');
|
||||
INSERT INTO personal_id_card (person_id, id_number) VALUES (null, '456456456');
|
||||
|
||||
DROP TABLE IF EXISTS carrier;
|
||||
CREATE TABLE carrier
|
||||
(
|
||||
@ -61,3 +78,77 @@ INSERT INTO carrier (id, name, company_code, service_level) VALUES (8, 'USPS Sup
|
||||
INSERT INTO carrier (id, name, company_code, service_level) VALUES (9, 'USPS Super Fast', 'USPS', '0');
|
||||
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 order_line;
|
||||
DROP TABLE IF EXISTS item;
|
||||
DROP TABLE IF EXISTS `order`;
|
||||
DROP TABLE IF EXISTS store;
|
||||
|
||||
CREATE TABLE store
|
||||
(
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(80) NOT NULL
|
||||
);
|
||||
|
||||
-- define 3 stores
|
||||
INSERT INTO store (id, name) VALUES (1, 'Q-Mart');
|
||||
INSERT INTO store (id, name) VALUES (2, 'QQQ ''R'' Us');
|
||||
INSERT INTO store (id, name) VALUES (3, 'QDepot');
|
||||
|
||||
CREATE TABLE item
|
||||
(
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
sku VARCHAR(80) NOT NULL,
|
||||
store_id INT NOT NULL REFERENCES store
|
||||
);
|
||||
|
||||
-- three items for each store
|
||||
INSERT INTO item (id, sku, store_id) VALUES (1, 'QM-1', 1);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (2, 'QM-2', 1);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (3, 'QM-3', 1);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (4, 'QRU-1', 2);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (5, 'QRU-2', 2);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (6, 'QRU-3', 2);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (7, 'QD-1', 3);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (8, 'QD-2', 3);
|
||||
INSERT INTO item (id, sku, store_id) VALUES (9, 'QD-3', 3);
|
||||
|
||||
CREATE TABLE `order`
|
||||
(
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
store_id INT REFERENCES store,
|
||||
bill_to_person_id INT,
|
||||
ship_to_person_id INT
|
||||
);
|
||||
|
||||
-- variable orders
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (1, 1, 1, 1);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (2, 1, 1, 2);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (3, 1, 2, 3);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (4, 2, 4, 5);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (5, 2, 5, 4);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (6, 3, 5, null);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (7, 3, null, 5);
|
||||
INSERT INTO `order` (id, store_id, bill_to_person_id, ship_to_person_id) VALUES (8, 3, null, 5);
|
||||
|
||||
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...
|
||||
quantity INT
|
||||
);
|
||||
|
||||
-- various lines
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (1, 'QM-1', 1, 10);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (1, 'QM-2', 1, 1);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (1, 'QM-3', 1, 1);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (2, 'QRU-1', 2, 1); -- this line has an item from a different store than its order.
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (3, 'QM-1', 1, 20);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (4, 'QRU-1', 2, 1);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (4, 'QRU-2', 2, 2);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (5, 'QRU-1', 2, 1);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (6, 'QD-1', 3, 1);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (7, 'QD-1', 3, 2);
|
||||
INSERT INTO order_line (order_id, sku, store_id, quantity) VALUES (8, 'QD-1', 3, 3);
|
||||
|
Reference in New Issue
Block a user