This is an automated email from the ASF dual-hosted git repository.

mboehm7 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/systemds.git


The following commit(s) were added to refs/heads/main by this push:
     new 5b9db8767e [SYSTEMDS-3708] raJoin and raGroupby builtin functions
5b9db8767e is described below

commit 5b9db8767ea3f0728afe0630138771a8f77c0369
Author: gghsu <ppp432...@gmail.com>
AuthorDate: Sun Jun 30 10:16:51 2024 +0200

    [SYSTEMDS-3708] raJoin and raGroupby builtin functions
    
    LDE project SoSe'24, part 2
    Closes #2037.
---
 scripts/builtin/raGroupby.dml                      |  92 +++++++++
 scripts/builtin/{raSelection.dml => raJoin.dml}    |  39 ++--
 scripts/builtin/raSelection.dml                    |   2 +-
 .../java/org/apache/sysds/common/Builtins.java     |   2 +
 .../builtin/part2/BuiltinRaGroupbyTest.java        | 164 ++++++++++++++++
 .../functions/builtin/part2/BuiltinRaJoinTest.java | 212 +++++++++++++++++++++
 src/test/scripts/functions/builtin/raGroupby.dml   |  28 +++
 src/test/scripts/functions/builtin/raJoin.dml      |  29 +++
 8 files changed, 550 insertions(+), 18 deletions(-)

diff --git a/scripts/builtin/raGroupby.dml b/scripts/builtin/raGroupby.dml
new file mode 100644
index 0000000000..35f5996616
--- /dev/null
+++ b/scripts/builtin/raGroupby.dml
@@ -0,0 +1,92 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+# This raGroupby-function takes a matrix dataset as input from where it 
performs
+# relational operations : groupby
+#
+# INPUT:
+# 
------------------------------------------------------------------------------
+# X         Matrix of input data [shape: N x M]
+# col       Integer indicating the column index to execute grupby command
+# method    Groupby implemention method (nested-loop)
+# 
------------------------------------------------------------------------------
+#
+# OUTPUT:
+# 
------------------------------------------------------------------------------
+# Y         Matrix of selected data [shape N' x M] with N' <= N
+# 
------------------------------------------------------------------------------
+
+m_raGroupby = function (Matrix[Double] X, Integer col, String 
method="nested-loop")
+  return (Matrix[Double] Y)
+{
+  # Extract and sort unique values from the specified column (1-based index)
+  uniqueValues = unique(X[, col])
+  order_uniqueValues = order(target = uniqueValues, by = 1);
+
+  # Calcute the number of groups
+  numGroups = nrow(uniqueValues)
+
+  # Determine the maximum number of rows in any group
+  maxRowsInGroup = 0
+  for(i in 1:numGroups){
+    groupValue = uniqueValues[i,1]
+    groupRows = ( X[,col] == groupValue )
+
+    groupSize = sum(groupRows)
+    if( groupSize > maxRowsInGroup ){
+      maxRowsInGroup = groupSize
+    }
+  }
+
+  # Define a zero matrix to put the group data into
+  Y=matrix(0,numGroups,maxRowsInGroup*(ncol(X)-1)+1)
+
+  # Put the ordered uniqueValues into first column of Y as group_id
+  Y[,1] = order_uniqueValues
+
+  # Loop for each group
+  for(i in 1:numGroups){
+    index = 0
+
+    # Iterate each row in matrix X to deal with group data
+    for ( j in 1:nrow(X) ) {
+      if ( as.scalar( X[j,col] == order_uniqueValues[i,1] )) {
+        # Define the formula of the start and end column position
+        startCol = index*(ncol(X)-1) +2
+        endCol = startCol + (ncol(X)-2)
+
+        if (col == 1) {
+          # Case when the selected column is the first column
+          Y[i,startCol:endCol]=X[j,2:ncol(X)]
+        }  else if (col == ncol(X)) {
+          # Case when the selected column is the last column
+          Y[i,startCol:endCol]=X[j,1:(ncol(X)-1)]
+        } else {
+          # General case
+          newRow = cbind(X[j, 1:(col-1)], X[j, (col+1):ncol(X)])
+          Y[i,startCol:endCol]=newRow
+        }
+        index = index +1
+      }
+    }
+  }
+}
+
diff --git a/scripts/builtin/raSelection.dml b/scripts/builtin/raJoin.dml
similarity index 56%
copy from scripts/builtin/raSelection.dml
copy to scripts/builtin/raJoin.dml
index 70d05b5cc8..333a1f3e8d 100644
--- a/scripts/builtin/raSelection.dml
+++ b/scripts/builtin/raJoin.dml
@@ -19,34 +19,39 @@
 #
 #-------------------------------------------------------------
 
