This is a follow-up to https://github.com/payloadcms/payload/pull/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 https://github.com/payloadcms/payload/pull/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
97 lines
2.3 KiB
TypeScript
97 lines
2.3 KiB
TypeScript
import type { LibSQLDatabase } from 'drizzle-orm/libsql'
|
|
import type { UpdateOne } from 'payload'
|
|
|
|
import toSnakeCase from 'to-snake-case'
|
|
|
|
import type { DrizzleAdapter } from './types.js'
|
|
|
|
import { buildQuery } from './queries/buildQuery.js'
|
|
import { selectDistinct } from './queries/selectDistinct.js'
|
|
import { upsertRow } from './upsertRow/index.js'
|
|
import { getTransaction } from './utilities/getTransaction.js'
|
|
|
|
export const updateOne: UpdateOne = async function updateOne(
|
|
this: DrizzleAdapter,
|
|
{
|
|
id,
|
|
collection: collectionSlug,
|
|
data,
|
|
joins: joinQuery,
|
|
locale,
|
|
options = { upsert: false },
|
|
req,
|
|
returning,
|
|
select,
|
|
where: whereArg,
|
|
},
|
|
) {
|
|
const db = await getTransaction(this, req)
|
|
const collection = this.payload.collections[collectionSlug].config
|
|
const tableName = this.tableNameMap.get(toSnakeCase(collection.slug))
|
|
let idToUpdate = id
|
|
|
|
if (!idToUpdate) {
|
|
const { joins, selectFields, where } = buildQuery({
|
|
adapter: this,
|
|
fields: collection.flattenedFields,
|
|
locale,
|
|
tableName,
|
|
where: whereArg,
|
|
})
|
|
|
|
// selectDistinct will only return if there are joins
|
|
const selectDistinctResult = await selectDistinct({
|
|
adapter: this,
|
|
db,
|
|
joins,
|
|
query: ({ query }) => query.limit(1),
|
|
selectFields,
|
|
tableName,
|
|
where,
|
|
})
|
|
|
|
if (selectDistinctResult?.[0]?.id) {
|
|
idToUpdate = selectDistinctResult?.[0]?.id
|
|
// If id wasn't passed but `where` without any joins, retrieve it with findFirst
|
|
} else if (whereArg && !joins.length) {
|
|
const table = this.tables[tableName]
|
|
|
|
const docsToUpdate = await (db as LibSQLDatabase)
|
|
.select({
|
|
id: table.id,
|
|
})
|
|
.from(table)
|
|
.where(where)
|
|
.limit(1)
|
|
idToUpdate = docsToUpdate?.[0]?.id
|
|
}
|
|
}
|
|
|
|
if (!idToUpdate && !options.upsert) {
|
|
// TODO: In 4.0, if returning === false, we should differentiate between:
|
|
// - No document found to update
|
|
// - Document found, but returning === false
|
|
return null
|
|
}
|
|
|
|
const result = await upsertRow({
|
|
id: idToUpdate,
|
|
adapter: this,
|
|
data,
|
|
db,
|
|
fields: collection.flattenedFields,
|
|
ignoreResult: returning === false,
|
|
joinQuery,
|
|
operation: 'update',
|
|
req,
|
|
select,
|
|
tableName,
|
|
})
|
|
|
|
if (returning === false) {
|
|
return null
|
|
}
|
|
|
|
return result
|
|
}
|