From eea3cca28bd9eaa0e53527f1af0f761cc76e845b Mon Sep 17 00:00:00 2001 From: James Date: Tue, 8 Aug 2023 13:30:08 -0400 Subject: [PATCH] chore: WIP - nested array insertion --- packages/db-mongodb/src/create.ts | 1 + packages/db-postgres/src/create/index.ts | 1 + .../db-postgres/src/create/insertArrays.ts | 85 ++++++ packages/db-postgres/src/create/insertRows.ts | 242 +++++++++------- .../db-postgres/src/create/traverseFields.ts | 270 ++++++++++-------- packages/db-postgres/src/create/types.ts | 39 ++- packages/db-postgres/src/schema/build.ts | 3 +- .../db-postgres/src/schema/traverseFields.ts | 34 ++- .../src/transform/traverseFields.ts | 4 +- src/utilities/timestamp.ts | 5 + test/postgres/config.ts | 1 + 11 files changed, 424 insertions(+), 261 deletions(-) create mode 100644 packages/db-postgres/src/create/insertArrays.ts create mode 100644 src/utilities/timestamp.ts diff --git a/packages/db-mongodb/src/create.ts b/packages/db-mongodb/src/create.ts index 6208ba7b0e..0a54c11544 100644 --- a/packages/db-mongodb/src/create.ts +++ b/packages/db-mongodb/src/create.ts @@ -22,5 +22,6 @@ export const create: Create = async function create( if (verificationToken) { result._verificationToken = verificationToken; } + return result; }; diff --git a/packages/db-postgres/src/create/index.ts b/packages/db-postgres/src/create/index.ts index 0d2af5bfd4..b643d3af32 100644 --- a/packages/db-postgres/src/create/index.ts +++ b/packages/db-postgres/src/create/index.ts @@ -15,6 +15,7 @@ export const create: Create = async function create({ fallbackLocale: req.fallbackLocale, fields: collection.fields, locale: req.locale, + operation: 'create', tableName: toSnakeCase(collectionSlug), }); diff --git a/packages/db-postgres/src/create/insertArrays.ts b/packages/db-postgres/src/create/insertArrays.ts new file mode 100644 index 0000000000..2266766f85 --- /dev/null +++ b/packages/db-postgres/src/create/insertArrays.ts @@ -0,0 +1,85 @@ +/* eslint-disable no-param-reassign */ +import { PostgresAdapter } from '../types'; +import { RowToInsert } from './types'; + +type Args = { + adapter: PostgresAdapter + rowsToInsert: RowToInsert[] + parentRows: Record[] +} + +type RowsByTable = { + [tableName: string]: { + rows: Record[] + locales: Record[] + columnName: string + rowIndexMap: [number, number][] + } +} + +export const insertArrays = async ({ + adapter, + rowsToInsert, + parentRows, +}: Args): Promise => { + const rowsByTable: RowsByTable = {}; + + rowsToInsert.forEach(({ arrays }, parentRowIndex) => { + Object.entries(arrays).forEach(([tableName, arrayRows]) => { + if (!rowsByTable[tableName]) { + rowsByTable[tableName] = { + rows: [], + locales: [], + columnName: arrayRows[0]?.columnName, + rowIndexMap: [], + }; + } + + const parentID = parentRows[parentRowIndex].id; + + rowsByTable[tableName].rowIndexMap.push([ + rowsByTable[tableName].rows.length, arrayRows.length, + ]); + + arrayRows.forEach((arrayRow) => { + arrayRow.row._parentID = parentID; + rowsByTable[tableName].rows.push(arrayRow.row); + arrayRow.locale._parentID = arrayRow.row.id; + rowsByTable[tableName].locales.push(arrayRow.locale); + }); + }); + }); + + await Promise.all(Object.entries(rowsByTable).map(async ( + [tableName, { locales, rows }], + ) => { + const insertedRows = await adapter.db.insert(adapter.tables[tableName]) + .values(rows).returning(); + + rowsByTable[tableName].rows = insertedRows; + + if (adapter.tables[`${tableName}_locales`]) { + const insertedLocaleRows = await adapter.db.insert(adapter.tables[`${tableName}_locales`]) + .values(locales).returning(); + + insertedLocaleRows.forEach((localeRow, i) => { + rowsByTable[tableName].rows[i]._locales = [localeRow]; + }); + } + + // await insertRows({ + // adapter, + // parentRows: rowsByTable[tableName].rows, + // }); + })); + + Object.values(rowsByTable).forEach(({ rows, columnName, rowIndexMap }) => { + rowIndexMap.forEach(([start, finish], i) => { + parentRows[i][columnName] = rows.slice(start, finish); + }); + }); + + console.log(parentRows); + + // Recursively call arrays at this point +}; diff --git a/packages/db-postgres/src/create/insertRows.ts b/packages/db-postgres/src/create/insertRows.ts index 4130f8a7e3..c42e27de37 100644 --- a/packages/db-postgres/src/create/insertRows.ts +++ b/packages/db-postgres/src/create/insertRows.ts @@ -1,159 +1,181 @@ /* eslint-disable no-param-reassign */ import { Field } from 'payload/types'; -import toSnakeCase from 'to-snake-case'; -import { Block, fieldAffectsData } from 'payload/dist/fields/config/types'; import { PostgresAdapter } from '../types'; import { traverseFields } from './traverseFields'; import { transform } from '../transform'; -import { ArrayRowPromisesMap, BlockRowsToInsert, RowInsertionGroup } from './types'; +import { BlockRowToInsert, RowToInsert } from './types'; +import { insertArrays } from './insertArrays'; type Args = { adapter: PostgresAdapter - addRowIndexToPath?: boolean - rows: Record[] fallbackLocale?: string | false fields: Field[] - initialRowData?: Record[] - incomingRelationshipRows?: Record[] - incomingBlockRows?: { [blockType: string]: BlockRowsToInsert } locale: string operation: 'create' | 'update' path?: string + rows: Record[] tableName: string } export const insertRows = async ({ adapter, - addRowIndexToPath, - rows, fallbackLocale, fields, - initialRowData, - incomingBlockRows, - incomingRelationshipRows, locale, operation, path = '', + rows, tableName, }: Args): Promise[]> => { - const insertions: RowInsertionGroup[] = []; + const rowsToInsert: RowToInsert[] = []; - await Promise.all(rows.map(async (data, i) => { - const insertion: RowInsertionGroup = { - row: { ...initialRowData?.[i] || {} }, - localeRow: {}, - relationshipRows: incomingRelationshipRows || [], - blockRows: incomingBlockRows || {}, - arrayRowPromises: {}, - }; + rows.forEach((data, i) => { + rowsToInsert.push({ + row: {}, + locale: {}, + relationships: [], + blocks: {}, + arrays: {}, + }); - await traverseFields({ + traverseFields({ adapter, - arrayRowPromises: insertion.arrayRowPromises, - blockRows: insertion.blockRows, + arrays: rowsToInsert[i].arrays, + blocks: rowsToInsert[i].blocks, + columnPrefix: '', data, - fallbackLocale, fields, locale, - localeRow: insertion.localeRow, - operation, - path: addRowIndexToPath ? `${path}${i}.` : path, - relationshipRows: insertion.relationshipRows, - row: insertion.row, - tableName, + localeRow: rowsToInsert[i].locale, + newTableName: tableName, + parentTableName: tableName, + path, + relationships: rowsToInsert[i].relationships, + row: rowsToInsert[i].row, }); - - insertions.push(insertion); - })); - - const insertedRows = await adapter.db.insert(adapter.tables[tableName]) - .values(insertions.map(({ row }) => row)).returning(); - - let insertedLocaleRows: Record[] = []; - let insertedRelationshipRows: Record[] = []; - - const relatedRowPromises = []; - - // Fill related rows with parent IDs returned from database - insertedRows.forEach((row, i) => { - insertions[i].row = row; - const { localeRow, relationshipRows, blockRows, arrayRowPromises } = insertions[i]; - - if (Object.keys(arrayRowPromises).length > 0) { - Object.entries(arrayRowPromises).forEach(([key, func]) => { - relatedRowPromises.push(async () => { - insertions[i].row[key] = await func({ parentID: row.id as string }); - }); - }); - } - - if (!incomingBlockRows && Object.keys(blockRows).length > 0) { - Object.entries(blockRows).forEach(([blockType, { block, rows: blockRowsToInsert }]) => { - relatedRowPromises.push(async () => { - const result = await insertRows({ - adapter, - addRowIndexToPath: true, - rows: blockRowsToInsert, - fallbackLocale, - fields: block.fields, - initialRowData: blockRowsToInsert.map((initialBlockRow) => ({ - _order: initialBlockRow._order, - _parentID: row.id, - _path: initialBlockRow._path, - })), - incomingBlockRows, - incomingRelationshipRows, - locale, - operation, - path, - tableName: `${tableName}_${toSnakeCase(blockType)}`, - }); - - return result; - }); - }); - } - - if (Object.keys(localeRow).length > 0) { - localeRow._parentID = row.id; - localeRow._locale = locale; - insertedLocaleRows.push(localeRow); - } - - if (relationshipRows.length > 0) { - insertedRelationshipRows = insertedRelationshipRows.concat(relationshipRows.map((relationshipRow) => { - relationshipRow.parent = row.id; - return relationshipRow; - })); - } }); - // Insert locales - if (insertedLocaleRows.length > 0) { - relatedRowPromises.push(async () => { + const insertedRows = await adapter.db.insert(adapter.tables[tableName]) + .values(rowsToInsert.map(({ row }) => row)).returning(); + + const localesToInsert: Record[] = []; + const relationsToInsert: Record[] = []; + const blocksToInsert: { [blockType: string]: BlockRowToInsert[] } = {}; + + const promises = []; + + insertedRows.forEach((insertedRow, i) => { + if (Object.keys(rowsToInsert[i].locale).length > 0) { + rowsToInsert[i].locale._parentID = insertedRow.id; + rowsToInsert[i].locale._locale = locale; + localesToInsert.push(rowsToInsert[i].locale); + } + + if (rowsToInsert[i].relationships) { + rowsToInsert[i].relationships.forEach((relation) => { + relation.parent = insertedRow.id; + relationsToInsert.push(relation); + }); + } + + Object.keys(rowsToInsert[i].blocks).forEach((blockName) => { + rowsToInsert[i].blocks[blockName].forEach((blockRow) => { + blockRow.row._parentID = insertedRow.id; + if (!blocksToInsert[blockName]) blocksToInsert[blockName] = []; + blocksToInsert[blockName].push(blockRow); + }); + }); + }); + + await insertArrays({ + adapter, + rowsToInsert, + parentRows: insertedRows, + }); + + // ////////////////////////////////// + // INSERT LOCALES + // ////////////////////////////////// + + let insertedLocaleRows; + + if (localesToInsert.length > 0) { + promises.push(async () => { insertedLocaleRows = await adapter.db.insert(adapter.tables[`${tableName}_locales`]) - .values(insertedLocaleRows).returning(); + .values(localesToInsert).returning(); }); } - // Insert relationships - // NOTE - only do this if there are no incoming relationship rows - // because `insertRows` is recursive and relationships should only happen at the top level - if (!incomingRelationshipRows && insertedRelationshipRows.length > 0) { - relatedRowPromises.push(async () => { + // ////////////////////////////////// + // INSERT RELATIONSHIPS + // ////////////////////////////////// + + let insertedRelationshipRows; + + if (relationsToInsert.length > 0) { + promises.push(async () => { insertedRelationshipRows = await adapter.db.insert(adapter.tables[`${tableName}_relationships`]) - .values(insertedRelationshipRows).returning(); + .values(relationsToInsert).returning(); }); } - await Promise.all(relatedRowPromises.map((promise) => promise())); + // ////////////////////////////////// + // INSERT BLOCKS + // ////////////////////////////////// + + const insertedBlockRows: Record[]> = {}; + + Object.entries(blocksToInsert).forEach(([blockName, blockRows]) => { + promises.push(async () => { + insertedBlockRows[blockName] = await adapter.db.insert(adapter.tables[`${tableName}_${blockName}`]) + .values(blockRows.map(({ row }) => row)).returning(); + + insertedBlockRows[blockName].forEach((row, i) => { + blockRows[i].row = row; + }); + + const blockLocaleIndexMap: number[] = []; + + const blockLocaleRowsToInsert = blockRows.reduce((acc, blockRow, i) => { + if (Object.keys(blockRow.locale).length > 0) { + blockRow.locale._parentID = blockRow.row.id; + blockRow.locale._locale = locale; + acc.push(blockRow.locale); + blockLocaleIndexMap.push(i); + return acc; + } + + return acc; + }, []); + + if (blockLocaleRowsToInsert.length > 0) { + const insertedBlockLocaleRows = await adapter.db.insert(adapter.tables[`${tableName}_${blockName}_locales`]) + .values(blockLocaleRowsToInsert).returning(); + + insertedBlockLocaleRows.forEach((blockLocaleRow, i) => { + insertedBlockRows[blockName][blockLocaleIndexMap[i]]._locales = [blockLocaleRow]; + }); + } + }); + }); + + await Promise.all(promises.map((promise) => promise())); + + // ////////////////////////////////// + // TRANSFORM DATA + // ////////////////////////////////// return insertedRows.map((row) => { - const matchedLocaleRow = insertedLocaleRows.find(({ _parentID }) => _parentID === row.id); + const matchedLocaleRow = insertedLocaleRows?.find(({ _parentID }) => _parentID === row.id); if (matchedLocaleRow) row._locales = [matchedLocaleRow]; - const matchedRelationshipRows = insertedRelationshipRows.filter(({ parent }) => parent === row.id); - if (matchedRelationshipRows.length > 0) row._relationships = matchedRelationshipRows; + const matchedRelationshipRows = insertedRelationshipRows?.filter(({ parent }) => parent === row.id); + if (matchedRelationshipRows?.length > 0) row._relationships = matchedRelationshipRows; + + Object.entries(insertedBlockRows).forEach(([blockName, blocks]) => { + const matchedBlocks = blocks.filter(({ _parentID }) => _parentID === row.id); + if (matchedBlocks.length > 0) row[`_blocks_${blockName}`] = matchedBlocks; + }); const result = transform({ config: adapter.payload.config, diff --git a/packages/db-postgres/src/create/traverseFields.ts b/packages/db-postgres/src/create/traverseFields.ts index 77d3a670df..9e8d63b314 100644 --- a/packages/db-postgres/src/create/traverseFields.ts +++ b/packages/db-postgres/src/create/traverseFields.ts @@ -3,47 +3,48 @@ import { Field } from 'payload/types'; import toSnakeCase from 'to-snake-case'; import { fieldAffectsData, valueIsValueWithRelation } from 'payload/dist/fields/config/types'; import { PostgresAdapter } from '../types'; -import { ArrayRowPromise, ArrayRowPromisesMap, BlockRowsToInsert } from './types'; -import { insertRows } from './insertRows'; +import { ArrayRowToInsert, BlockRowToInsert } from './types'; import { isArrayOfRows } from '../utilities/isArrayOfRows'; type Args = { adapter: PostgresAdapter - arrayRowPromises: ArrayRowPromisesMap - blockRows: { [blockType: string]: BlockRowsToInsert } - columnPrefix?: string + arrays: { + [tableName: string]: ArrayRowToInsert[] + } + blocks: { + [blockType: string]: BlockRowToInsert[] + } + columnPrefix: string data: Record - fallbackLocale?: string | false fields: Field[] locale: string localeRow: Record - operation: 'create' | 'update' + newTableName: string + parentTableName: string path: string - relationshipRows: Record[] + relationships: Record[] row: Record - tableName: string } -export const traverseFields = async ({ +export const traverseFields = ({ adapter, - arrayRowPromises, - blockRows, + arrays, + blocks, columnPrefix, data, - fallbackLocale, fields, locale, localeRow, - operation, + newTableName, + parentTableName, path, - relationshipRows, + relationships, row, - tableName, }: Args) => { - await Promise.all(fields.map(async (field) => { + fields.forEach((field) => { let targetRow = row; - let columnName: string; - let fieldData: unknown; + let columnName = ''; + let fieldData; if (fieldAffectsData(field)) { columnName = `${columnPrefix || ''}${field.name}`; @@ -73,34 +74,42 @@ export const traverseFields = async ({ case 'array': { if (isArrayOfRows(fieldData)) { - const arrayTableName = `${tableName}_${toSnakeCase(field.name)}`; + const arrayTableName = `${newTableName}_${toSnakeCase(field.name)}`; + if (!arrays[arrayTableName]) arrays[arrayTableName] = []; - const promise: ArrayRowPromise = async ({ parentID }) => { - const result = await insertRows({ - adapter, - addRowIndexToPath: true, - fallbackLocale, - fields: field.fields, - incomingBlockRows: blockRows, - incomingRelationshipRows: relationshipRows, - initialRowData: (fieldData as []).map((_, i) => ({ + fieldData.forEach((arrayRow, i) => { + const newRow: ArrayRowToInsert = { + columnName, + parentTableName, + row: { _order: i + 1, - _parentID: parentID, - })), + }, + locale: { + _locale: locale, + }, + arrays: {}, + }; + + if (field.localized) newRow.row._locale = locale; + + traverseFields({ + adapter, + arrays: newRow.arrays, + blocks, + columnPrefix: '', + data: arrayRow, + fields: field.fields, locale, - operation, - rows: fieldData as Record[], - tableName: arrayTableName, + localeRow: newRow.locale, + newTableName: arrayTableName, + parentTableName: arrayTableName, + path: `${path || ''}${field.name}.${i}.`, + relationships, + row: newRow.row, }); - return result.map((subRow) => { - delete subRow._order; - delete subRow._parentID; - return subRow; - }); - }; - - arrayRowPromises[columnName] = promise; + arrays[arrayTableName].push(newRow); + }); } break; @@ -113,15 +122,38 @@ export const traverseFields = async ({ const matchedBlock = field.blocks.find(({ slug }) => slug === blockRow.blockType); if (!matchedBlock) return; - if (!blockRows[blockRow.blockType]) { - blockRows[blockRow.blockType] = { - rows: [], - block: matchedBlock, - }; - } - blockRow._order = i + 1; - blockRow._path = `${path}${field.name}`; - blockRows[blockRow.blockType].rows.push(blockRow); + if (!blocks[blockRow.blockType]) blocks[blockRow.blockType] = []; + + const newRow: BlockRowToInsert = { + arrays: {}, + row: { + _order: i + 1, + _path: `${path}${field.name}`, + }, + locale: {}, + }; + + if (field.localized) newRow.row._locale = locale; + + const blockTableName = `${newTableName}_${toSnakeCase(blockRow.blockType)}`; + + traverseFields({ + adapter, + arrays: newRow.arrays, + blocks, + columnPrefix: '', + data: blockRow, + fields: matchedBlock.fields, + locale, + localeRow: newRow.locale, + newTableName: blockTableName, + parentTableName: blockTableName, + path: `${path || ''}${field.name}.${i}.`, + relationships, + row: newRow.row, + }); + + blocks[blockRow.blockType].push(newRow); }); } @@ -130,86 +162,86 @@ export const traverseFields = async ({ case 'group': { if (typeof data[field.name] === 'object' && data[field.name] !== null) { - await traverseFields({ + traverseFields({ adapter, - arrayRowPromises, - blockRows, + arrays, + blocks, columnPrefix: `${columnName}_`, data: data[field.name] as Record, fields: field.fields, locale, localeRow, - operation, + newTableName: `${parentTableName}_${toSnakeCase(field.name)}`, + parentTableName, path: `${path || ''}${field.name}.`, - relationshipRows, + relationships, row, - tableName, }); } break; } - case 'tabs': { - await Promise.all(field.tabs.map(async (tab) => { - if ('name' in tab) { - if (typeof data[tab.name] === 'object' && data[tab.name] !== null) { - await traverseFields({ - adapter, - arrayRowPromises, - blockRows, - columnPrefix: `${columnName}_`, - data: data[tab.name] as Record, - fields: tab.fields, - locale, - localeRow, - operation, - path: `${path || ''}${tab.name}.`, - relationshipRows, - row, - tableName, - }); - } - } else { - await traverseFields({ - adapter, - arrayRowPromises, - blockRows, - columnPrefix, - data, - fields: tab.fields, - locale, - localeRow, - operation, - path, - relationshipRows, - row, - tableName, - }); - } - })); - break; - } + // case 'tabs': { + // await Promise.all(field.tabs.map(async (tab) => { + // if ('name' in tab) { + // if (typeof data[tab.name] === 'object' && data[tab.name] !== null) { + // await traverseFields({ + // adapter, + // arrayRowPromises, + // blockRows, + // columnPrefix: `${columnName}_`, + // data: data[tab.name] as Record, + // fields: tab.fields, + // locale, + // localeRow, + // operation, + // path: `${path || ''}${tab.name}.`, + // relationshipRows, + // row, + // tableName, + // }); + // } + // } else { + // await traverseFields({ + // adapter, + // arrayRowPromises, + // blockRows, + // columnPrefix, + // data, + // fields: tab.fields, + // locale, + // localeRow, + // operation, + // path, + // relationshipRows, + // row, + // tableName, + // }); + // } + // })); + // break; + // } - case 'row': - case 'collapsible': { - await traverseFields({ - adapter, - arrayRowPromises, - blockRows, - columnPrefix, - data, - fields: field.fields, - locale, - localeRow, - operation, - path, - relationshipRows, - row, - tableName, - }); - break; - } + // case 'row': + // case 'collapsible': { + // await traverseFields({ + // adapter, + // arrayRowPromises, + // blockRows, + // columnPrefix, + // data, + // fields: field.fields, + // locale, + // localeRow, + // operation, + // path, + // relationshipRows, + // row, + // tableName, + // }); + // break; + // } case 'relationship': case 'upload': { @@ -225,10 +257,10 @@ export const traverseFields = async ({ if (Array.isArray(field.relationTo) && valueIsValueWithRelation(relation)) { relationRow[`${relation.relationTo}ID`] = relation.value; - relationshipRows.push(relationRow); + relationships.push(relationRow); } else { relationRow[`${field.relationTo}ID`] = relation; - relationshipRows.push(relationRow); + relationships.push(relationRow); } }); @@ -243,5 +275,5 @@ export const traverseFields = async ({ break; } } - })); + }); }; diff --git a/packages/db-postgres/src/create/types.ts b/packages/db-postgres/src/create/types.ts index a2398ffbd9..659ecd37f9 100644 --- a/packages/db-postgres/src/create/types.ts +++ b/packages/db-postgres/src/create/types.ts @@ -1,20 +1,29 @@ -import { Block } from 'payload/types'; - -export type ArrayRowPromise = (args: { parentID: string | number }) => Promise[]> - -export type ArrayRowPromisesMap = { - [tableName: string]: ArrayRowPromise +export type ArrayRowToInsert = { + columnName: string + parentTableName: string + row: Record, + locale: Record + arrays: { + [tableName: string]: ArrayRowToInsert[] + } } -export type BlockRowsToInsert = { - block: Block - rows: Record[] +export type BlockRowToInsert = { + row: Record, + locale: Record + arrays: { + [tableName: string]: ArrayRowToInsert[] + } } -export type RowInsertionGroup = { - row: Record - localeRow: Record - relationshipRows: Record[] - arrayRowPromises: ArrayRowPromisesMap, - blockRows: { [blockType: string]: BlockRowsToInsert } +export type RowToInsert = { + row: Record, + locale: Record, + relationships: Record[], + blocks: { + [blockType: string]: BlockRowToInsert[] + } + arrays: { + [tableName: string]: ArrayRowToInsert[] + } } diff --git a/packages/db-postgres/src/schema/build.ts b/packages/db-postgres/src/schema/build.ts index 680072c6d2..8c14941952 100644 --- a/packages/db-postgres/src/schema/build.ts +++ b/packages/db-postgres/src/schema/build.ts @@ -86,7 +86,8 @@ export const buildTable = ({ indexes, localesColumns, localesIndexes, - tableName, + newTableName: tableName, + parentTableName: tableName, relationships, })); diff --git a/packages/db-postgres/src/schema/traverseFields.ts b/packages/db-postgres/src/schema/traverseFields.ts index 3601f78904..c9e8b893c1 100644 --- a/packages/db-postgres/src/schema/traverseFields.ts +++ b/packages/db-postgres/src/schema/traverseFields.ts @@ -20,7 +20,8 @@ type Args = { indexes: Record IndexBuilder> localesColumns: Record localesIndexes: Record IndexBuilder> - tableName: string + newTableName: string + parentTableName: string relationships: Set } @@ -40,7 +41,8 @@ export const traverseFields = ({ indexes, localesColumns, localesIndexes, - tableName, + newTableName, + parentTableName, relationships, }: Args): Result => { let hasLocalizedField = false; @@ -115,14 +117,14 @@ export const traverseFields = ({ case 'array': { const baseColumns: Record = { _order: integer('_order').notNull(), - _parentID: parentIDColumnMap[parentIDColType]('_parent_id').references(() => adapter.tables[tableName].id).notNull(), + _parentID: parentIDColumnMap[parentIDColType]('_parent_id').references(() => adapter.tables[parentTableName].id).notNull(), }; if (field.localized && adapter.payload.config.localization) { baseColumns._locale = adapter.enums._locales('_locale').notNull(); } - const arrayTableName = `${tableName}_${toSnakeCase(field.name)}`; + const arrayTableName = `${newTableName}_${toSnakeCase(field.name)}`; const { arrayBlockRelations: subArrayBlockRelations } = buildTable({ adapter, @@ -135,9 +137,9 @@ export const traverseFields = ({ const arrayTableRelations = relations(adapter.tables[arrayTableName], ({ many, one }) => { const result: Record> = { - _parentID: one(adapter.tables[tableName], { + _parentID: one(adapter.tables[parentTableName], { fields: [adapter.tables[arrayTableName]._parentID], - references: [adapter.tables[tableName].id], + references: [adapter.tables[parentTableName].id], }), }; @@ -162,14 +164,14 @@ export const traverseFields = ({ const baseColumns: Record = { _order: integer('_order').notNull(), _path: text('_path').notNull(), - _parentID: parentIDColumnMap[parentIDColType]('_parent_id').references(() => adapter.tables[tableName].id).notNull(), + _parentID: parentIDColumnMap[parentIDColType]('_parent_id').references(() => adapter.tables[parentTableName].id).notNull(), }; if (field.localized && adapter.payload.config.localization) { baseColumns._locale = adapter.enums._locales('_locale').notNull(); } - const blockTableName = `${tableName}_${toSnakeCase(block.slug)}`; + const blockTableName = `${newTableName}_${toSnakeCase(block.slug)}`; if (!adapter.tables[blockTableName]) { const { arrayBlockRelations: subArrayBlockRelations } = buildTable({ @@ -181,9 +183,9 @@ export const traverseFields = ({ const blockTableRelations = relations(adapter.tables[blockTableName], ({ many, one }) => { const result: Record> = { - _parentID: one(adapter.tables[tableName], { + _parentID: one(adapter.tables[parentTableName], { fields: [adapter.tables[blockTableName]._parentID], - references: [adapter.tables[tableName].id], + references: [adapter.tables[parentTableName].id], }), }; @@ -223,7 +225,8 @@ export const traverseFields = ({ indexes, localesColumns, localesIndexes, - tableName, + newTableName: `${parentTableName}_${toSnakeCase(field.name)}`, + parentTableName, relationships, }); @@ -249,7 +252,8 @@ export const traverseFields = ({ indexes, localesColumns, localesIndexes, - tableName, + newTableName: `${parentTableName}_${toSnakeCase(tab.name)}`, + parentTableName, relationships, }); @@ -268,7 +272,8 @@ export const traverseFields = ({ indexes, localesColumns, localesIndexes, - tableName, + newTableName: parentTableName, + parentTableName, relationships, })); } @@ -290,7 +295,8 @@ export const traverseFields = ({ indexes, localesColumns, localesIndexes, - tableName, + newTableName: parentTableName, + parentTableName, relationships, })); break; diff --git a/packages/db-postgres/src/transform/traverseFields.ts b/packages/db-postgres/src/transform/traverseFields.ts index 8e30fc1254..1f94fbab2f 100644 --- a/packages/db-postgres/src/transform/traverseFields.ts +++ b/packages/db-postgres/src/transform/traverseFields.ts @@ -161,7 +161,7 @@ export const traverseFields = >({ if (relation) { // Handle hasOne Poly if (Array.isArray(field.relationTo)) { - const matchedRelation = Object.entries(relation).find(([, val]) => val !== null); + const matchedRelation = Object.entries(relation).find(([key, val]) => val !== null && !['order', 'id', 'parent'].includes(key)); if (matchedRelation) { const relationTo = matchedRelation[0].replace('ID', ''); @@ -234,7 +234,7 @@ export const traverseFields = >({ } } else { // Handle hasMany Poly - const matchedRelation = Object.entries(relation).find(([key, val]) => val !== null && key !== 'order'); + const matchedRelation = Object.entries(relation).find(([key, val]) => val !== null && !['order', 'parent', 'id'].includes(key)); if (matchedRelation) { const relationTo = matchedRelation[0].replace('ID', ''); diff --git a/src/utilities/timestamp.ts b/src/utilities/timestamp.ts new file mode 100644 index 0000000000..4e193d6081 --- /dev/null +++ b/src/utilities/timestamp.ts @@ -0,0 +1,5 @@ +export const timestamp = (label) => { + if (!process.env.PAYLOAD_TIME) process.env.PAYLOAD_TIME = String(new Date().getTime()); + const now = new Date(); + console.log(`[${now.getTime() - Number(process.env.PAYLOAD_TIME)}ms] ${label}`); +}; diff --git a/test/postgres/config.ts b/test/postgres/config.ts index 7cf820257b..216e772e88 100644 --- a/test/postgres/config.ts +++ b/test/postgres/config.ts @@ -1,6 +1,7 @@ import { CollectionConfig } from '../../src/collections/config/types'; import { buildConfigWithDefaults } from '../buildConfigWithDefaults'; import { devUser } from '../credentials'; +import { timestamp } from '../../src/utilities/timestamp'; export const Posts: CollectionConfig = { slug: 'posts',