Skip to content
This repository has been archived by the owner on Jun 29, 2021. It is now read-only.

Commit

Permalink
METAMODEL-1144: Minor formatting and warning-elemination
Browse files Browse the repository at this point in the history
Fixes #148
  • Loading branch information
kaspersorensen committed Jul 27, 2017
1 parent dda13e2 commit ddfa13e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 144 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -7,6 +7,7 @@
* [METAMODEL-1139] - Employed Java 8 functional types (java.util.function) in favor of (now deprecated) Ref, Action, Func.
* [METAMODEL-1140] - Allowed SalesforceDataContext without a security token.
* [METAMODEL-1141] - Added RFC 4180 compliant CSV parsing.
* [METAMODEL-1144] - Optimized evaluation of conditional client-side JOIN statements.

### Apache MetaModel 4.6.0

Expand Down
48 changes: 23 additions & 25 deletions core/src/main/java/org/apache/metamodel/MetaModelHelper.java
Expand Up @@ -175,7 +175,7 @@ public static DataSet getCarthesianProduct(DataSet[] fromDataSets, FilterItem...
}

public static DataSet getCarthesianProduct(DataSet[] fromDataSets, Iterable<FilterItem> whereItems) {
assert(fromDataSets.length>0);
assert (fromDataSets.length > 0);
// First check if carthesian product is even nescesary
if (fromDataSets.length == 1) {
return getFiltered(fromDataSets[0], whereItems);
Expand All @@ -185,76 +185,75 @@ public static DataSet getCarthesianProduct(DataSet[] fromDataSets, Iterable<Filt

DataSet joined = dsIter.next();

while(dsIter.hasNext()){
joined = nestedLoopJoin(
dsIter.next(),
joined,
(whereItems));
while (dsIter.hasNext()) {
joined = nestedLoopJoin(dsIter.next(), joined, (whereItems));

}

return joined;


}

/**
* Executes a simple nested loop join. The innerLoopDs will be copied in an in-memory dataset.
* Executes a simple nested loop join. The innerLoopDs will be copied in an
* in-memory dataset.
*
*/
public static InMemoryDataSet nestedLoopJoin(DataSet innerLoopDs, DataSet outerLoopDs, Iterable<FilterItem> filtersIterable){
public static InMemoryDataSet nestedLoopJoin(DataSet innerLoopDs, DataSet outerLoopDs,
Iterable<FilterItem> filtersIterable) {

List<FilterItem> filters = new ArrayList<>();
for(FilterItem fi : filtersIterable){
for (FilterItem fi : filtersIterable) {
filters.add(fi);
}
List<Row> innerRows = innerLoopDs.toRows();


List<SelectItem> allItems = new ArrayList<>(Arrays.asList(outerLoopDs.getSelectItems())) ;
List<SelectItem> allItems = new ArrayList<>(Arrays.asList(outerLoopDs.getSelectItems()));
allItems.addAll(Arrays.asList(innerLoopDs.getSelectItems()));

Set<FilterItem> applicableFilters = applicableFilters(filters,allItems);
Set<FilterItem> applicableFilters = applicableFilters(filters, allItems);

DataSetHeader jointHeader = new CachingDataSetHeader(allItems);

List<Row> resultRows = new ArrayList<>();
for(Row outerRow: outerLoopDs){
for(Row innerRow: innerRows){
for (Row outerRow : outerLoopDs) {
for (Row innerRow : innerRows) {

Object[] joinedRowObjects = new Object[outerRow.getValues().length + innerRow.getValues().length];

System.arraycopy(outerRow.getValues(),0,joinedRowObjects,0,outerRow.getValues().length);
System.arraycopy(innerRow.getValues(),0,joinedRowObjects,outerRow.getValues().length,innerRow.getValues().length);

Row joinedRow = new DefaultRow(jointHeader,joinedRowObjects);
System.arraycopy(outerRow.getValues(), 0, joinedRowObjects, 0, outerRow.getValues().length);
System.arraycopy(innerRow.getValues(), 0, joinedRowObjects, outerRow.getValues().length, innerRow
.getValues().length);

Row joinedRow = new DefaultRow(jointHeader, joinedRowObjects);

if(applicableFilters.isEmpty()|| applicableFilters.stream().allMatch(fi -> fi.accept(joinedRow))){
if (applicableFilters.isEmpty() || applicableFilters.stream().allMatch(fi -> fi.accept(joinedRow))) {
resultRows.add(joinedRow);
}
}
}

return new InMemoryDataSet(jointHeader,resultRows);
return new InMemoryDataSet(jointHeader, resultRows);
}

/**
* Filters the FilterItems such that only the FilterItems are returned,
* which contain SelectItems that are contained in selectItemList
*
* @param filters
* @param selectItemList
* @return
*/
private static Set<FilterItem> applicableFilters(Collection<FilterItem> filters, Collection<SelectItem> selectItemList) {
private static Set<FilterItem> applicableFilters(Collection<FilterItem> filters,
Collection<SelectItem> selectItemList) {

Set<SelectItem> items = new HashSet<SelectItem>(selectItemList);

return filters.stream().filter( fi -> {
return filters.stream().filter(fi -> {
Collection<SelectItem> fiSelectItems = new ArrayList<>();
fiSelectItems.add(fi.getSelectItem());
Object operand = fi.getOperand();
if(operand instanceof SelectItem){
if (operand instanceof SelectItem) {
fiSelectItems.add((SelectItem) operand);
}

Expand All @@ -263,7 +262,6 @@ private static Set<FilterItem> applicableFilters(Collection<FilterItem> filters
}).collect(Collectors.toSet());
}


public static DataSet getFiltered(DataSet dataSet, Iterable<FilterItem> filterItems) {
List<IRowFilter> filters = CollectionUtils.map(filterItems, filterItem -> {
return filterItem;
Expand Down
109 changes: 50 additions & 59 deletions core/src/test/java/org/apache/metamodel/MetaModelHelperTest.java
Expand Up @@ -116,14 +116,17 @@ public void testRightJoin() throws Exception {
public void testSimpleCarthesianProduct() throws Exception {
DataSet dataSet = MetaModelHelper.getCarthesianProduct(createDataSet1(), createDataSet2());
List<String> results = new ArrayList<String>();
while(dataSet.next()){
results.add(dataSet.getRow().toString());

while (dataSet.next()) {
results.add(dataSet.getRow().toString());
}
assertEquals(2, dataSet.getSelectItems().length);
assertEquals(9, results.size());
assertTrue(results.contains("Row[values=[f, b]]"));
assertTrue(results.contains("Row[values=[f, a]]"));
assertTrue(results.contains("Row[values=[f, r]]"));
assertTrue(results.contains("Row[values=[o, b]]"));
assertTrue(results.contains("Row[values=[o, a]]"));
assertTrue(results.contains("Row[values=[o, r]]"));
}

Expand Down Expand Up @@ -182,8 +185,8 @@ private DataSet createDataSet1() {
data1.add(new Object[] { "f" });
data1.add(new Object[] { "o" });
data1.add(new Object[] { "o" });
DataSet dataSet1 = createDataSet(
new SelectItem[] { new SelectItem(new MutableColumn("foo", ColumnType.VARCHAR)) }, data1);
DataSet dataSet1 = createDataSet(new SelectItem[] { new SelectItem(new MutableColumn("foo",
ColumnType.VARCHAR)) }, data1);
return dataSet1;
}

Expand All @@ -200,8 +203,8 @@ private DataSet createDataSet3() {
List<Object[]> data3 = new ArrayList<Object[]>();
data3.add(new Object[] { "w00p", true });
data3.add(new Object[] { "yippie", false });
DataSet dataSet3 = createDataSet(new SelectItem[] { new SelectItem("expression", "e"),
new SelectItem("webish?", "w") }, data3);
DataSet dataSet3 = createDataSet(new SelectItem[] { new SelectItem("expression", "e"), new SelectItem("webish?",
"w") }, data3);
return dataSet3;
}

Expand All @@ -210,52 +213,41 @@ private DataSet createDataSet4() {
DataSet dataSet4 = createDataSet(new SelectItem[] { new SelectItem("abc", "abc") }, data4);
return dataSet4;
}




private int bigDataSetSize = 3000;

/**
*
* @return a big dataset, mocking an employee table
*/
private DataSet createDataSet5() {
List<Object[]> data5 = new ArrayList<Object[]>();


for(int i = 0; i<bigDataSetSize;i++){
data5.add(new Object[]{i,"Person_" + i, bigDataSetSize-(i+1) });
}

DataSet dataSet5 = createDataSet(
new SelectItem[] {
new SelectItem(new MutableColumn("nr", ColumnType.BIGINT)),
new SelectItem(new MutableColumn("name", ColumnType.STRING)),
new SelectItem(new MutableColumn("dnr", ColumnType.BIGINT))
},
data5);
return dataSet5;
}

List<Object[]> data5 = new ArrayList<Object[]>();

for (int i = 0; i < bigDataSetSize; i++) {
data5.add(new Object[] { i, "Person_" + i, bigDataSetSize - (i + 1) });
}

DataSet dataSet5 = createDataSet(new SelectItem[] { new SelectItem(new MutableColumn("nr", ColumnType.BIGINT)),
new SelectItem(new MutableColumn("name", ColumnType.STRING)), new SelectItem(new MutableColumn("dnr",
ColumnType.BIGINT)) }, data5);
return dataSet5;
}

/**
*
* @return a big dataset, mocking an department table
*/
private DataSet createDataSet6() {
List<Object[]> data6 = new ArrayList<Object[]>();

for(int i = 0; i<bigDataSetSize;i++){
data6.add(new Object[]{i,"Department_" + i });
}

DataSet dataSet6 = createDataSet(
new SelectItem[] {
new SelectItem(new MutableColumn("nr", ColumnType.BIGINT)),
new SelectItem(new MutableColumn("name", ColumnType.STRING)),
},
data6);
return dataSet6;
}
List<Object[]> data6 = new ArrayList<Object[]>();

for (int i = 0; i < bigDataSetSize; i++) {
data6.add(new Object[] { i, "Department_" + i });
}

DataSet dataSet6 = createDataSet(new SelectItem[] { new SelectItem(new MutableColumn("nr", ColumnType.BIGINT)),
new SelectItem(new MutableColumn("name", ColumnType.STRING)), }, data6);
return dataSet6;
}

public void testGetTables() throws Exception {
MutableTable table1 = new MutableTable("table1");
Expand Down Expand Up @@ -365,23 +357,22 @@ public void testLeftJoinNoRowsOrSingleRow() throws Exception {
assertEquals("Row[values=[1, 2, null]]", joinedDs.getRow().toString());
assertFalse(joinedDs.next());
}


public void testCarthesianProductScalability(){

DataSet employees = createDataSet5();
DataSet departmens = createDataSet6();

FilterItem fi = new FilterItem(employees.getSelectItems()[2], OperatorType.EQUALS_TO,departmens.getSelectItems()[0]);

DataSet joined = MetaModelHelper.getCarthesianProduct(new DataSet[]{employees,departmens}, fi);
int count = 0;
while(joined.next()){
count++;
}

assertTrue(count == bigDataSetSize);



public void testCarthesianProductScalability() {

DataSet employees = createDataSet5();
DataSet departmens = createDataSet6();

FilterItem fi = new FilterItem(employees.getSelectItems()[2], OperatorType.EQUALS_TO, departmens
.getSelectItems()[0]);

DataSet joined = MetaModelHelper.getCarthesianProduct(new DataSet[] { employees, departmens }, fi);
int count = 0;
while (joined.next()) {
count++;
}

assertTrue(count == bigDataSetSize);

}
}

0 comments on commit ddfa13e

Please sign in to comment.