-# This raSelection-function takes a matrix data set as input from where it 
performs
-# relational operations : selection
+# This raJoin-function takes two matrix datasets as input from where it 
performs
+# relational operations : join
 #
 # INPUT:
 # 
------------------------------------------------------------------------------
-# X         Matrix of input data [shape: N x M]
-# col       Integer indicating the column index to execute selection command
-# op        String specifying the comparison operator (e.g., ">", "<", "==").
-# val       Constant value to compare the column values "with col op val'
+# A         Matrix of left input data [shape: N x M]
+# colA      Integer indicating the column index of matrix A to execute inner 
join command
+# B         Matrix of right left data [shape: N x M]
+# colA      Integer indicating the column index of matrix B to execute inner 
join command
+# method    Join implementation method (nested-loop)
 # 
------------------------------------------------------------------------------
 #
 # OUTPUT:
 # 
------------------------------------------------------------------------------
-# Y         Matrix of selected data [shape N' x M] with N' <= N
+# Y         Matrix of joined data [shape N' x M] with N' <= N
 # 
------------------------------------------------------------------------------
 
-m_raSelection = function (Matrix[Double] X, Integer col, String op, Double val)
+m_raJoin = function (Matrix[Double] A, Integer colA, Matrix[Double] B,
+  Integer colB, String method="nested-loop")
   return (Matrix[Double] Y)
 {
-  # Dertimine the operators
-  I = ifelse(op == "==", X[,col] == val,
-        ifelse(op == "!=", X[,col] != val,
-        ifelse(op == "<",  X[,col] <  val,
-        ifelse(op == ">",  X[,col] >  val,
-        ifelse(op == "<=", X[,col] <= val,
-        X[,col] >= val)))))
+  # matrix of result data
+  Y = matrix(0, rows=0, cols=ncol(A) + ncol(B) )
 
-  # Perform actual selection
-  Y = removeEmpty(target=X, margin="rows", select=I);
+  for (i in 1:nrow(A)) {
+    for (j in 1:nrow(B)) {
+      if (as.scalar(A[i, colA] == B[j, colB])) {
+        # Combine the matching row from A and B to match
+        match = cbind(A[i,], B[j,])
+        # merge the match row into result Y
+        Y = rbind(Y, match)
+      }
+    }
+  }
 }
 
diff --git a/scripts/builtin/raSelection.dml b/scripts/builtin/raSelection.dml
index 70d05b5cc8..b94e8ad1c1 100644
--- a/scripts/builtin/raSelection.dml
+++ b/scripts/builtin/raSelection.dml
@@ -27,7 +27,7 @@
 # X         Matrix of input data [shape: N x M]
 # col       Integer indicating the column index to execute selection command
 # op        String specifying the comparison operator (e.g., ">", "<", "==").
-# val       Constant value to compare the column values "with col op val'
+# val       Constant value to compare the column values "with col op val"
 # 
------------------------------------------------------------------------------
 #
 # OUTPUT:
