ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
     // Start typing your C/C++ solution below
     // DO NOT write int main() function
     ListNode *head = NULL;
     ListNode *tail = NULL;
     ListNode *p1 = l1, *p2 = l2;
     while (p1 != NULL && p2 != NULL) {
         if (p1->val < p2->val) {
             tail = joinNode(tail, p1, &head);
             p1 = p1->next;
         } else {
             tail = joinNode(tail, p2, &head);
             p2 = p2->next;
         }
     }
     while (p1 != NULL) {
         tail = joinNode(tail, p1, &head);
         p1 = p1->next;
     }
     while (p2 != NULL) {
         tail = joinNode(tail, p2, &head);
         p2 = p2->next;
     }
     return head;
 }
status_t BSchemaRowIDJoin::JoinIterator::NextLocked(uint32_t flags, SValue* key, SValue* entry)
{
	SValue joinKey;

	// First retrieve columns from the join row.
	m_joinIterator->Owner()->Lock();
	status_t err = m_joinIterator->NextLocked(flags, &joinKey, entry);
	m_joinIterator->Owner()->Unlock();

	if (err != B_OK) return err;

	if (entry->IsObject()) flags &= ~INode::COLLAPSE_CATALOG;

	// Find the corresponding row id in the primary table.
	SNode node(*entry);
	SDatum rowIDDatum(node.Walk(m_owner->m_joinIDColumn));
	uint32_t rowID(rowIDDatum.FetchValue(4).AsInt32(&err));
	if (err != B_OK) return err;

	{
		SAutolock _l(m_primaryData->Table()->Lock());

		SString name(m_primaryData->Table()->EntryNameForLocked(rowID));
		name += "+";
		name += joinKey.AsString();
		*key = SValue::String(name);

		if ((flags & (INode::COLLAPSE_CATALOG|INode::REQUEST_DATA)) == (INode::COLLAPSE_CATALOG|INode::REQUEST_DATA)) {
			if (m_owner->m_primaryColumnName.Length() > 0) {
				if (m_includePrimaryNode) {
					if (m_primaryData->Table()->RowIDIsValidLocked(rowID)) {
						sptr<BSchemaTableNode::RowNode> priObj = m_primaryData->Table()->NodeForLocked(rowID);
						if (priObj != NULL) {
							entry->JoinItem(SValue::String(m_owner->m_primaryColumnName), SValue::Binder((BnNode*)priObj.ptr()));
						} else {
							err = B_NO_MEMORY;
						}
					}
				}
			} else {
				SValue priValue;
				err = m_primaryData->LoadDataLocked(rowID, flags, &priValue);
				if (err != B_OK) {
					entry->Join(priValue);
				}
			}
		} else {
			sptr<INode> joinNode(interface_cast<INode>(*entry));
			sptr<BSchemaTableNode::RowNode> priObj = m_primaryData->Table()->NodeForLocked(rowID);
			sptr<BSchemaTableNode::RowNode> joinObj = static_cast<BSchemaTableNode::RowNode*>(joinNode.ptr());
			sptr<RowNode> node;
			if (joinObj != NULL && priObj != NULL) {
				node = m_owner->NodeForLocked(priObj, joinObj);
				*entry = SValue::Binder((BnNode*)node.ptr());
			}
			if (node == NULL) err = B_NO_MEMORY;
		}

	}

	return err;
}