-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different (incorrect) results for sortedMergeInnerJoin vs. hashInnerJoin #43
Comments
Hey @puddleglum56, thanks for the kind words and taking an interest in the library! I ran a test locally to check. If I'm reading this right, these two rows are producing the unexpected output.
You're right, I threw together a test and it definitely errors. describe('#43', () => {
const leftAccessor = (row: any) => {
return row["id"];
};
const rightAccessor = (row: any) => {
return row["id"];
};
const merger = (l: any, r: any): any => assign({}, l, r)
const left = [
{ id: 1, name: "John", sameColumn: "left", leftId: 1 },
{ id: 2, name: "Jane", sameColumn: "left", leftId: 2 },
{ id: "left", name: "Left", sameColumn: "left", leftId: "left" },
];
const right = [
{ id: 1, age: 20, sameColumn: "right", rightId: 1 },
{ id: 2, age: 30, sameColumn: "right", rightId: 2 },
{ id: "right", age: 1000, sameColumn: "right", rightId: "right" },
];
const result = joins.sortedMergeInnerJoin(left, leftAccessor, right, rightAccessor, merger);
const expected = [
{
id: 1,
name: 'John',
sameColumn: 'right',
leftId: 1,
age: 20,
rightId: 1
},
{
id: 2,
name: 'Jane',
sameColumn: 'right',
leftId: 2,
age: 30,
rightId: 2
}
];
it('should match the expected output', () =>
expect(result).toEqual(expected));
});
I wonder if this has to do with the sort or comparison of the const leftAccessor = (row: any) => {
return `${row["id"]}`;
};
const rightAccessor = (row: any) => {
return `${row["id"]}`;
}; I'll look into a bit further, but good find! |
I see why, it's caused by the mixture of numbers and strings as the key accessor. Comparisons on the keys are done using If I remember correctly, the expectation instead was using natural comparisons, if Let me think about a better way to perform comparisons when the types aren't the same. For now you could update the accessor to return strings always. const leftAccessor = (row: any) => {
return `${row["id"]}`;
};
const rightAccessor = (row: any) => {
return `${row["id"]}`;
}; The hash implementation works because it puts the keys into a dictionary, which coerces them to strings. The nested loop implementation also works because the |
Interesting as well, Lodash's sortBy function is used here to sort by the accessor prior to comparison. Seems if you return different types there, it also breaks the sort.
Notice the last example has unchanged order. Maybe converting the keys to strings and using localeCompare for both the sort and comparisons would work, but then I'm wondering if it's worth the change. Seems like you would want your keys to be the same domain/type. Is there a reason they aren't or a reason they can't be, to help produce a determinate sort? |
Hi @mtraynham, Thanks so much for looking into this. Sorry for the late reply. Ah, what you found makes sense! It hadn't even occurred to me that I was using different key types, it was just a random selection to help me write the tests. To answer your question, for my use case there is no reason to expect keys of different types. It seems that this is an extreme edge case that wouldn't really make sense in the real world. I will simply update my tests and switch back to sortedMerge join functions. Thank you again for your time and effort! |
Not a problem! I'll retain what's currently implemented, and added a caveat to the readme about this finding, https://github.com/mtraynham/lodash-joins#implementations. |
Hello!
Great library, very helpful to avoid having to implement SQL joins myself in Typescript. Smaller and easier to work with than AlaSQL.
Recently I was writing some tests for some joins I am doing with this library (installed via NPM) and found that sortedMergeInnerJoin is giving incorrect results.
Here is the code to reproduce:
This is producing:
, instead of expected:
It looks like the expected join is returned by hashInnerJoin.
The text was updated successfully, but these errors were encountered: