-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #65 from AnyhowStep/tpt-update-and-fetch-one-by-ca…
…ndidate-key Tpt update and fetch one by candidate key
- Loading branch information
Showing
20 changed files
with
1,121 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
src/design-pattern-table-per-type/util/execution/absorb-row.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import {BuiltInExprUtil} from "../../../built-in-expr"; | ||
import {DataTypeUtil} from "../../../data-type"; | ||
import {ITable} from "../../../table"; | ||
|
||
/** | ||
* @todo Better name | ||
* | ||
* Adds properties from `row` to `result`. | ||
* | ||
* If a property from `row` already exists on `result`, | ||
* we use `table` to check if the values on both objects are equal. | ||
* | ||
* If they are not equal, an `Error` is thrown. | ||
*/ | ||
export function absorbRow ( | ||
result : Record<string, unknown>, | ||
table : ITable, | ||
row : Record<string, unknown> | ||
) { | ||
for (const columnAlias of Object.keys(row)) { | ||
/** | ||
* This is guaranteed to be a value expression. | ||
*/ | ||
const newValue = row[columnAlias]; | ||
|
||
if (Object.prototype.hasOwnProperty.call(result, columnAlias)) { | ||
/** | ||
* This `curValue` could be a non-value expression. | ||
* We only want value expressions. | ||
*/ | ||
const curValue = result[columnAlias]; | ||
|
||
if (BuiltInExprUtil.isAnyNonValueExpr(curValue)) { | ||
/** | ||
* Add this new value to the `result` | ||
* so we can use it to update rows of tables | ||
* further down the inheritance hierarchy. | ||
*/ | ||
result[columnAlias] = newValue; | ||
continue; | ||
} | ||
|
||
if (curValue === newValue) { | ||
/** | ||
* They are equal, do nothing. | ||
*/ | ||
continue; | ||
} | ||
/** | ||
* We need some custom equality checking logic | ||
*/ | ||
if (!DataTypeUtil.isNullSafeEqual( | ||
table.columns[columnAlias], | ||
/** | ||
* This may throw | ||
*/ | ||
table.columns[columnAlias].mapper( | ||
`${table.alias}.${columnAlias}`, | ||
curValue | ||
), | ||
newValue | ||
)) { | ||
/** | ||
* @todo Custom `Error` type | ||
*/ | ||
throw new Error(`All columns with the same name in an inheritance hierarchy must have the same value; mismatch found for ${table.alias}.${columnAlias}`); | ||
} | ||
} else { | ||
/** | ||
* Add this new value to the `result` | ||
* so we can use it to update rows of tables | ||
* further down the inheritance hierarchy. | ||
*/ | ||
result[columnAlias] = newValue; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
export * from "./fetch-one"; | ||
export * from "./insert-and-fetch"; | ||
export * from "./insert-row"; | ||
export * from "./update-and-fetch-one-by-candidate-key"; | ||
export * from "./update-and-fetch-one-impl"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
src/design-pattern-table-per-type/util/execution/invoke-assignment-delegate.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import {ITablePerType} from "../../table-per-type"; | ||
import {CustomAssignmentMap, AssignmentMapDelegate} from "./update-and-fetch-one-by-candidate-key"; | ||
import {IsolableSelectConnection, ExecutionUtil} from "../../../execution"; | ||
import {ColumnRefUtil} from "../../../column-ref"; | ||
import {ColumnUtil, ColumnArrayUtil} from "../../../column"; | ||
import {from, From} from "../execution-impl"; | ||
import {WhereDelegate} from "../../../where-clause"; | ||
import {isMutableColumnAlias, columnMapper} from "../query"; | ||
import {BuiltInExprUtil} from "../../../built-in-expr"; | ||
import {expr, ExprUtil} from "../../../expr"; | ||
import {DataTypeUtil} from "../../../data-type"; | ||
|
||
/** | ||
* Not meant to be called externally. | ||
* | ||
* @todo Better name | ||
*/ | ||
export async function invokeAssignmentDelegate< | ||
TptT extends ITablePerType, | ||
AssignmentMapT extends CustomAssignmentMap<TptT> | ||
> ( | ||
tpt : TptT, | ||
connection : IsolableSelectConnection, | ||
whereDelegate : WhereDelegate<From<TptT>["fromClause"]>, | ||
assignmentMapDelegate : AssignmentMapDelegate<TptT, AssignmentMapT> | ||
) : Promise<Record<string, unknown>> { | ||
const columns = ColumnRefUtil.fromColumnArray< | ||
ColumnUtil.FromColumnMap< | ||
| TptT["childTable"]["columns"] | ||
| TptT["parentTables"][number]["columns"] | ||
>[] | ||
>( | ||
ColumnArrayUtil.fromColumnMapArray< | ||
| TptT["childTable"]["columns"] | ||
| TptT["parentTables"][number]["columns"] | ||
>( | ||
[ | ||
tpt.childTable.columns, | ||
...tpt.parentTables.map(parentTable => parentTable.columns) | ||
] | ||
) | ||
); | ||
/** | ||
* May contain extra properties that are not mutable columns, | ||
* or even columns at all. | ||
*/ | ||
const rawAssignmentMap = assignmentMapDelegate(columns); | ||
|
||
const columnAliasArr = Object.keys(rawAssignmentMap); | ||
if (columnAliasArr.length == 0) { | ||
return {}; | ||
} | ||
|
||
const query = from(tpt) | ||
.where(whereDelegate as any) | ||
.select(() => columnAliasArr | ||
.filter(columnAlias => isMutableColumnAlias(tpt, columnAlias)) | ||
.map(columnAlias => { | ||
const customExpr = rawAssignmentMap[columnAlias as keyof typeof rawAssignmentMap] as any; | ||
if (BuiltInExprUtil.isAnyNonValueExpr(customExpr)) { | ||
/** | ||
* We have a non-value expression | ||
*/ | ||
return expr( | ||
{ | ||
mapper : DataTypeUtil.intersect( | ||
columnMapper(tpt, columnAlias), | ||
BuiltInExprUtil.mapper(customExpr) | ||
), | ||
usedRef : BuiltInExprUtil.usedRef(customExpr), | ||
}, | ||
BuiltInExprUtil.buildAst(customExpr) | ||
).as(columnAlias); | ||
} else { | ||
/** | ||
* We have a value expression | ||
*/ | ||
return ExprUtil.fromRawExprNoUsedRefInput( | ||
columnMapper(tpt, columnAlias), | ||
customExpr | ||
).as(columnAlias); | ||
} | ||
}) as any | ||
); | ||
/** | ||
* Should only contain value expressions now. | ||
*/ | ||
return ExecutionUtil.fetchOne( | ||
query as any, | ||
connection | ||
) as Promise<Record<string, unknown>>; | ||
} |
Oops, something went wrong.