u
This commit is contained in:
@@ -206,3 +206,37 @@ WHERE ca.category_id = @categoryId
|
|||||||
ORDER BY a.id ASC
|
ORDER BY a.id ASC
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const TOUCH_SUBTREE_CATEGORIES = `
|
||||||
|
;WITH cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
)
|
||||||
|
UPDATE category
|
||||||
|
SET updated_at = SYSUTCDATETIME()
|
||||||
|
WHERE id IN (SELECT id FROM cats)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TOUCH_SUBTREE_ARTICLES = `
|
||||||
|
;WITH cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
)
|
||||||
|
UPDATE article
|
||||||
|
SET updated_at = SYSUTCDATETIME()
|
||||||
|
WHERE id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
UNION
|
||||||
|
SELECT child.id FROM article child
|
||||||
|
WHERE child.parentarticle_id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
SELECT parent.parentarticle_id FROM article parent
|
||||||
|
WHERE parent.id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
) AND parent.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -129,4 +129,38 @@ FROM categoryarticle ca
|
|||||||
INNER JOIN article a ON a.id = ca.article_id
|
INNER JOIN article a ON a.id = ca.article_id
|
||||||
WHERE ca.category_id IN (SELECT id FROM tree)
|
WHERE ca.category_id IN (SELECT id FROM tree)
|
||||||
AND a.parentarticle_id IS NULL
|
AND a.parentarticle_id IS NULL
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TOUCH_SUBTREE_CATEGORIES = `
|
||||||
|
WITH RECURSIVE cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
)
|
||||||
|
UPDATE category
|
||||||
|
SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
||||||
|
WHERE id IN (SELECT id FROM cats)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const TOUCH_SUBTREE_ARTICLES = `
|
||||||
|
WITH RECURSIVE cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
)
|
||||||
|
UPDATE article
|
||||||
|
SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
||||||
|
WHERE id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
UNION
|
||||||
|
SELECT child.id FROM article child
|
||||||
|
WHERE child.parentarticle_id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
SELECT parent.parentarticle_id FROM article parent
|
||||||
|
WHERE parent.id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
) AND parent.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
`;
|
`;
|
||||||
@@ -2,11 +2,15 @@ import {
|
|||||||
GET_NEXT_SIBLING_SORT as MSSQL_GET_NEXT_SIBLING_SORT,
|
GET_NEXT_SIBLING_SORT as MSSQL_GET_NEXT_SIBLING_SORT,
|
||||||
IS_ANCESTOR as MSSQL_IS_ANCESTOR,
|
IS_ANCESTOR as MSSQL_IS_ANCESTOR,
|
||||||
MOVE as MSSQL_MOVE,
|
MOVE as MSSQL_MOVE,
|
||||||
|
TOUCH_SUBTREE_CATEGORIES as MSSQL_TOUCH_SUBTREE_CATEGORIES,
|
||||||
|
TOUCH_SUBTREE_ARTICLES as MSSQL_TOUCH_SUBTREE_ARTICLES,
|
||||||
} from '../../providers/mssql/queries/category.js';
|
} from '../../providers/mssql/queries/category.js';
|
||||||
import {
|
import {
|
||||||
GET_NEXT_SIBLING_SORT as SQLITE_GET_NEXT_SIBLING_SORT,
|
GET_NEXT_SIBLING_SORT as SQLITE_GET_NEXT_SIBLING_SORT,
|
||||||
IS_ANCESTOR as SQLITE_IS_ANCESTOR,
|
IS_ANCESTOR as SQLITE_IS_ANCESTOR,
|
||||||
MOVE as SQLITE_MOVE,
|
MOVE as SQLITE_MOVE,
|
||||||
|
TOUCH_SUBTREE_CATEGORIES as SQLITE_TOUCH_SUBTREE_CATEGORIES,
|
||||||
|
TOUCH_SUBTREE_ARTICLES as SQLITE_TOUCH_SUBTREE_ARTICLES,
|
||||||
} from '../../providers/sqlite3/queries/category.js';
|
} from '../../providers/sqlite3/queries/category.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -20,6 +24,12 @@ export default function move(provider) {
|
|||||||
? SQLITE_GET_NEXT_SIBLING_SORT
|
? SQLITE_GET_NEXT_SIBLING_SORT
|
||||||
: MSSQL_GET_NEXT_SIBLING_SORT;
|
: MSSQL_GET_NEXT_SIBLING_SORT;
|
||||||
const moveSql = isSqlite ? SQLITE_MOVE : MSSQL_MOVE;
|
const moveSql = isSqlite ? SQLITE_MOVE : MSSQL_MOVE;
|
||||||
|
const touchCategoriesSql = isSqlite
|
||||||
|
? SQLITE_TOUCH_SUBTREE_CATEGORIES
|
||||||
|
: MSSQL_TOUCH_SUBTREE_CATEGORIES;
|
||||||
|
const touchArticlesSql = isSqlite
|
||||||
|
? SQLITE_TOUCH_SUBTREE_ARTICLES
|
||||||
|
: MSSQL_TOUCH_SUBTREE_ARTICLES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a category to a new parent, preventing cycles and cross-company moves.
|
* Moves a category to a new parent, preventing cycles and cross-company moves.
|
||||||
@@ -70,6 +80,9 @@ export default function move(provider) {
|
|||||||
throw new Error('Category not found');
|
throw new Error('Category not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(touchCategoriesSql, { id });
|
||||||
|
await runner.query(touchArticlesSql, { id });
|
||||||
|
|
||||||
return { id, parentId, sort };
|
return { id, parentId, sort };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -225,6 +225,42 @@ describe('store.category', () => {
|
|||||||
/Not authorized|Parent not found/,
|
/Not authorized|Parent not found/,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('touches updated_at on moved category, subcategories, and associated articles', async () => {
|
||||||
|
const topTarget = await create('Move Target');
|
||||||
|
const movedCat = await create('Moved Cat');
|
||||||
|
const subCat = await create('Sub Cat', movedCat.id);
|
||||||
|
const artMoved = await createArticle(store, tenant, { parentId: movedCat.id, name: 'Article in Moved' });
|
||||||
|
const artSub = await createArticle(store, tenant, { parentId: subCat.id, name: 'Article in Sub' });
|
||||||
|
|
||||||
|
const oldDate = '2020-01-01T00:00:00.000Z';
|
||||||
|
await ctx.provider.query(
|
||||||
|
`UPDATE category SET updated_at = '${oldDate}' WHERE id IN (${movedCat.id}, ${subCat.id})`
|
||||||
|
);
|
||||||
|
await ctx.provider.query(
|
||||||
|
`UPDATE article SET updated_at = '${oldDate}' WHERE id IN (${artMoved.id}, ${artSub.id})`
|
||||||
|
);
|
||||||
|
|
||||||
|
await store.category.move({
|
||||||
|
googleAuthId: tenant.googleAuthId,
|
||||||
|
id: movedCat.id,
|
||||||
|
parentId: topTarget.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cats = await ctx.provider.query(
|
||||||
|
`SELECT id, updated_at FROM category WHERE id IN (${movedCat.id}, ${subCat.id})`
|
||||||
|
);
|
||||||
|
for (const row of cats.rows) {
|
||||||
|
assert.ok(new Date(row.updated_at) > new Date(oldDate), `Category ${row.id} updated_at was touched`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const arts = await ctx.provider.query(
|
||||||
|
`SELECT id, updated_at FROM article WHERE id IN (${artMoved.id}, ${artSub.id})`
|
||||||
|
);
|
||||||
|
for (const row of arts.rows) {
|
||||||
|
assert.ok(new Date(row.updated_at) > new Date(oldDate), `Article ${row.id} updated_at was touched`);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('order', () => {
|
describe('order', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user