mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-03 14:52:21 +02:00
Add strLstMergeAnti() for merge anti-joins.
We deal with some pretty big lists in archive-push so a nested-loop anti-join looked like it would not be efficient enough. This merge anti-join should do the trick even though both lists must be sorted first.
This commit is contained in:
parent
538e2c7474
commit
abba2bd132
@ -93,6 +93,10 @@
|
||||
<p>Make <code>strLstDup()</code> null-tolerant.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>strLstMergeAnti()</code> for merge anti-joins.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>cvtSSizeToZ()</code> and debug macros.</p>
|
||||
</release-item>
|
||||
|
@ -472,6 +472,69 @@ strLstJoinQuote(const StringList *this, const char *separator, const char *quote
|
||||
FUNCTION_TEST_RETURN(join);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return all items in this list which are not in the anti list
|
||||
|
||||
The input lists must *both* be sorted or the results will be unpredictable.
|
||||
***********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstMergeAnti(const StringList *this, const StringList *anti)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, anti);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(anti != NULL);
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
result = strLstNew();
|
||||
unsigned int antiIdx = 0;
|
||||
|
||||
// Check every item in this
|
||||
for (unsigned int thisIdx = 0; thisIdx < strLstSize(this); thisIdx++)
|
||||
{
|
||||
bool add = true;
|
||||
const String *listItem = strLstGet(this, thisIdx);
|
||||
|
||||
// If anything left in anti look for matches
|
||||
while (antiIdx < strLstSize(anti))
|
||||
{
|
||||
int compare = strCmp(listItem, strLstGet(anti, antiIdx));
|
||||
|
||||
// If the current item in this is less than the current item in anti then it will be added
|
||||
if (compare < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// If they are equal it will not be added
|
||||
else if (compare == 0)
|
||||
{
|
||||
add = false;
|
||||
antiIdx++;
|
||||
break;
|
||||
}
|
||||
// Otherwise keep searching anti for a match
|
||||
else
|
||||
antiIdx++;
|
||||
}
|
||||
|
||||
// Add to the result list if no match found
|
||||
if (add)
|
||||
strLstAdd(result, listItem);
|
||||
}
|
||||
|
||||
strLstMove(result, MEM_CONTEXT_OLD());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Move the string list
|
||||
***********************************************************************************************************************************/
|
||||
|
@ -42,6 +42,7 @@ StringList *strLstInsertZ(StringList *this, unsigned int listIdx, const char *st
|
||||
String *strLstGet(const StringList *this, unsigned int listIdx);
|
||||
String *strLstJoin(const StringList *this, const char *separator);
|
||||
String *strLstJoinQuote(const StringList *this, const char *separator, const char *quote);
|
||||
StringList *strLstMergeAnti(const StringList *this, const StringList *anti);
|
||||
StringList * strLstMove(StringList *this, MemContext *parentNew);
|
||||
const char **strLstPtr(const StringList *this);
|
||||
unsigned int strLstSize(const StringList *this);
|
||||
|
@ -155,7 +155,7 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-string
|
||||
total: 25
|
||||
total: 26
|
||||
|
||||
coverage:
|
||||
common/type/string: full
|
||||
|
@ -396,6 +396,49 @@ testRun(void)
|
||||
strLstFree(list);
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strLstMergeAnti()"))
|
||||
{
|
||||
StringList *list = strLstNew();
|
||||
StringList *anti = strLstNew();
|
||||
|
||||
TEST_RESULT_STR(strPtr(strLstJoin(strLstMergeAnti(list, anti), ", ")), "", "list and anti empty");
|
||||
|
||||
strLstAddZ(anti, "item2");
|
||||
strLstAddZ(anti, "item3");
|
||||
|
||||
TEST_RESULT_STR(strPtr(strLstJoin(strLstMergeAnti(list, anti), ", ")), "", "list empty");
|
||||
|
||||
strLstAddZ(list, "item1");
|
||||
strLstAddZ(list, "item3");
|
||||
strLstAddZ(list, "item4");
|
||||
strLstAddZ(list, "item5");
|
||||
|
||||
TEST_RESULT_STR(strPtr(strLstJoin(strLstMergeAnti(list, anti), ", ")), "item1, item4, item5", "list results");
|
||||
|
||||
list = strLstNew();
|
||||
strLstAddZ(list, "item2");
|
||||
strLstAddZ(list, "item4");
|
||||
strLstAddZ(list, "item6");
|
||||
|
||||
anti = strLstNew();
|
||||
strLstAddZ(anti, "item1");
|
||||
strLstAddZ(anti, "item4");
|
||||
strLstAddZ(anti, "item7");
|
||||
|
||||
TEST_RESULT_STR(strPtr(strLstJoin(strLstMergeAnti(list, anti), ", ")), "item2, item6", "list results");
|
||||
|
||||
list = strLstNew();
|
||||
strLstAddZ(list, "item7");
|
||||
|
||||
anti = strLstNew();
|
||||
strLstAddZ(anti, "item1");
|
||||
strLstAddZ(anti, "item4");
|
||||
strLstAddZ(anti, "item6");
|
||||
|
||||
TEST_RESULT_STR(strPtr(strLstJoin(strLstMergeAnti(list, anti), ", ")), "item7", "list results");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strLstSort()"))
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user