diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d81da2eeff7a188dad1a3829ee770a988c70de9..369555f5458b664c8203bb07cdc5fd9419094761 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 # Version 1.4.0 (not yet released)
 
-* Search tasks (eg. Export) work with Member,Contribute,Participant,Case... 
+* Search tasks (eg. Export) work with Member,Contribute,Participant,Case...
+* Added source to retrieve the owner membership, when owner membership is not set (meaning it is already the primary) then it will return itself.
 
 # Version 1.3.0
 
diff --git a/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php b/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php
index bd23d1e4bfd04019480937c6dbfdee7287c6bb3a..703fce83ff2cac2cc0987ea88eed860967ca3847 100644
--- a/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php
+++ b/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php
@@ -59,8 +59,8 @@ class SimpleNonRequiredJoin  extends  SimpleJoin {
    */
   public function getJoinClause(DataFlowDescription $sourceDataFlowDescription) {
     $this->initialize();
-    $joinClause = "";
-    if ($sourceDataFlowDescription->getJoinSpecification()) {
+    $joinClause = "ON 1";
+    if ($this->left_table && $this->right_table && $sourceDataFlowDescription->getJoinSpecification()) {
       $leftColumnName = "`{$this->left_table}`.`{$this->left_field}`";
       if ($this->leftFieldSpec) {
         $leftColumnName = $this->leftFieldSpec->getSqlColumnName($this->left_table);
diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php
index 12674738b2ddf70e6ed7fc640960c7f230e43c13..abbfe7716c974af7677bc45b2b0073f2251e1219 100644
--- a/Civi/DataProcessor/Factory.php
+++ b/Civi/DataProcessor/Factory.php
@@ -117,6 +117,7 @@ class Factory {
     $this->addDataSource('mailing_job', new Definition('Civi\DataProcessor\Source\Mailing\MailingJobSource'), E::ts('Mailing Job'));
     $this->addDataSource('mailing_group', new Definition('Civi\DataProcessor\Source\Mailing\MailingGroupSource'), E::ts('Mailing Group'));
     $this->addDataSource('membership', new Definition('Civi\DataProcessor\Source\Member\MembershipSource'), E::ts('Membership'));
+    $this->addDataSource('primary_membership', new Definition('Civi\DataProcessor\Source\Member\PrimaryMembershipSource'), E::ts('Primary Membership (retrieve the owner membership id'));
     $this->addDataSource('membership_type', new Definition('Civi\DataProcessor\Source\Member\MembershipTypeSource'), E::ts('Membership Type'));
     $this->addDataSource('membership_status', new Definition('Civi\DataProcessor\Source\Member\MembershipStatusSource'), E::ts('Membership Status'));
     $this->addDataSource('csv', new Definition('Civi\DataProcessor\Source\CSV'), E::ts('CSV File'));
diff --git a/Civi/DataProcessor/Source/Member/PrimaryMembershipSource.php b/Civi/DataProcessor/Source/Member/PrimaryMembershipSource.php
new file mode 100644
index 0000000000000000000000000000000000000000..3362fd86ff90064ad2b94aefadb46d7d4a1cac71
--- /dev/null
+++ b/Civi/DataProcessor/Source/Member/PrimaryMembershipSource.php
@@ -0,0 +1,167 @@
+<?php
+/**
+ * @author Jaap Jansma <jaap.jansma@civicoop.org>
+ * @license AGPL-3.0
+ */
+
+namespace Civi\DataProcessor\Source\Member;
+
+use Civi\DataProcessor\DataFlow\CombinedDataFlow\SubqueryDataFlow;
+use Civi\DataProcessor\DataFlow\MultipleDataFlows\DataFlowDescription;
+use Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleJoin;
+use Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleNonRequiredJoin;
+use Civi\DataProcessor\DataFlow\SqlDataFlow\AndClause;
+use Civi\DataProcessor\DataFlow\SqlDataFlow\OrClause;
+use Civi\DataProcessor\DataFlow\SqlDataFlow\PureSqlStatementClause;
+use Civi\DataProcessor\DataFlow\SqlDataFlow\SimpleWhereClause;
+use Civi\DataProcessor\DataFlow\SqlTableDataFlow;
+use Civi\DataProcessor\DataSpecification\DataSpecification;
+use Civi\DataProcessor\DataSpecification\FieldExistsException;
+use Civi\DataProcessor\DataSpecification\FieldSpecification;
+use Civi\DataProcessor\Source\AbstractSource;
+
+use CRM_Dataprocessor_ExtensionUtil as E;
+
+class PrimaryMembershipSource extends AbstractSource {
+
+  /**
+   * @var \Civi\DataProcessor\DataSpecification\DataSpecification
+   */
+  protected $availableFields;
+
+  /**
+   * @var \Civi\DataProcessor\DataSpecification\DataSpecification
+   */
+  protected $availableFilterFields;
+
+  /**
+   * @var SqlTableDataFlow
+   */
+  protected $primary_membership_data_flow;
+
+  /**
+   * @var SqlTableDataFlow
+   */
+  protected $membership_data_flow;
+
+  /**
+   * Initialize the join
+   *
+   * @return void
+   */
+  public function initialize() {
+    if (!$this->dataFlow) {
+      $this->primary_membership_data_flow = new SqlTableDataFlow('civicrm_membership', $this->getSourceName().'_primary_membership');
+      $this->membership_data_flow = new SqlTableDataFlow('civicrm_membership', $this->getSourceName().'_membership');
+
+      $joinClause = new OrClause();
+      $joinClause1 = new AndClause();
+      $joinClause1->addWhereClause(new SimpleWhereClause($this->membership_data_flow->getTableAlias(), 'owner_membership_id', 'IS NOT NULL', null, 'String', TRUE));
+      $joinClause1->addWhereClause(new PureSqlStatementClause("`{$this->primary_membership_data_flow->getTableAlias()}`.`id` = `{$this->membership_data_flow->getTableAlias()}`.`owner_membership_id`"));
+      $joinClause->addWhereClause($joinClause1);
+
+      $joinClause2 = new AndClause();
+      $joinClause2->addWhereClause(new SimpleWhereClause($this->membership_data_flow->getTableAlias(), 'owner_membership_id', 'IS NULL', null, 'String', TRUE));
+      $joinClause2->addWhereClause(new PureSqlStatementClause("`{$this->primary_membership_data_flow->getTableAlias()}`.`id` = `{$this->membership_data_flow->getTableAlias()}`.`id`"));
+      $joinClause->addWhereClause($joinClause2);
+
+      $join = new SimpleNonRequiredJoin(null, null, null, null, 'INNER');
+      $join->addFilterClause($joinClause);
+
+      $this->dataFlow = new SubqueryDataFlow($this->getSourceName(), 'civicrm_membership', $this->getSourceName());
+      $primaryMembershipDataFlowDescription = new DataFlowDescription($this->primary_membership_data_flow);
+      $this->dataFlow->addSourceDataFlow($primaryMembershipDataFlowDescription);
+      $memberShipDataFlowDescription = new DataFlowDescription($this->membership_data_flow, $join);
+      $this->dataFlow->addSourceDataFlow($memberShipDataFlowDescription);
+
+      try {
+        $this->primary_membership_data_flow->getDataSpecification()
+          ->addFieldSpecification('id', new FieldSpecification('id','Integer', E::ts('Primary Membership ID'), null, 'primary_membership_id'))
+          ->addFieldSpecification('contact_id', new FieldSpecification('contact_id','Integer', E::ts('Primary Membership Contact ID'), null, 'primary_membership_contact_id'));
+
+        $this->membership_data_flow->getDataSpecification()
+          ->addFieldSpecification('id', new FieldSpecification('id','Integer', E::ts('Membership ID'), null, 'membership_id'))
+          ->addFieldSpecification('contact_id', new FieldSpecification('contact_id','Integer', E::ts('Membership Contact ID'), null, 'membership_contact_id'));
+
+        /*$this->dataFlow->getDataSpecification()
+          ->addFieldSpecification('primary_membership_id', $this->getAvailableFields()
+            ->getFieldSpecificationByName('primary_membership_id'))
+          ->addFieldSpecification('primary_membership_contact_id', $this->getAvailableFields()
+            ->getFieldSpecificationByName('primary_membership_contact_id'))
+          ->addFieldSpecification('membership_id', $this->getAvailableFields()
+            ->getFieldSpecificationByName('membership_id'))
+          ->addFieldSpecification('membership_contact_id', $this->getAvailableFields()
+            ->getFieldSpecificationByName('membership_contact_id'));*/
+      } catch (\Exception $e) {
+        // Do nothing
+      }
+
+    }
+  }
+
+  /**
+   * @return \Civi\DataProcessor\DataSpecification\DataSpecification
+   * @throws \Exception
+   */
+  public function getAvailableFields() {
+    if (!$this->availableFields) {
+      $this->availableFields = new DataSpecification();
+      $this->loadFields($this->availableFields);
+    }
+    return $this->availableFields;
+  }
+
+  /**
+   * @return \Civi\DataProcessor\DataSpecification\DataSpecification
+   * @throws \Exception
+   */
+  public function getAvailableFilterFields() {
+    if (!$this->availableFilterFields) {
+      $this->availableFilterFields = new DataSpecification();
+      $this->loadFields($this->availableFilterFields);
+    }
+    return $this->availableFilterFields;
+  }
+
+  /**
+   * Add custom fields to the available fields section
+   *
+   * @param DataSpecification $dataSpecification
+   * @throws \Civi\DataProcessor\DataSpecification\FieldExistsException
+   * @throws \Exception
+   */
+  protected function loadFields(DataSpecification $dataSpecification) {
+    $dataSpecification->addFieldSpecification('primary_membership_id', new FieldSpecification('primary_membership_id','Integer', E::ts('Primary Membership ID'), null, $this->getSourceName().'_primary_membership_id'));
+    $dataSpecification->addFieldSpecification('membership_id', new FieldSpecification('membership_id','Integer', E::ts('Membership ID'), null, $this->getSourceName().'_membership_id'));
+    $dataSpecification->addFieldSpecification('primary_membership_contact_id', new FieldSpecification('primary_membership_contact_id','Integer', E::ts('Primary Membership Contact ID'), null, $this->getSourceName().'_primary_membership_contact_id'));
+    $dataSpecification->addFieldSpecification('membership_contact_id', new FieldSpecification('membership_contact_id','Integer', E::ts('Membership Contact ID'), null, $this->getSourceName().'_membership_contact_id'));
+  }
+
+  /**
+   * Ensures a field is in the data source
+   *
+   * @param \Civi\DataProcessor\DataSpecification\FieldSpecification $fieldSpecification
+   * @return \Civi\DataProcessor\Source\SourceInterface
+   * @throws \Exception
+   */
+  public function ensureFieldInSource(FieldSpecification $fieldSpecification) {
+    try {
+      $this->dataFlow->getDataSpecification()->addFieldSpecification($fieldSpecification->alias, $fieldSpecification);
+    } catch (FieldExistsException $e) {
+      // Do nothing.
+    }
+    return $this;
+  }
+
+  /**
+   * Ensure that filter field is accesible in the query
+   *
+   * @param FieldSpecification $field
+   * @return \Civi\DataProcessor\DataFlow\AbstractDataFlow|null
+   * @throws \Exception
+   */
+  public function ensureField(FieldSpecification $field) {
+    return $this->dataFlow;
+  }
+
+}