diff --git a/src/main/java/org/apache/sysds/common/Builtins.java 
b/src/main/java/org/apache/sysds/common/Builtins.java
index a358b2e2bc..8baee4ec2f 100644
--- a/src/main/java/org/apache/sysds/common/Builtins.java
+++ b/src/main/java/org/apache/sysds/common/Builtins.java
@@ -275,6 +275,8 @@ public enum Builtins {
        RANDOM_FOREST("randomForest", true),
        RANDOM_FOREST_PREDICT("randomForestPredict", true),
        RANGE("range", false),
+       RAGROUPBY("raGroupby", true),
+       RAJOIN("raJoin", true),
        RASELECTION("raSelection", true),
        RBIND("rbind", false),
        RCM("rowClassMeet", "rcm", false, false, ReturnType.MULTI_RETURN),
diff --git 
a/src/test/java/org/apache/sysds/test/functions/builtin/part2/BuiltinRaGroupbyTest.java
 
b/src/test/java/org/apache/sysds/test/functions/builtin/part2/BuiltinRaGroupbyTest.java
new file mode 100644
index 0000000000..6db3c46d3b
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/functions/builtin/part2/BuiltinRaGroupbyTest.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysds.test.functions.builtin.part2;
+
+import org.apache.sysds.common.Types.ExecMode;
+import org.apache.sysds.runtime.matrix.data.MatrixValue.CellIndex;
+import org.apache.sysds.test.AutomatedTestBase;
+import org.apache.sysds.test.TestConfiguration;
+import org.apache.sysds.test.TestUtils;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class BuiltinRaGroupbyTest extends AutomatedTestBase
+{
+       private final static String TEST_NAME = "raGroupby";
+       private final static String TEST_DIR = "functions/builtin/";
+       private static final String TEST_CLASS_DIR = TEST_DIR + 
BuiltinRaGroupbyTest.class.getSimpleName() + "/";
+       private final static double eps = 1e-8;
+       
+       @Override
+       public void setUp() {
+               addTestConfiguration(TEST_NAME,new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME,new String[]{"result"}));
+       }
+
+       @Test
+       public void testRaGroupbyTest() {
+               //generate actual dataset and variables
+               double[][] X = {
+                               {1, 2, 3},
+                               {4, 7, 8},
+                               {1, 3, 6},
+                               {4, 7, 8},
+                               {4, 8, 9}};
+               int select_col = 1;
+
+               // Expected output matrix
+               double[][] Y = {
+                               {1, 2, 3, 3, 6, 0, 0},
+                               {4, 7, 8, 7, 8, 8, 9}
+               };
+
+               runRaGroupbyTest(X, select_col, Y);
+       }
+
+       @Test
+       public void testRaGroupbyTestwithDifferentColumn() {
+               //generate actual dataset and variables
+               double[][] X = {
+                               {1, 2, 3},
+                               {4, 7, 8},
+                               {1, 3, 6},
+                               {4, 7, 8},
+                               {4, 8, 9}};
+               int select_col = 2;
+
+               // Expected output matrix
+               double[][] Y = {
+                               {2, 1, 3, 0, 0},
+                               {3, 1, 6, 0, 0},
+                               {7, 4, 8, 4, 8},
+                               {8, 4, 9, 0, 0}
+               };
+
+               runRaGroupbyTest(X, select_col, Y);
+       }
+
+       @Test
+       public void testRaGroupbyTestwithNoGroup() {
+               // Test case with different values in select_col
+               double[][] X = {
+                               {1, 1, 1},
+                               {2, 2, 2},
+                               {3, 1, 3},
+                               {4, 2, 4},
+                               {5, 1, 5}};
+               int select_col = 3;
+
+               // Expected output matrix
+               double[][] Y = {
+                               {1, 1, 1},
+                               {2, 2, 2},
+                               {3, 3, 1},
+                               {4, 4, 2},
+                               {5, 5, 1}
+               };
+
+               runRaGroupbyTest(X, select_col, Y);
+       }
+
+       @Test
+       public void testRaGroupbyTestwithOneGroup() {
+               //generate actual dataset and variables
+               double[][] X = {
+                               {1, 2, 3, 8, 2},
+                               {4, 7, 8, 8, 3},
+                               {1, 3, 6, 8, 4},
+                               {4, 7, 8, 8, 5},
+                               {4, 8, 9, 8, 6}};
+               int select_col = 4;
+
+               // Expected output matrix
+               double[][] Y = {
+                               {8, 1, 2, 3, 2, 4, 7, 8, 3, 1, 3, 6, 4, 4, 7, 
8, 5, 4, 8, 9, 6},
+               };
+
+               runRaGroupbyTest(X, select_col, Y);
+       }
+
+       private void runRaGroupbyTest(double [][] X, int col, double [][] Y)
+       {
+               ExecMode platformOld = setExecMode(ExecMode.SINGLE_NODE);
+               
+               try
+               {
+                       loadTestConfiguration(getTestConfiguration(TEST_NAME));
+                       String HOME = SCRIPT_DIR + TEST_DIR;
+
+                       fullDMLScriptName = HOME + TEST_NAME + ".dml";
+                       programArgs = new String[]{"-stats", "-args",
+                               input("X"), String.valueOf(col), 
output("result") };
+                       System.out.println(Arrays.deepToString(X));
+                       System.out.println(col);
+                       //fullRScriptName = HOME + TEST_NAME + ".R";
+                       //rCmd = "Rscript" + " " + fullRScriptName + " "
+                       //      + inputDir() + " " + col + " "  + expectedDir();
+
+                       writeInputMatrixWithMTD("X", X, true);
+                       System.out.println(Arrays.deepToString(X));
+                       //writeExpectedMatrix("result", Y);
+
+                       // run dmlScript and RScript
+                       runTest(true, false, null, -1);
+                       //runRScript(true);
+
+                       //compare matrices
+                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromOutputDir("result");
+                       HashMap<CellIndex, Double> expectedOutput = 
TestUtils.convert2DDoubleArrayToHashMap(Y);
+                       //HashMap<CellIndex, Double> rfile  = 
readRMatrixFromExpectedDir("result");
+                       TestUtils.compareMatrices(dmlfile, expectedOutput, eps, 
"Stat-DML", "Expected");
+               }
+               finally {
+                       rtplatform = platformOld;
+               }
+       }
+}
diff --git 
a/src/test/java/org/apache/sysds/test/functions/builtin/part2/BuiltinRaJoinTest.java
 
