Skip to content
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

last-child move operation to update ancestor nodes #69

Merged
merged 5 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/giant-penguins-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"prisma-extension-bark": patch
---

Fix an issue in move operation where `numchild` fields were not always updated. ([Issue #68](https://github.com/adamjkb/bark/issues/68))
72 changes: 36 additions & 36 deletions packages/prisma-extension-bark/src/operations/move.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export default async function ({ node, where, position, reference }) {
* Variables
*/

let new_path
let new_depth = rn_node.depth
let new_pos = null
let siblings = []
Expand Down Expand Up @@ -141,7 +142,7 @@ export default async function ({ node, where, position, reference }) {
position === 'last-sibling' ||
(position === 'right' && rn_node.id === rn_last_sibling.id)) {
// Easy mode!
const new_path = increment_path(rn_last_sibling.path)
new_path = increment_path(rn_last_sibling.path)
await update_node_and_descendants({
old_path: original_node.path,
new_path,
Expand Down Expand Up @@ -188,7 +189,7 @@ export default async function ({ node, where, position, reference }) {
}
}

const new_path = path_from_depth({ path: rn_node.path, depth: new_depth - 1 }) + int2str(new_pos)
new_path = path_from_depth({ path: rn_node.path, depth: new_depth - 1 }) + int2str(new_pos)

// If the move is amongst siblings and is to the left and there
// are siblings to the right of its new position then to be on
Expand Down Expand Up @@ -216,17 +217,19 @@ export default async function ({ node, where, position, reference }) {
//(i.e.if we've got holes, allow them to compress)
let move_siblings = []
let prior_path = new_path
for (const node of siblings) {
// If the path of the node is already greater than the path
// of the previous node it doesn't need shifting
if (node.path > prior_path) {
continue
if (siblings?.length > 0) {
for (const node of siblings) {
// If the path of the node is already greater than the path
// of the previous node it doesn't need shifting
if (node.path > prior_path) {
continue
}
// It does need shifting, so add to the list
move_siblings.push(node)
// Calculate the path that it would be moved to, as that's
// the next "priorpath"
prior_path = increment_path(node.path)
}
// It does need shifting, so add to the list
move_siblings.push(node)
// Calculate the path that it would be moved to, as that's
// the next "priorpath"
prior_path = increment_path(node.path)
}
// Order of operation matters because we want to compress them
move_siblings.reverse()
Expand Down Expand Up @@ -270,27 +273,28 @@ export default async function ({ node, where, position, reference }) {
}


// Updating parent numchilds when original_node is changing depth
const original_parent_path = path_from_depth({ path: original_node.path, depth: original_node.depth - 1 })
const new_parent_path = path_from_depth({ path: new_path, depth: new_depth - 1 })
if (
(!original_parent_path && new_parent_path) ||
(original_parent_path && !new_parent_path) ||
(original_parent_path !== new_parent_path)
) {
if (original_parent_path) {
await ctx.update({
where: { path: original_parent_path },
data: { numchild: { decrement: 1 } }
})
}
}
// Updating parent numchilds when original_node is changing depth
const original_parent_path = path_from_depth({ path: original_node.path, depth: original_node.depth - 1 })
const new_parent_path = path_from_depth({ path: new_path, depth: new_depth - 1 })

if (new_parent_path) {
await ctx.update({
where: { path: new_parent_path },
data: { numchild: { increment: 1 } }
})
}
if (
(!original_parent_path && new_parent_path) ||
(original_parent_path && !new_parent_path) ||
(original_parent_path !== new_parent_path)
) {
if (original_parent_path) {
await ctx.update({
where: { path: original_parent_path },
data: { numchild: { decrement: 1 } }
})
}

if (new_parent_path) {
await ctx.update({
where: { path: new_parent_path },
data: { numchild: { increment: 1 } }
})
}
}
}
Expand All @@ -307,10 +311,6 @@ export default async function ({ node, where, position, reference }) {
/** @type {Promise<import('@prisma/client').Prisma.PrismaPromise<any>> | any[]}*/
const queue = []

// TODO: Ideally this would make use of transactions
// Issue is that Promise.all-ing a queue will lock SQLite but $transactions won't
// As a work-around we can set connection_limit=1
// https://github.com/prisma/prisma/issues?q=is%3Aissue+is%3Aopen+label%3A%22topic%3A+Timed+out+during+query+execution%22
queue.push(ctx.update({
where: { path: old_path },
data: {
Expand Down
6 changes: 6 additions & 0 deletions packages/prisma-extension-bark/test/operations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
get_b_a_node,
get_b_node,
get_c_node,
get_home_node,
prisma
} from './utilities/prisma'

Expand Down Expand Up @@ -176,9 +177,14 @@ describe('Operation: move(), Position: last-child', async () => {
it('last-child — depth move, descendants', async () => {
const node = await get_b_node()
const reference_node = await get_a_node()
const home_node = await get_home_node()

await prisma.node.move({ node: node, position: 'last-child', reference: { node: reference_node } })

const result_home_node = await get_home_node()
expect(result_home_node).toMatchObject({ depth: home_node.depth, numchild: home_node.numchild - 1 })
const result_reference_node = await get_a_node()
expect(result_reference_node).toMatchObject({ depth: reference_node.depth, numchild: reference_node.numchild + 1 })
const result = await get_b_node()
expect(result).toMatchObject({ path: '0001000100010006', depth: node.depth + 1, numchild: node.numchild })
const result_child = await get_b_a_node()
Expand Down