From 629d7c326387e95c0b7b706f53f679cbbfb7afff Mon Sep 17 00:00:00 2001 From: James Mikrut Date: Wed, 24 Apr 2024 22:42:24 -0400 Subject: [PATCH] fix(db-postgres): fully functional dbNames (#6023) --- packages/db-postgres/src/count.ts | 7 +- packages/db-postgres/src/create.ts | 10 +-- packages/db-postgres/src/createGlobal.ts | 10 +-- .../db-postgres/src/createGlobalVersion.ts | 9 +-- packages/db-postgres/src/createVersion.ts | 20 ++---- packages/db-postgres/src/deleteMany.ts | 5 +- packages/db-postgres/src/deleteOne.ts | 9 ++- packages/db-postgres/src/deleteVersions.ts | 11 ++- packages/db-postgres/src/destroy.ts | 1 - packages/db-postgres/src/find.ts | 9 ++- .../db-postgres/src/find/traverseFields.ts | 29 +++----- packages/db-postgres/src/findGlobal.ts | 9 ++- .../db-postgres/src/findGlobalVersions.ts | 11 ++- packages/db-postgres/src/findOne.ts | 9 ++- packages/db-postgres/src/findVersions.ts | 11 ++- packages/db-postgres/src/index.ts | 4 +- packages/db-postgres/src/init.ts | 16 +++-- .../src/queries/getTableColumnFromPath.ts | 69 +++++++------------ packages/db-postgres/src/queryDrafts.ts | 26 +++---- packages/db-postgres/src/schema/build.ts | 6 +- .../{getTableName.ts => createTableName.ts} | 45 +++++++----- .../db-postgres/src/schema/traverseFields.ts | 14 ++-- .../db-postgres/src/transform/write/array.ts | 1 + .../db-postgres/src/transform/write/blocks.ts | 2 +- .../src/transform/write/traverseFields.ts | 4 +- packages/db-postgres/src/types.ts | 5 +- packages/db-postgres/src/update.ts | 8 +-- packages/db-postgres/src/updateGlobal.ts | 8 +-- .../db-postgres/src/updateGlobalVersion.ts | 12 ++-- packages/db-postgres/src/updateVersion.ts | 11 ++- packages/db-postgres/src/upsertRow/index.ts | 11 +-- test/database/config.ts | 8 +++ test/database/int.spec.ts | 48 +++++++++++++ 33 files changed, 231 insertions(+), 227 deletions(-) rename packages/db-postgres/src/schema/{getTableName.ts => createTableName.ts} (55%) diff --git a/packages/db-postgres/src/count.ts b/packages/db-postgres/src/count.ts index caf38e3c51..0d64620246 100644 --- a/packages/db-postgres/src/count.ts +++ b/packages/db-postgres/src/count.ts @@ -2,13 +2,13 @@ import type { Count } from 'payload/database' import type { SanitizedCollectionConfig } from 'payload/types' import { sql } from 'drizzle-orm' +import toSnakeCase from 'to-snake-case' import type { ChainedMethods } from './find/chainMethods.js' import type { PostgresAdapter } from './types.js' import { chainMethods } from './find/chainMethods.js' import buildQuery from './queries/buildQuery.js' -import { getTableName } from './schema/getTableName.js' export const count: Count = async function count( this: PostgresAdapter, @@ -16,10 +16,7 @@ export const count: Count = async function count( ) { const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - }) + const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)) const db = this.sessions[req.transactionID]?.db || this.drizzle const table = this.tables[tableName] diff --git a/packages/db-postgres/src/create.ts b/packages/db-postgres/src/create.ts index df4ec9ac5c..177b7744b0 100644 --- a/packages/db-postgres/src/create.ts +++ b/packages/db-postgres/src/create.ts @@ -1,8 +1,9 @@ import type { Create } from 'payload/database' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export const create: Create = async function create( @@ -12,6 +13,8 @@ export const create: Create = async function create( const db = this.sessions[req.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config + const tableName = this.tableNameMap.get(toSnakeCase(collection.slug)) + const result = await upsertRow({ adapter: this, data, @@ -19,10 +22,7 @@ export const create: Create = async function create( fields: collection.fields, operation: 'create', req, - tableName: getTableName({ - adapter: this, - config: collection, - }), + tableName, }) return result diff --git a/packages/db-postgres/src/createGlobal.ts b/packages/db-postgres/src/createGlobal.ts index 952adb3186..a8f185c80c 100644 --- a/packages/db-postgres/src/createGlobal.ts +++ b/packages/db-postgres/src/createGlobal.ts @@ -1,9 +1,10 @@ import type { CreateGlobalArgs } from 'payload/database' import type { PayloadRequest, TypeWithID } from 'payload/types' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export async function createGlobal( @@ -13,6 +14,8 @@ export async function createGlobal( const db = this.sessions[req.transactionID]?.db || this.drizzle const globalConfig = this.payload.globals.config.find((config) => config.slug === slug) + const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug)) + const result = await upsertRow({ adapter: this, data, @@ -20,10 +23,7 @@ export async function createGlobal( fields: globalConfig.fields, operation: 'create', req, - tableName: getTableName({ - adapter: this, - config: globalConfig, - }), + tableName, }) return result diff --git a/packages/db-postgres/src/createGlobalVersion.ts b/packages/db-postgres/src/createGlobalVersion.ts index eaac120074..c3e2ad9705 100644 --- a/packages/db-postgres/src/createGlobalVersion.ts +++ b/packages/db-postgres/src/createGlobalVersion.ts @@ -4,10 +4,10 @@ import type { PayloadRequest, TypeWithID } from 'payload/types' import { sql } from 'drizzle-orm' import { type CreateGlobalVersionArgs } from 'payload/database' import { buildVersionGlobalFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export async function createGlobalVersion( @@ -16,11 +16,8 @@ export async function createGlobalVersion( ) { const db = this.sessions[req.transactionID]?.db || this.drizzle const global = this.payload.globals.config.find(({ slug }) => slug === globalSlug) - const tableName = getTableName({ - adapter: this, - config: global, - versions: true, - }) + + const tableName = this.tableNameMap.get(`_${toSnakeCase(global.slug)}${this.versionsSuffix}`) const result = await upsertRow>({ adapter: this, diff --git a/packages/db-postgres/src/createVersion.ts b/packages/db-postgres/src/createVersion.ts index d651ea141e..f130e8a7e1 100644 --- a/packages/db-postgres/src/createVersion.ts +++ b/packages/db-postgres/src/createVersion.ts @@ -3,10 +3,10 @@ import type { PayloadRequest, TypeWithID } from 'payload/types' import { sql } from 'drizzle-orm' import { buildVersionCollectionFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export async function createVersion( @@ -21,11 +21,9 @@ export async function createVersion( ) { const db = this.sessions[req.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config - const tableName = getTableName({ - adapter: this, - config: collection, - versions: true, - }) + const defaultTableName = toSnakeCase(collection.slug) + + const tableName = this.tableNameMap.get(`_${defaultTableName}${this.versionsSuffix}`) const result = await upsertRow>({ adapter: this, @@ -43,15 +41,9 @@ export async function createVersion( }) const table = this.tables[tableName] + const relationshipsTable = - this.tables[ - getTableName({ - adapter: this, - config: collection, - relationships: true, - versions: true, - }) - ] + this.tables[`_${defaultTableName}${this.versionsSuffix}${this.relationshipsSuffix}`] if (collection.versions.drafts) { await db.execute(sql` diff --git a/packages/db-postgres/src/deleteMany.ts b/packages/db-postgres/src/deleteMany.ts index a892b6ba3b..a0e326169d 100644 --- a/packages/db-postgres/src/deleteMany.ts +++ b/packages/db-postgres/src/deleteMany.ts @@ -2,11 +2,11 @@ import type { DeleteMany } from 'payload/database' import type { PayloadRequest } from 'payload/types' import { inArray } from 'drizzle-orm' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export const deleteMany: DeleteMany = async function deleteMany( this: PostgresAdapter, @@ -14,7 +14,8 @@ export const deleteMany: DeleteMany = async function deleteMany( ) { const db = this.sessions[req.transactionID]?.db || this.drizzle const collectionConfig = this.payload.collections[collection].config - const tableName = getTableName({ adapter: this, config: collectionConfig }) + + const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)) const result = await findMany({ adapter: this, diff --git a/packages/db-postgres/src/deleteOne.ts b/packages/db-postgres/src/deleteOne.ts index ade465129b..7f99424ee0 100644 --- a/packages/db-postgres/src/deleteOne.ts +++ b/packages/db-postgres/src/deleteOne.ts @@ -2,13 +2,13 @@ import type { DeleteOne } from 'payload/database' import type { PayloadRequest } from 'payload/types' import { eq } from 'drizzle-orm' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import { buildFindManyArgs } from './find/buildFindManyArgs.js' import buildQuery from './queries/buildQuery.js' import { selectDistinct } from './queries/selectDistinct.js' -import { getTableName } from './schema/getTableName.js' import { transform } from './transform/read/index.js' export const deleteOne: DeleteOne = async function deleteOne( @@ -17,10 +17,9 @@ export const deleteOne: DeleteOne = async function deleteOne( ) { const db = this.sessions[req.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config - const tableName = getTableName({ - adapter: this, - config: collection, - }) + + const tableName = this.tableNameMap.get(toSnakeCase(collection.slug)) + let docToDelete: Record const { joinAliases, joins, selectFields, where } = await buildQuery({ diff --git a/packages/db-postgres/src/deleteVersions.ts b/packages/db-postgres/src/deleteVersions.ts index c93b1e09a6..5f790daf1e 100644 --- a/packages/db-postgres/src/deleteVersions.ts +++ b/packages/db-postgres/src/deleteVersions.ts @@ -3,11 +3,11 @@ import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types' import { inArray } from 'drizzle-orm' import { buildVersionCollectionFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export const deleteVersions: DeleteVersions = async function deleteVersion( this: PostgresAdapter, @@ -16,11 +16,10 @@ export const deleteVersions: DeleteVersions = async function deleteVersion( const db = this.sessions[req.transactionID]?.db || this.drizzle const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - versions: true, - }) + const tableName = this.tableNameMap.get( + `_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`, + ) + const fields = buildVersionCollectionFields(collectionConfig) const { docs } = await findMany({ diff --git a/packages/db-postgres/src/destroy.ts b/packages/db-postgres/src/destroy.ts index 7fd89095a0..690bcd5de6 100644 --- a/packages/db-postgres/src/destroy.ts +++ b/packages/db-postgres/src/destroy.ts @@ -8,7 +8,6 @@ export const destroy: Destroy = async function destroy(this: PostgresAdapter) { this.schema = {} this.tables = {} this.relations = {} - this.blockTableNames = {} this.fieldConstraints = {} this.drizzle = undefined } diff --git a/packages/db-postgres/src/find.ts b/packages/db-postgres/src/find.ts index 62719c2763..fa339989c2 100644 --- a/packages/db-postgres/src/find.ts +++ b/packages/db-postgres/src/find.ts @@ -1,10 +1,11 @@ import type { Find } from 'payload/database' import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export const find: Find = async function find( this: PostgresAdapter, @@ -21,10 +22,8 @@ export const find: Find = async function find( ) { const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - }) + + const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)) return findMany({ adapter: this, diff --git a/packages/db-postgres/src/find/traverseFields.ts b/packages/db-postgres/src/find/traverseFields.ts index e4cdc070c0..b8503f31ee 100644 --- a/packages/db-postgres/src/find/traverseFields.ts +++ b/packages/db-postgres/src/find/traverseFields.ts @@ -2,12 +2,11 @@ import type { Field } from 'payload/types' import { fieldAffectsData, tabHasName } from 'payload/types' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from '../types.js' import type { Result } from './buildFindManyArgs.js' -import { getTableName } from '../schema/getTableName.js' - type TraverseFieldArgs = { _locales: Record adapter: PostgresAdapter @@ -79,20 +78,11 @@ export const traverseFields = ({ with: {}, } - const arrayTableName = getTableName({ - adapter, - config: field, - parentTableName: currentTableName, - prefix: `${currentTableName}_${path}`, - }) + const arrayTableName = adapter.tableNameMap.get( + `${currentTableName}_${path}${toSnakeCase(field.name)}`, + ) - const arrayTableNameWithLocales = getTableName({ - adapter, - config: field, - locales: true, - parentTableName: currentTableName, - prefix: `${currentTableName}_${path}`, - }) + const arrayTableNameWithLocales = `${arrayTableName}${adapter.localesSuffix}` if (adapter.tables[arrayTableNameWithLocales]) withArray.with._locales = _locales currentArgs.with[`${path}${field.name}`] = withArray @@ -142,12 +132,9 @@ export const traverseFields = ({ with: {}, } - const tableName = getTableName({ - adapter, - config: block, - parentTableName: topLevelTableName, - prefix: `${topLevelTableName}_blocks_`, - }) + const tableName = adapter.tableNameMap.get( + `${topLevelTableName}_blocks_${toSnakeCase(block.slug)}`, + ) if (adapter.tables[`${tableName}${adapter.localesSuffix}`]) { withBlock.with._locales = _locales diff --git a/packages/db-postgres/src/findGlobal.ts b/packages/db-postgres/src/findGlobal.ts index 360ba68639..261ad14a65 100644 --- a/packages/db-postgres/src/findGlobal.ts +++ b/packages/db-postgres/src/findGlobal.ts @@ -1,19 +1,18 @@ import type { FindGlobal } from 'payload/database' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export const findGlobal: FindGlobal = async function findGlobal( this: PostgresAdapter, { slug, locale, req, where }, ) { const globalConfig = this.payload.globals.config.find((config) => config.slug === slug) - const tableName = getTableName({ - adapter: this, - config: globalConfig, - }) + + const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug)) const { docs: [doc], diff --git a/packages/db-postgres/src/findGlobalVersions.ts b/packages/db-postgres/src/findGlobalVersions.ts index df49ed059b..0ee21b28cc 100644 --- a/packages/db-postgres/src/findGlobalVersions.ts +++ b/packages/db-postgres/src/findGlobalVersions.ts @@ -2,11 +2,11 @@ import type { FindGlobalVersions } from 'payload/database' import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types' import { buildVersionGlobalFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export const findGlobalVersions: FindGlobalVersions = async function findGlobalVersions( this: PostgresAdapter, @@ -27,11 +27,10 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV ) const sort = typeof sortArg === 'string' ? sortArg : '-createdAt' - const tableName = getTableName({ - adapter: this, - config: globalConfig, - versions: true, - }) + const tableName = this.tableNameMap.get( + `_${toSnakeCase(globalConfig.slug)}${this.versionsSuffix}`, + ) + const fields = buildVersionGlobalFields(globalConfig) return findMany({ diff --git a/packages/db-postgres/src/findOne.ts b/packages/db-postgres/src/findOne.ts index 938d739802..404e79e56a 100644 --- a/packages/db-postgres/src/findOne.ts +++ b/packages/db-postgres/src/findOne.ts @@ -1,20 +1,19 @@ import type { FindOneArgs } from 'payload/database' import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export async function findOne( this: PostgresAdapter, { collection, locale, req = {} as PayloadRequest, where }: FindOneArgs, ): Promise { const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - }) + + const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)) const { docs } = await findMany({ adapter: this, diff --git a/packages/db-postgres/src/findVersions.ts b/packages/db-postgres/src/findVersions.ts index caf7be8e4a..33f6f5c0b2 100644 --- a/packages/db-postgres/src/findVersions.ts +++ b/packages/db-postgres/src/findVersions.ts @@ -2,11 +2,11 @@ import type { FindVersions } from 'payload/database' import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types' import { buildVersionCollectionFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' export const findVersions: FindVersions = async function findVersions( this: PostgresAdapter, @@ -25,11 +25,10 @@ export const findVersions: FindVersions = async function findVersions( const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - versions: true, - }) + const tableName = this.tableNameMap.get( + `_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`, + ) + const fields = buildVersionCollectionFields(collectionConfig) return findMany({ diff --git a/packages/db-postgres/src/index.ts b/packages/db-postgres/src/index.ts index 8379b23a59..bd3d727c20 100644 --- a/packages/db-postgres/src/index.ts +++ b/packages/db-postgres/src/index.ts @@ -52,9 +52,6 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj return createDatabaseAdapter({ name: 'postgres', - - // Postgres-specific - blockTableNames: {}, drizzle: undefined, enums: {}, fieldConstraints: {}, @@ -70,6 +67,7 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj schema: {}, schemaName: args.schemaName, sessions: {}, + tableNameMap: new Map(), tables: {}, versionsSuffix: args.versionsSuffix || '_v', diff --git a/packages/db-postgres/src/init.ts b/packages/db-postgres/src/init.ts index 089762da1e..04fc09423e 100644 --- a/packages/db-postgres/src/init.ts +++ b/packages/db-postgres/src/init.ts @@ -8,7 +8,7 @@ import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/ import type { PostgresAdapter } from './types.js' import { buildTable } from './schema/build.js' -import { getTableName } from './schema/getTableName.js' +import { createTableName } from './schema/createTableName.js' export const init: Init = function init(this: PostgresAdapter) { if (this.schemaName) { @@ -25,7 +25,7 @@ export const init: Init = function init(this: PostgresAdapter) { } this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => { - const tableName = getTableName({ + const tableName = createTableName({ adapter: this, config: collection, }) @@ -44,10 +44,11 @@ export const init: Init = function init(this: PostgresAdapter) { }) if (collection.versions) { - const versionsTableName = getTableName({ + const versionsTableName = createTableName({ adapter: this, config: collection, versions: true, + versionsCustomName: true, }) const versionFields = buildVersionCollectionFields(collection) @@ -67,7 +68,7 @@ export const init: Init = function init(this: PostgresAdapter) { }) this.payload.config.globals.forEach((global) => { - const tableName = getTableName({ adapter: this, config: global }) + const tableName = createTableName({ adapter: this, config: global }) buildTable({ adapter: this, @@ -83,7 +84,12 @@ export const init: Init = function init(this: PostgresAdapter) { }) if (global.versions) { - const versionsTableName = getTableName({ adapter: this, config: global, versions: true }) + const versionsTableName = createTableName({ + adapter: this, + config: global, + versions: true, + versionsCustomName: true, + }) const versionFields = buildVersionGlobalFields(global) buildTable({ diff --git a/packages/db-postgres/src/queries/getTableColumnFromPath.ts b/packages/db-postgres/src/queries/getTableColumnFromPath.ts index 1133f167f4..1e236f2a0d 100644 --- a/packages/db-postgres/src/queries/getTableColumnFromPath.ts +++ b/packages/db-postgres/src/queries/getTableColumnFromPath.ts @@ -14,8 +14,6 @@ import { v4 as uuid } from 'uuid' import type { GenericColumn, GenericTable, PostgresAdapter } from '../types.js' import type { BuildQueryJoinAliases, BuildQueryJoins } from './buildQuery.js' -import { getTableName } from '../schema/getTableName.js' - type Constraint = { columnName: string table: GenericTable | PgTableWithColumns @@ -185,13 +183,7 @@ export const getTableColumnFromPath = ({ case 'group': { if (locale && field.localized && adapter.payload.config.localization) { - newTableName = getTableName({ - adapter, - config: field, - locales: true, - parentTableName: tableName, - prefix: `${tableName}_`, - }) + newTableName = `${tableName}${adapter.localesSuffix}` joins[tableName] = eq( adapter.tables[tableName].id, @@ -227,12 +219,9 @@ export const getTableColumnFromPath = ({ case 'select': { if (field.hasMany) { - newTableName = getTableName({ - adapter, - config: field, - parentTableName: `${tableName}_${tableNameSuffix}`, - prefix: `${tableName}_${tableNameSuffix}`, - }) + const newTableName = adapter.tableNameMap.get( + `${tableName}_${tableNameSuffix}${toSnakeCase(field.name)}`, + ) if (locale && field.localized && adapter.payload.config.localization) { joins[newTableName] = and( @@ -305,12 +294,10 @@ export const getTableColumnFromPath = ({ } case 'array': { - newTableName = getTableName({ - adapter, - config: field, - parentTableName: `${tableName}_${tableNameSuffix}`, - prefix: `${tableName}_${tableNameSuffix}`, - }) + newTableName = adapter.tableNameMap.get( + `${tableName}_${tableNameSuffix}${toSnakeCase(field.name)}`, + ) + constraintPath = `${constraintPath}${field.name}.%.` if (locale && field.localized && adapter.payload.config.localization) { joins[newTableName] = and( @@ -357,12 +344,11 @@ export const getTableColumnFromPath = ({ const blockTypes = Array.isArray(value) ? value : [value] blockTypes.forEach((blockType) => { const block = field.blocks.find((block) => block.slug === blockType) - newTableName = getTableName({ - adapter, - config: block, - parentTableName: tableName, - prefix: `${tableName}_blocks_`, - }) + + newTableName = adapter.tableNameMap.get( + `${tableName}_blocks_${toSnakeCase(block.slug)}`, + ) + joins[newTableName] = eq( adapter.tables[tableName].id, adapter.tables[newTableName]._parentID, @@ -382,13 +368,9 @@ export const getTableColumnFromPath = ({ } const hasBlockField = field.blocks.some((block) => { - newTableName = getTableName({ - adapter, - config: block, - parentTableName: tableName, - prefix: `${tableName}_blocks_`, - }) + newTableName = adapter.tableNameMap.get(`${tableName}_blocks_${toSnakeCase(block.slug)}`) constraintPath = `${constraintPath}${field.name}.%.` + let result const blockConstraints = [] const blockSelectFields = {} @@ -495,10 +477,9 @@ export const getTableColumnFromPath = ({ if (typeof field.relationTo === 'string') { const relationshipConfig = adapter.payload.collections[field.relationTo].config - newTableName = getTableName({ - adapter, - config: relationshipConfig, - }) + + newTableName = adapter.tableNameMap.get(toSnakeCase(relationshipConfig.slug)) + // parent to relationship join table relationshipFields = relationshipConfig.fields @@ -518,13 +499,13 @@ export const getTableColumnFromPath = ({ } } } else if (newCollectionPath === 'value') { - const tableColumnsNames = field.relationTo.map( - (relationTo) => - `"${aliasRelationshipTableName}"."${getTableName({ - adapter, - config: adapter.payload.collections[relationTo].config, - })}_id"`, - ) + const tableColumnsNames = field.relationTo.map((relationTo) => { + const relationTableName = adapter.tableNameMap.get( + toSnakeCase(adapter.payload.collections[relationTo].config.slug), + ) + + return `"${aliasRelationshipTableName}"."${relationTableName}_id"` + }) return { constraints, field, diff --git a/packages/db-postgres/src/queryDrafts.ts b/packages/db-postgres/src/queryDrafts.ts index 8012dd0c35..103285b085 100644 --- a/packages/db-postgres/src/queryDrafts.ts +++ b/packages/db-postgres/src/queryDrafts.ts @@ -2,26 +2,20 @@ import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types' import { type QueryDrafts, combineQueries } from 'payload/database' import { buildVersionCollectionFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' + +import type { PostgresAdapter } from './types.js' import { findMany } from './find/findMany.js' -import { getTableName } from './schema/getTableName.js' -export const queryDrafts: QueryDrafts = async function queryDrafts({ - collection, - limit, - locale, - page = 1, - pagination, - req = {} as PayloadRequest, - sort, - where, -}) { +export const queryDrafts: QueryDrafts = async function queryDrafts( + this: PostgresAdapter, + { collection, limit, locale, page = 1, pagination, req = {} as PayloadRequest, sort, where }, +) { const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - versions: true, - }) + const tableName = this.tableNameMap.get( + `_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`, + ) const fields = buildVersionCollectionFields(collectionConfig) const combinedWhere = combineQueries({ latest: { equals: true } }, where) diff --git a/packages/db-postgres/src/schema/build.ts b/packages/db-postgres/src/schema/build.ts index e489c7325b..e685b38720 100644 --- a/packages/db-postgres/src/schema/build.ts +++ b/packages/db-postgres/src/schema/build.ts @@ -24,7 +24,7 @@ import toSnakeCase from 'to-snake-case' import type { GenericColumns, GenericTable, IDType, PostgresAdapter } from '../types.js' -import { getTableName } from './getTableName.js' +import { createTableName } from './createTableName.js' import { parentIDColumnMap } from './parentIDColumnMap.js' import { setColumnID } from './setColumnID.js' import { traverseFields } from './traverseFields.js' @@ -313,7 +313,7 @@ export const buildTable = ({ relationships.forEach((relationTo) => { const relationshipConfig = adapter.payload.collections[relationTo].config - const formattedRelationTo = getTableName({ + const formattedRelationTo = createTableName({ adapter, config: relationshipConfig, throwValidationError: true, @@ -381,7 +381,7 @@ export const buildTable = ({ } relationships.forEach((relationTo) => { - const relatedTableName = getTableName({ + const relatedTableName = createTableName({ adapter, config: adapter.payload.collections[relationTo].config, throwValidationError: true, diff --git a/packages/db-postgres/src/schema/getTableName.ts b/packages/db-postgres/src/schema/createTableName.ts similarity index 55% rename from packages/db-postgres/src/schema/getTableName.ts rename to packages/db-postgres/src/schema/createTableName.ts index 1119efca4e..083c8f5e36 100644 --- a/packages/db-postgres/src/schema/getTableName.ts +++ b/packages/db-postgres/src/schema/createTableName.ts @@ -14,53 +14,59 @@ type Args = { name?: string slug?: string } - /** Localized tables need to be given the locales suffix */ - locales?: boolean /** For nested tables passed for the user custom dbName functions to handle their own iterations */ parentTableName?: string /** For sub tables (array for example) this needs to include the parentTableName */ prefix?: string - /** Adds the relationships suffix */ - relationships?: boolean /** For tables based on fields that could have both enumName and dbName (ie: select with hasMany), default: 'dbName' */ target?: 'dbName' | 'enumName' throwValidationError?: boolean - /** Adds the versions suffix, should only be used on the base collection to duplicate suffixing */ + /** Adds the versions suffix to the default table name - should only be used on the base collection to avoid duplicate suffixing */ versions?: boolean + /** Adds the versions suffix to custom dbName only - this is used while creating blocks / selects / arrays / etc */ + versionsCustomName?: boolean } /** * Used to name database enums and tables * Returns the table or enum name for a given entity */ -export const getTableName = ({ +export const createTableName = ({ adapter, config: { name, slug }, config, - locales = false, parentTableName, prefix = '', - relationships = false, target = 'dbName', throwValidationError = false, versions = false, + versionsCustomName = false, }: Args): string => { - let result: string - let custom = config[target] + let customNameDefinition = config[target] - if (!custom && target === 'enumName') { - custom = config['dbName'] + let defaultTableName = `${prefix}${toSnakeCase(name ?? slug)}` + + if (versions) defaultTableName = `_${defaultTableName}${adapter.versionsSuffix}` + + let customTableNameResult: string + + if (!customNameDefinition && target === 'enumName') { + customNameDefinition = config['dbName'] } - if (custom) { - result = typeof custom === 'function' ? custom({ tableName: parentTableName }) : custom - } else { - result = `${prefix}${toSnakeCase(name ?? slug)}` + if (customNameDefinition) { + customTableNameResult = + typeof customNameDefinition === 'function' + ? customNameDefinition({ tableName: parentTableName }) + : customNameDefinition + + if (versionsCustomName) + customTableNameResult = `_${customTableNameResult}${adapter.versionsSuffix}` } - if (locales) result = `${result}${adapter.localesSuffix}` - if (versions) result = `_${result}${adapter.versionsSuffix}` - if (relationships) result = `${result}${adapter.relationshipsSuffix}` + const result = customTableNameResult || defaultTableName + + adapter.tableNameMap.set(defaultTableName, result) if (!throwValidationError) { return result @@ -71,5 +77,6 @@ export const getTableName = ({ `Exceeded max identifier length for table or enum name of 63 characters. Invalid name: ${result}`, ) } + return result } diff --git a/packages/db-postgres/src/schema/traverseFields.ts b/packages/db-postgres/src/schema/traverseFields.ts index 9d089a59b0..004d4dd6f0 100644 --- a/packages/db-postgres/src/schema/traverseFields.ts +++ b/packages/db-postgres/src/schema/traverseFields.ts @@ -29,7 +29,7 @@ import type { BaseExtraConfig } from './build.js' import { hasLocalesTable } from '../utilities/hasLocalesTable.js' import { buildTable } from './build.js' import { createIndex } from './createIndex.js' -import { getTableName } from './getTableName.js' +import { createTableName } from './createTableName.js' import { idToUUID } from './idToUUID.js' import { parentIDColumnMap } from './parentIDColumnMap.js' import { validateExistingBlockIsIdentical } from './validateExistingBlockIsIdentical.js' @@ -223,7 +223,7 @@ export const traverseFields = ({ case 'radio': case 'select': { - const enumName = getTableName({ + const enumName = createTableName({ adapter, config: field, parentTableName: newTableName, @@ -244,12 +244,13 @@ export const traverseFields = ({ ) if (field.type === 'select' && field.hasMany) { - const selectTableName = getTableName({ + const selectTableName = createTableName({ adapter, config: field, parentTableName: newTableName, prefix: `${newTableName}_`, throwValidationError, + versionsCustomName: versions, }) const baseColumns: Record = { order: integer('order').notNull(), @@ -317,12 +318,13 @@ export const traverseFields = ({ case 'array': { const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull - const arrayTableName = getTableName({ + const arrayTableName = createTableName({ adapter, config: field, parentTableName: newTableName, prefix: `${newTableName}_`, throwValidationError, + versionsCustomName: versions, }) const baseColumns: Record = { @@ -405,12 +407,13 @@ export const traverseFields = ({ const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull field.blocks.forEach((block) => { - const blockTableName = getTableName({ + const blockTableName = createTableName({ adapter, config: block, parentTableName: rootTableName, prefix: `${rootTableName}_blocks_`, throwValidationError, + versionsCustomName: versions, }) if (!adapter.tables[blockTableName]) { const baseColumns: Record = { @@ -500,7 +503,6 @@ export const traverseFields = ({ tableLocales: adapter.tables[`${blockTableName}${adapter.localesSuffix}`], }) } - adapter.blockTableNames[`${rootTableName}.${toSnakeCase(block.slug)}`] = blockTableName rootRelationsToBuild.set(`_blocks_${block.slug}`, blockTableName) }) diff --git a/packages/db-postgres/src/transform/write/array.ts b/packages/db-postgres/src/transform/write/array.ts index 5ac87ae60c..c2741cc40a 100644 --- a/packages/db-postgres/src/transform/write/array.ts +++ b/packages/db-postgres/src/transform/write/array.ts @@ -45,6 +45,7 @@ export const transformArray = ({ texts, }: Args) => { const newRows: ArrayRowToInsert[] = [] + const hasUUID = adapter.tables[arrayTableName]._uuid if (isArrayOfRows(data)) { diff --git a/packages/db-postgres/src/transform/write/blocks.ts b/packages/db-postgres/src/transform/write/blocks.ts index 809e95e81a..35d6605f80 100644 --- a/packages/db-postgres/src/transform/write/blocks.ts +++ b/packages/db-postgres/src/transform/write/blocks.ts @@ -61,7 +61,7 @@ export const transformBlocks = ({ if (field.localized && locale) newRow.row._locale = locale - const blockTableName = `${baseTableName}_blocks_${blockType}` + const blockTableName = adapter.tableNameMap.get(`${baseTableName}_blocks_${blockType}`) const hasUUID = adapter.tables[blockTableName]._uuid diff --git a/packages/db-postgres/src/transform/write/traverseFields.ts b/packages/db-postgres/src/transform/write/traverseFields.ts index 3e23256ea6..656f2eabc7 100644 --- a/packages/db-postgres/src/transform/write/traverseFields.ts +++ b/packages/db-postgres/src/transform/write/traverseFields.ts @@ -94,7 +94,7 @@ export const traverseFields = ({ } if (field.type === 'array') { - const arrayTableName = `${parentTableName}_${columnName}` + const arrayTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`) if (!arrays[arrayTableName]) arrays[arrayTableName] = [] @@ -458,7 +458,7 @@ export const traverseFields = ({ } if (field.type === 'select' && field.hasMany) { - const selectTableName = `${parentTableName}_${columnName}` + const selectTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`) if (!selects[selectTableName]) selects[selectTableName] = [] if (field.localized) { diff --git a/packages/db-postgres/src/types.ts b/packages/db-postgres/src/types.ts index 7a753ed56d..7e1156c910 100644 --- a/packages/db-postgres/src/types.ts +++ b/packages/db-postgres/src/types.ts @@ -61,10 +61,6 @@ export type DrizzleTransaction = PgTransaction< > export type PostgresAdapter = BaseDatabaseAdapter & { - /** - * Used internally to map the block name to the table name - */ - blockTableNames: Record drizzle: DrizzleDB enums: Record /** @@ -90,6 +86,7 @@ export type PostgresAdapter = BaseDatabaseAdapter & { resolve: () => Promise } } + tableNameMap: Map tables: Record> versionsSuffix?: string } diff --git a/packages/db-postgres/src/update.ts b/packages/db-postgres/src/update.ts index ab59c59b04..b3717e44f4 100644 --- a/packages/db-postgres/src/update.ts +++ b/packages/db-postgres/src/update.ts @@ -1,10 +1,11 @@ import type { UpdateOne } from 'payload/database' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' import buildQuery from './queries/buildQuery.js' import { selectDistinct } from './queries/selectDistinct.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export const updateOne: UpdateOne = async function updateOne( @@ -13,10 +14,7 @@ export const updateOne: UpdateOne = async function updateOne( ) { const db = this.sessions[req.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config - const tableName = getTableName({ - adapter: this, - config: collection, - }) + const tableName = this.tableNameMap.get(toSnakeCase(collection.slug)) const whereToUse = whereArg || { id: { equals: id } } let idToUpdate = id diff --git a/packages/db-postgres/src/updateGlobal.ts b/packages/db-postgres/src/updateGlobal.ts index b5197c700f..a9e3cfd2f2 100644 --- a/packages/db-postgres/src/updateGlobal.ts +++ b/packages/db-postgres/src/updateGlobal.ts @@ -1,9 +1,10 @@ import type { UpdateGlobalArgs } from 'payload/database' import type { PayloadRequest, TypeWithID } from 'payload/types' +import toSnakeCase from 'to-snake-case' + import type { PostgresAdapter } from './types.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export async function updateGlobal( @@ -12,10 +13,7 @@ export async function updateGlobal( ): Promise { const db = this.sessions[req.transactionID]?.db || this.drizzle const globalConfig = this.payload.globals.config.find((config) => config.slug === slug) - const tableName = getTableName({ - adapter: this, - config: globalConfig, - }) + const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug)) const existingGlobal = await db.query[tableName].findFirst({}) diff --git a/packages/db-postgres/src/updateGlobalVersion.ts b/packages/db-postgres/src/updateGlobalVersion.ts index 0f0f82e28d..7fc6becc06 100644 --- a/packages/db-postgres/src/updateGlobalVersion.ts +++ b/packages/db-postgres/src/updateGlobalVersion.ts @@ -2,11 +2,11 @@ import type { TypeWithVersion, UpdateGlobalVersionArgs } from 'payload/database' import type { PayloadRequest, SanitizedGlobalConfig, TypeWithID } from 'payload/types' import { buildVersionGlobalFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import buildQuery from './queries/buildQuery.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export async function updateGlobalVersion( @@ -25,11 +25,11 @@ export async function updateGlobalVersion( ({ slug }) => slug === global, ) const whereToUse = whereArg || { id: { equals: id } } - const tableName = getTableName({ - adapter: this, - config: globalConfig, - versions: true, - }) + + const tableName = this.tableNameMap.get( + `_${toSnakeCase(globalConfig.slug)}${this.versionsSuffix}`, + ) + const fields = buildVersionGlobalFields(globalConfig) const { where } = await buildQuery({ diff --git a/packages/db-postgres/src/updateVersion.ts b/packages/db-postgres/src/updateVersion.ts index b93e979120..91694b17b1 100644 --- a/packages/db-postgres/src/updateVersion.ts +++ b/packages/db-postgres/src/updateVersion.ts @@ -2,11 +2,11 @@ import type { TypeWithVersion, UpdateVersionArgs } from 'payload/database' import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types' import { buildVersionCollectionFields } from 'payload/versions' +import toSnakeCase from 'to-snake-case' import type { PostgresAdapter } from './types.js' import buildQuery from './queries/buildQuery.js' -import { getTableName } from './schema/getTableName.js' import { upsertRow } from './upsertRow/index.js' export async function updateVersion( @@ -23,11 +23,10 @@ export async function updateVersion( const db = this.sessions[req.transactionID]?.db || this.drizzle const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const whereToUse = whereArg || { id: { equals: id } } - const tableName = getTableName({ - adapter: this, - config: collectionConfig, - versions: true, - }) + const tableName = this.tableNameMap.get( + `_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`, + ) + const fields = buildVersionCollectionFields(collectionConfig) const { where } = await buildQuery({ diff --git a/packages/db-postgres/src/upsertRow/index.ts b/packages/db-postgres/src/upsertRow/index.ts index 81427ab0d3..3b24230143 100644 --- a/packages/db-postgres/src/upsertRow/index.ts +++ b/packages/db-postgres/src/upsertRow/index.ts @@ -137,7 +137,7 @@ export const upsertRow = async ({ // ////////////////////////////////// if (localesToInsert.length > 0) { - const localeTable = adapter.tables[`${tableName}_locales`] + const localeTable = adapter.tables[`${tableName}${adapter.localesSuffix}`] if (operation === 'update') { await db.delete(localeTable).where(eq(localeTable._parentID, insertedRow.id)) @@ -150,7 +150,7 @@ export const upsertRow = async ({ // INSERT RELATIONSHIPS // ////////////////////////////////// - const relationshipsTableName = `${tableName}_rels` + const relationshipsTableName = `${tableName}${adapter.relationshipsSuffix}` if (operation === 'update') { await deleteExistingRowsByPath({ @@ -223,15 +223,16 @@ export const upsertRow = async ({ if (operation === 'update') { for (const blockName of rowToInsert.blocksToDelete) { - const blockTableName = `${tableName}_blocks_${blockName}` + const blockTableName = adapter.tableNameMap.get(`${tableName}_blocks_${blockName}`) const blockTable = adapter.tables[blockTableName] await db.delete(blockTable).where(eq(blockTable._parentID, insertedRow.id)) } } for (const [blockName, blockRows] of Object.entries(blocksToInsert)) { + const blockTableName = adapter.tableNameMap.get(`${tableName}_blocks_${blockName}`) insertedBlockRows[blockName] = await db - .insert(adapter.tables[`${tableName}_blocks_${blockName}`]) + .insert(adapter.tables[blockTableName]) .values(blockRows.map(({ row }) => row)) .returning() @@ -258,7 +259,7 @@ export const upsertRow = async ({ if (blockLocaleRowsToInsert.length > 0) { await db - .insert(adapter.tables[`${tableName}_blocks_${blockName}_locales`]) + .insert(adapter.tables[`${blockTableName}${adapter.localesSuffix}`]) .values(blockLocaleRowsToInsert) .returning() } diff --git a/test/database/config.ts b/test/database/config.ts index df08974fe1..14f8061037 100644 --- a/test/database/config.ts +++ b/test/database/config.ts @@ -45,6 +45,10 @@ export default buildConfigWithDefaults({ { slug: 'relation-a', fields: [ + { + name: 'title', + type: 'text', + }, { name: 'relationship', type: 'relationship', @@ -63,6 +67,10 @@ export default buildConfigWithDefaults({ { slug: 'relation-b', fields: [ + { + name: 'title', + type: 'text', + }, { name: 'relationship', type: 'relationship', diff --git a/test/database/int.spec.ts b/test/database/int.spec.ts index e1f0d049dc..3867708a64 100644 --- a/test/database/int.spec.ts +++ b/test/database/int.spec.ts @@ -214,6 +214,54 @@ describe('database', () => { expect(db.enums.radioEnum).toBeDefined() } }) + + it('should create and read doc with custom db names', async () => { + const relationA = await payload.create({ + collection: 'relation-a', + data: { + title: 'hello', + }, + }) + + const { id } = await payload.create({ + collection: 'custom-schema', + data: { + text: 'test', + relationship: [relationA.id], + localizedText: 'hello', + select: ['a', 'b'], + radio: 'a', + array: [ + { + text: 'hello', + localizedText: 'goodbye', + }, + ], + blocks: [ + { + blockType: 'block', + text: 'hello', + localizedText: 'goodbye', + }, + ], + }, + }) + + const doc = await payload.findByID({ + collection: 'custom-schema', + id, + }) + + expect(doc.relationship[0].title).toStrictEqual(relationA.title) + expect(doc.text).toStrictEqual('test') + expect(doc.localizedText).toStrictEqual('hello') + expect(doc.select).toHaveLength(2) + expect(doc.radio).toStrictEqual('a') + expect(doc.array[0].text).toStrictEqual('hello') + expect(doc.array[0].localizedText).toStrictEqual('goodbye') + expect(doc.blocks[0].text).toStrictEqual('hello') + expect(doc.blocks[0].localizedText).toStrictEqual('goodbye') + }) }) describe('transactions', () => {