Skip to content

Commit 7cd682c

Browse files
authored
perf(drizzle): further optimize postgres row updates (#13184)
This is a follow-up to #13060. There are a bunch of other db adapter methods that use `upsertRow` for updates: `updateGlobal`, `updateGlobalVersion`, `updateJobs`, `updateMany`, `updateVersion`. The previous PR had the logic for using the optimized row updating logic inside the `updateOne` adapter. This PR moves that logic to the original `upsertRow` function. Benefits: - all the other db methods will benefit from this massive optimization as well. This will be especially relevant for optimizing postgres job queue initial updates - we should be able to close #11865 after another follow-up PR - easier to read db adapter methods due to less code. --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1210803039809810
1 parent be8e8d9 commit 7cd682c

File tree

4 files changed

+484
-461
lines changed

4 files changed

+484
-461
lines changed

packages/drizzle/src/updateOne.ts

Lines changed: 9 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,15 @@
11
import type { LibSQLDatabase } from 'drizzle-orm/libsql'
2-
import type { FlattenedField, UpdateOne } from 'payload'
2+
import type { UpdateOne } from 'payload'
33

4-
import { eq } from 'drizzle-orm'
54
import toSnakeCase from 'to-snake-case'
65

76
import type { DrizzleAdapter } from './types.js'
87

9-
import { buildFindManyArgs } from './find/buildFindManyArgs.js'
108
import { buildQuery } from './queries/buildQuery.js'
119
import { selectDistinct } from './queries/selectDistinct.js'
12-
import { transform } from './transform/read/index.js'
13-
import { transformForWrite } from './transform/write/index.js'
1410
import { upsertRow } from './upsertRow/index.js'
1511
import { getTransaction } from './utilities/getTransaction.js'
1612

17-
/**
18-
* Checks whether we should use the upsertRow function for the passed data and otherwise use a simple SQL SET call.
19-
* We need to use upsertRow only when the data has arrays, blocks, hasMany select/text/number, localized fields, complex relationships.
20-
*/
21-
const shouldUseUpsertRow = ({
22-
data,
23-
fields,
24-
}: {
25-
data: Record<string, unknown>
26-
fields: FlattenedField[]
27-
}) => {
28-
for (const key in data) {
29-
const value = data[key]
30-
const field = fields.find((each) => each.name === key)
31-
32-
if (!field) {
33-
continue
34-
}
35-
36-
if (
37-
field.type === 'array' ||
38-
field.type === 'blocks' ||
39-
((field.type === 'text' ||
40-
field.type === 'relationship' ||
41-
field.type === 'upload' ||
42-
field.type === 'select' ||
43-
field.type === 'number') &&
44-
field.hasMany) ||
45-
((field.type === 'relationship' || field.type === 'upload') &&
46-
Array.isArray(field.relationTo)) ||
47-
field.localized
48-
) {
49-
return true
50-
}
51-
52-
if (
53-
(field.type === 'group' || field.type === 'tab') &&
54-
value &&
55-
typeof value === 'object' &&
56-
shouldUseUpsertRow({ data: value as Record<string, unknown>, fields: field.flattenedFields })
57-
) {
58-
return true
59-
}
60-
}
61-
62-
return false
63-
}
64-
6513
export const updateOne: UpdateOne = async function updateOne(
6614
this: DrizzleAdapter,
6715
{
@@ -126,72 +74,23 @@ export const updateOne: UpdateOne = async function updateOne(
12674
return null
12775
}
12876

129-
if (!idToUpdate || shouldUseUpsertRow({ data, fields: collection.flattenedFields })) {
130-
const result = await upsertRow({
131-
id: idToUpdate,
132-
adapter: this,
133-
data,
134-
db,
135-
fields: collection.flattenedFields,
136-
ignoreResult: returning === false,
137-
joinQuery,
138-
operation: 'update',
139-
req,
140-
select,
141-
tableName,
142-
})
143-
144-
if (returning === false) {
145-
return null
146-
}
147-
148-
return result
149-
}
150-
151-
const { row } = transformForWrite({
77+
const result = await upsertRow({
78+
id: idToUpdate,
15279
adapter: this,
15380
data,
154-
enableAtomicWrites: true,
81+
db,
15582
fields: collection.flattenedFields,
83+
ignoreResult: returning === false,
84+
joinQuery,
85+
operation: 'update',
86+
req,
87+
select,
15688
tableName,
15789
})
15890

159-
const drizzle = db as LibSQLDatabase
160-
await drizzle
161-
.update(this.tables[tableName])
162-
.set(row)
163-
// TODO: we can skip fetching idToUpdate here with using the incoming where
164-
.where(eq(this.tables[tableName].id, idToUpdate))
165-
16691
if (returning === false) {
16792
return null
16893
}
16994

170-
const findManyArgs = buildFindManyArgs({
171-
adapter: this,
172-
depth: 0,
173-
fields: collection.flattenedFields,
174-
joinQuery: false,
175-
select,
176-
tableName,
177-
})
178-
179-
findManyArgs.where = eq(this.tables[tableName].id, idToUpdate)
180-
181-
const doc = await db.query[tableName].findFirst(findManyArgs)
182-
183-
// //////////////////////////////////
184-
// TRANSFORM DATA
185-
// //////////////////////////////////
186-
187-
const result = transform({
188-
adapter: this,
189-
config: this.payload.config,
190-
data: doc,
191-
fields: collection.flattenedFields,
192-
joinQuery: false,
193-
tableName,
194-
})
195-
19695
return result
19796
}

0 commit comments

Comments
 (0)