b/src/test/java/org/apache/sysds/test/functions/builtin/part2/BuiltinRaJoinTest.java
new file mode 100644
index 0000000000..6c5ea9d8ac
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/functions/builtin/part2/BuiltinRaJoinTest.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysds.test.functions.builtin.part2;
+
+import org.apache.sysds.common.Types.ExecMode;
+import org.apache.sysds.runtime.matrix.data.MatrixValue.CellIndex;
+import org.apache.sysds.test.AutomatedTestBase;
+import org.apache.sysds.test.TestConfiguration;
+import org.apache.sysds.test.TestUtils;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class BuiltinRaJoinTest extends AutomatedTestBase
+{
+       private final static String TEST_NAME = "raJoin";
+       private final static String TEST_DIR = "functions/builtin/";
+       private static final String TEST_CLASS_DIR = TEST_DIR + 
BuiltinRaJoinTest.class.getSimpleName() + "/";
+       private final static double eps = 1e-8;
+       
+       @Override
+       public void setUp() {
+               addTestConfiguration(TEST_NAME,new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME,new String[]{"result"}));
+       }
+
+       @Test
+       public void testRaJoinTest() {
+               //generate actual dataset and variables
+               double[][] A = {
+                               {1, 2, 3},
+                               {4, 7, 8},
+                               {1, 3, 6},
+                               {4, 3, 5},
+                               {5, 8, 9}
+               };
+               double[][] B = {
+                               {1, 2, 9},
+                               {3, 7, 6},
+                               {2, 8, 5},
+                               {4, 7, 8},
+                               {4, 5, 10}
+               };
+               int colA = 1;
+               int colB = 1;
+
+               // Expected output matrix
+               double[][] Y = {
+                               {1, 2, 3, 1, 2, 9},
+                               {4, 7, 8, 4, 7, 8},
+                               {4, 7, 8, 4, 5, 10},
+                               {1, 3, 6, 1, 2, 9},
+                               {4, 3, 5, 4, 7, 8},
+                               {4, 3, 5, 4, 5, 10},
+               };
+               runRaJoinTest(A, colA, B, colB, Y);
+       }
+
+       @Test
+       public void testRaJoinTestwithDifferentColumn() {
+               // Generate actual dataset and variables
+               double[][] A = {
+                               {1, 5, 3},
+                               {2, 6, 8},
+                               {3, 7, 6},
+                               {4, 8, 5},
+                               {5, 9, 9}
+               };
+               double[][] B = {
+                               {1, 9, 2},
+                               {2, 8, 7},
+                               {3, 7, 6},
+                               {4, 5, 4},
+                               {5, 6, 1}
+               };
+               int colA = 2;
+               int colB = 3;
+
+               // Expected output matrix
+               double[][] Y = {
+                               {2, 6, 8, 3, 7, 6},
+                               {3, 7, 6, 2, 8, 7}
+               };
+               runRaJoinTest(A, colA, B, colB, Y);
+       }
+
+       @Test
+       public void testRaJoinTestwithDifferentColumn2() {
+               // Generate actual dataset and variables
+               double[][] A = {
+                               {1, 2, 3, 4, 5},
+                               {6, 7, 8, 9, 10},
+                               {11, 12, 13, 14, 15},
+                               {16, 17, 18, 19, 20},
+                               {21, 22, 23, 24, 25}
+               };
+               double[][] B = {
+                               {3, 5, 100},
+                               {1, 10, 200},
+                               {50, 25, 500}
+               };
+               int colA = 5; // Joining on the 5th column of A
+               int colB = 2; // Joining on the 1st column of B
+
+               // Expected output matrix
+               double[][] Y = {
+                               {1, 2, 3, 4, 5, 3, 5, 100},
+                               {6, 7, 8, 9, 10, 1, 10, 200},
+                               {21, 22, 23, 24, 25, 50, 25, 500}
+               };
+               runRaJoinTest(A, colA, B, colB, Y);
+       }
+
+       @Test
+       public void testRaJoinTestwithNoMatchingRows() {
+               // Generate actual dataset and variables
+               double[][] A = {
+                               {1, 2, 3},
+                               {2, 3, 4},
+                               {3, 4, 5}
+               };
+               double[][] B = {
+                               {4, 5, 6},
+                               {5, 6, 7},
+                               {6, 7, 8}
+               };
+               int colA = 1;
+               int colB = 1;
+
+               // Expected output matrix (no matching rows)
+               double[][] Y = {};
+               runRaJoinTest(A, colA, B, colB, Y);
+       }
+
+       @Test
+       public void testRaJoinTestwithAllMatchingRows() {
+               // Generate actual dataset and variables
+               double[][] A = {
+                               {1, 2, 3},
+                               {2, 3, 4},
+                               {3, 4, 5}
+               };
+               double[][] B = {
+                               {1, 2, 6},
+                               {2, 3, 7},
+                               {3, 4, 8}
+               };
+               int colA = 1;
+               int colB = 1;
+
+               // Expected output matrix (all rows match)
+               double[][] Y = {
+                               {1, 2, 3, 1, 2, 6},
+                               {2, 3, 4, 2, 3, 7},
+                               {3, 4, 5, 3, 4, 8}
+               };
+               runRaJoinTest(A, colA, B, colB, Y);
+       }
+
+       private void runRaJoinTest(double [][] A, int colA, double [][] B, int 
colB, double [][] Y)
+       {
+               ExecMode platformOld = setExecMode(ExecMode.SINGLE_NODE);
+               
+               try
+               {
+                       loadTestConfiguration(getTestConfiguration(TEST_NAME));
+                       String HOME = SCRIPT_DIR + TEST_DIR;
+
+                       fullDMLScriptName = HOME + TEST_NAME + ".dml";
+                       programArgs = new String[]{"-stats", "-args",
+                               input("A"), String.valueOf(colA), input("B"), 
String.valueOf(colB), output("result") };
+                       System.out.println(Arrays.deepToString(A));
+                       System.out.println(colA);
+                       //fullRScriptName = HOME + TEST_NAME + ".R";
+                       //rCmd = "Rscript" + " " + fullRScriptName + " "
+                       //      + inputDir() + " " + col + " "  + expectedDir();
+
+                       writeInputMatrixWithMTD("A", A, true);
+                       writeInputMatrixWithMTD("B", B, true);
+
+                       // run dmlScript and RScript
+                       runTest(true, false, null, -1);
+                       //runRScript(true);
+
+                       //compare matrices
+                       HashMap<CellIndex, Double> dmlfile = 
readDMLMatrixFromOutputDir("result");
+                       HashMap<CellIndex, Double> expectedOutput = 
TestUtils.convert2DDoubleArrayToHashMap(Y);
+                       //HashMap<CellIndex, Double> rfile  = 
readRMatrixFromExpectedDir("result");
+                       TestUtils.compareMatrices(dmlfile, expectedOutput, eps, 
"Stat-DML", "Expected");
+               }
+               finally {
+                       rtplatform = platformOld;
+               }
+       }
+}
diff --git a/src/test/scripts/functions/builtin/raGroupby.dml 
b/src/test/scripts/functions/builtin/raGroupby.dml
new file mode 100644
index 0000000000..b93f9add14
--- /dev/null
+++ b/src/test/scripts/functions/builtin/raGroupby.dml
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = read($1)
+col = as.integer($2)
+
+result = raGroupby(X, col, "nested-loop");
+write(result, $3);
+print(toString(result))
+
diff --git a/src/test/scripts/functions/builtin/raJoin.dml 
b/src/test/scripts/functions/builtin/raJoin.dml
new file mode 100644
index 0000000000..08483b8ea8
--- /dev/null
+++ b/src/test/scripts/functions/builtin/raJoin.dml
@@ -0,0 +1,29 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+A= read($1)
+colA = as.integer($2)
+B = read($3)
+colB = as.integer($4)
+
+result = raJoin(A, colA, B, colB, "nested-loop");
+write(result, $5);
+

Reply via email to