Optimize conditional uniqueness rules to partial unique indexes#316
Optimize conditional uniqueness rules to partial unique indexes#316thgreasi wants to merge 1 commit into
Conversation
323d546 to
2ea06f7
Compare
90c06d3 to
071fcd6
Compare
071fcd6 to
da3da0e
Compare
|
Removed es-toolkit |
| booleanNode[1][0] === 'ReferencedField' && | ||
| booleanNode[2][0] === 'ReferencedField'; |
There was a problem hiding this comment.
| booleanNode[1][0] === 'ReferencedField' && | |
| booleanNode[2][0] === 'ReferencedField'; | |
| isReferencedFieldNode(booleanNode[1]) && | |
| isReferencedFieldNode(booleanNode[2]); |
| if (fromNode[1][0] !== 'Alias') { | ||
| return; | ||
| } | ||
| if (fromNode[1][1][0] !== 'Table') { |
There was a problem hiding this comment.
| if (fromNode[1][1][0] !== 'Table') { | |
| if (!isTableNode(fromNode[1][1])) { |
| }; | ||
|
|
||
| function extractTableAndAlias(fromNode: FromNode) { | ||
| if (fromNode[1][0] !== 'Alias') { |
There was a problem hiding this comment.
| if (fromNode[1][0] !== 'Alias') { | |
| if (!isAliasNode(fromNode[1])) { |
11d170e to
a1e7407
Compare
| ) { | ||
| const outerSelectQuery = ruleBody[1]; | ||
| // Check if the query is of one of the following forms: | ||
| const queryChecksAbsenseOfRows = |
There was a problem hiding this comment.
| const queryChecksAbsenseOfRows = | |
| const queryChecksAbsenceOfRows = |
| * ) >= 2 | ||
| * ) = 0 AS "result"; | ||
| */ | ||
| function convertRuleToPartialUniqueIndex( |
There was a problem hiding this comment.
I think at this point it's probably worth creating a separate file to host individual optimizations (eg schema-optimizations/partial-unique-index.ts) with a shared code folder as well, since reviewing this PR has been very tricky and that's whilst being able to see the things related to this optimization in isolation, looking at it later when it's mixed in with other optimizations would make it even even harder which I don't want to imagine trying
a1e7407 to
fd2e2f9
Compare
fd2e2f9 to
9b9590f
Compare
9b9590f to
35eaa60
Compare
| return result; | ||
| } | ||
|
|
||
| export const convertReferencedFieldsToFields = (nodes: AbstractSqlType[]) => { |
There was a problem hiding this comment.
Moved as is from src/abstract-sql-schema-optimizer.ts
There was a problem hiding this comment.
Extracted mostly as is from src/abstract-sql-schema-optimizer.ts
0093b33 to
524e13e
Compare
| return result; | ||
| } | ||
|
|
||
| export const convertReferencedFieldsToFields = (nodes: AbstractSqlType[]) => { |
There was a problem hiding this comment.
Seeing this now makes me realize it should probably accept a table name to strip explicit references for, as a safety measure in case the ReferencedField is referencing something we don't expect
|
|
||
| // Find on the outer FROM the table matching the one in the inner FROM | ||
| const tableWithUniquenessCheck = nestedFromInfo.tableName; | ||
| const [targetTableInfos, parentTableInfos] = partition( |
There was a problem hiding this comment.
Can this/other cases like this become
| const [targetTableInfos, parentTableInfos] = partition( | |
| const { true: targetTableInfos, false: parentTableInfos } = groupBy( |
?
There was a problem hiding this comment.
That's how I had it initially, but at the end a didn't like how it looked in the already complex code and wanted to automatically do the ?? [], so that we can have simpler checks from that point onward.
But that's pretty much how I implemented partition() it in utils.ts.
If you insist I can inline it, but I prefer not to, to keep the sources simpler.
There was a problem hiding this comment.
Oh, more importantly!!!
Having a dedicated partition allowed me to use any return type assertions that the provided fn does, to automatically narrow down the typing of the true group.
export function partition<T, U extends T>(
entries: T[],
iteratee: (item: T) => item is U,
): [U[], T[]];| const result: BooleanTypeNodes[] = []; | ||
| for (const n of nodes) { | ||
| if (Array.isArray(n) && n[0] === 'Exists' && Array.isArray(n[1])) { | ||
| const maybeFieldTypeNode = n[1]; | ||
| const fieldName = | ||
| isReferencedFieldNode(maybeFieldTypeNode) && | ||
| maybeFieldTypeNode[1] === resourceAlias | ||
| ? maybeFieldTypeNode[2] | ||
| : undefined; | ||
| if ( | ||
| typeof fieldName === 'string' && | ||
| fieldsByFieldName[fieldName]?.required === true | ||
| ) { | ||
| continue; | ||
| } | ||
| } | ||
| result.push(n); | ||
| } | ||
| return result; |
There was a problem hiding this comment.
Maybe I'm missing something but I think this can be:
| const result: BooleanTypeNodes[] = []; | |
| for (const n of nodes) { | |
| if (Array.isArray(n) && n[0] === 'Exists' && Array.isArray(n[1])) { | |
| const maybeFieldTypeNode = n[1]; | |
| const fieldName = | |
| isReferencedFieldNode(maybeFieldTypeNode) && | |
| maybeFieldTypeNode[1] === resourceAlias | |
| ? maybeFieldTypeNode[2] | |
| : undefined; | |
| if ( | |
| typeof fieldName === 'string' && | |
| fieldsByFieldName[fieldName]?.required === true | |
| ) { | |
| continue; | |
| } | |
| } | |
| result.push(n); | |
| } | |
| return result; | |
| return nodes.map((n) => { | |
| if (!Array.isArray(n) && n[0] === 'Exists' && Array.isArray(n[1])) { | |
| const maybeFieldTypeNode = n[1]; | |
| const fieldName = | |
| isReferencedFieldNode(maybeFieldTypeNode) && | |
| maybeFieldTypeNode[1] === resourceAlias | |
| ? maybeFieldTypeNode[2] | |
| : undefined; | |
| if ( | |
| typeof fieldName === 'string' && | |
| fieldsByFieldName[fieldName]?.required === true | |
| ) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }); |
(with further simplification via changing where the returns are, but I left it as similar to current as possible for the example)
There was a problem hiding this comment.
I guess you mean .filter() instead of .map() and you also accidentally added a ! in from of the Array.isArray(n), right?
Yes it seems so 👍
524e13e to
a07b7f5
Compare
a07b7f5 to
02a6692
Compare
… indexes Change-type: minor See: https://balena.fibery.io/Work/Project/961
02a6692 to
116cc78
Compare
Change-type: minor
See: https://balena.fibery.io/Work/Project/961