From ddc692a9664548751ce86b0cbaf7cb820f1ca3ed Mon Sep 17 00:00:00 2001 From: Dan Ribbens Date: Tue, 15 Aug 2023 16:52:04 -0400 Subject: [PATCH 1/2] wip: postgres transactions --- packages/db-postgres/src/connect.ts | 8 +++- packages/db-postgres/src/index.ts | 13 +++--- .../src/transactions/beginTransaction.ts | 40 +++++++++++++++++++ .../src/transactions/commitTransaction.ts | 18 +++++++++ .../src/transactions/rollbackTransaction.ts | 12 ++++++ packages/db-postgres/src/types.ts | 1 + 6 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 packages/db-postgres/src/transactions/beginTransaction.ts create mode 100644 packages/db-postgres/src/transactions/commitTransaction.ts create mode 100644 packages/db-postgres/src/transactions/rollbackTransaction.ts diff --git a/packages/db-postgres/src/connect.ts b/packages/db-postgres/src/connect.ts index b3ed9b7700..15dd15835a 100644 --- a/packages/db-postgres/src/connect.ts +++ b/packages/db-postgres/src/connect.ts @@ -1,5 +1,6 @@ import fs from 'fs'; -import { sql, eq } from 'drizzle-orm'; +import { v4 as uuid } from 'uuid'; +import { eq, sql } from 'drizzle-orm'; import { drizzle } from 'drizzle-orm/node-postgres'; import type { Connect } from 'payload/dist/database/types'; import { Client, Pool } from 'pg'; @@ -9,7 +10,7 @@ import prompts from 'prompts'; import { jsonb, numeric, pgTable, varchar } from 'drizzle-orm/pg-core'; import type { PostgresAdapter } from './types'; -import { DrizzleDB, GenericEnum, GenericRelation, GenericTable } from './types'; +import { DrizzleDB } from './types'; // Migration table def in order to use query using drizzle const migrationsSchema = pgTable('payload_migrations', { @@ -31,6 +32,7 @@ export const connect: Connect = async function connect( }; try { + const sessionID = uuid(); if ('pool' in this && this.pool !== false) { const pool = new Pool(this.pool); db = drizzle(pool, { schema: this.schema }); @@ -43,6 +45,8 @@ export const connect: Connect = async function connect( await client.connect(); } + this.sessions[sessionID] = db; + if (process.env.PAYLOAD_DROP_DATABASE === 'true') { this.payload.logger.info('---- DROPPING TABLES ----'); await db.execute(sql`drop schema public cascade;\ncreate schema public;`); diff --git a/packages/db-postgres/src/index.ts b/packages/db-postgres/src/index.ts index f19bf4f1a5..b54ce89970 100644 --- a/packages/db-postgres/src/index.ts +++ b/packages/db-postgres/src/index.ts @@ -7,9 +7,9 @@ import { webpack } from './webpack'; import { Args, PostgresAdapter, PostgresAdapterResult } from './types'; // import { createGlobal } from './createGlobal'; // import { createVersion } from './createVersion'; -// import { beginTransaction } from './transactions/beginTransaction'; -// import { rollbackTransaction } from './transactions/rollbackTransaction'; -// import { commitTransaction } from './transactions/commitTransaction'; +import { beginTransaction } from './transactions/beginTransaction'; +import { rollbackTransaction } from './transactions/rollbackTransaction'; +import { commitTransaction } from './transactions/commitTransaction'; // import { queryDrafts } from './queryDrafts'; import { find } from './find'; // import { findGlobalVersions } from './findGlobalVersions'; @@ -31,6 +31,7 @@ export function postgresAdapter(args: Args): PostgresAdapterResult { // @ts-expect-error return createDatabaseAdapter({ ...args, + sessions: {}, enums: {}, relations: {}, tables: {}, @@ -41,9 +42,9 @@ export function postgresAdapter(args: Args): PostgresAdapterResult { init, webpack, createMigration, - // beginTransaction, - // rollbackTransaction, - // commitTransaction, + beginTransaction, + rollbackTransaction, + commitTransaction, // queryDrafts, findOne, find, diff --git a/packages/db-postgres/src/transactions/beginTransaction.ts b/packages/db-postgres/src/transactions/beginTransaction.ts new file mode 100644 index 0000000000..c47ecabc14 --- /dev/null +++ b/packages/db-postgres/src/transactions/beginTransaction.ts @@ -0,0 +1,40 @@ +import type { BeginTransaction } from 'payload/dist/database/types'; +import { PgTransactionConfig } from 'drizzle-orm/pg-core'; +import { v4 as uuid } from 'uuid'; +import { Client, Pool } from 'pg'; +import { drizzle } from 'drizzle-orm/node-postgres'; +import { sql } from 'drizzle-orm'; +import { DrizzleDB } from '../types'; + +export const beginTransaction: BeginTransaction = async function beginTransaction( + options: PgTransactionConfig = {}, +) { + let id; + try { + let db: DrizzleDB; + id = uuid(); + if ('pool' in this && this.pool !== false) { + const pool = new Pool(this.pool); + db = drizzle(pool, { schema: this.schema }); + await pool.connect(); + } + + if ('client' in this && this.client !== false) { + const client = new Client(this.client); + db = drizzle(client, { schema: this.schema }); + await client.connect(); + } + + this.sessions[id] = db; + + await db.execute(sql`BEGIN;`); + } catch (err) { + this.payload.logger.error( + `Error: cannot begin transaction: ${err.message}`, + err, + ); + process.exit(1); + } + + return id; +}; diff --git a/packages/db-postgres/src/transactions/commitTransaction.ts b/packages/db-postgres/src/transactions/commitTransaction.ts new file mode 100644 index 0000000000..afd32458c2 --- /dev/null +++ b/packages/db-postgres/src/transactions/commitTransaction.ts @@ -0,0 +1,18 @@ +import { CommitTransaction } from 'payload/dist/database/types'; +import { sql } from 'drizzle-orm'; + + +export const commitTransaction: CommitTransaction = async function commitTransaction(id) { + if (!this.sessions[id]) { + this.payload.logger.warn('commitTransaction called when no transaction exists'); + return; + } + + try { + await this.sessions[id].execute(sql`COMMIT;`); + } catch (err: unknown) { + await this.sessions[id].execute(sql`ROLLBACK;`); + } + + delete this.sessions[id]; +}; diff --git a/packages/db-postgres/src/transactions/rollbackTransaction.ts b/packages/db-postgres/src/transactions/rollbackTransaction.ts new file mode 100644 index 0000000000..388e4e2e81 --- /dev/null +++ b/packages/db-postgres/src/transactions/rollbackTransaction.ts @@ -0,0 +1,12 @@ +import { RollbackTransaction } from 'payload/dist/database/types'; +import { sql } from 'drizzle-orm'; + + +export const rollbackTransaction: RollbackTransaction = async function rollbackTransaction(id = '') { + if (!this.sessions[id]) { + this.payload.logger.warn('rollbackTransaction called when no transaction exists'); + return; + } + await this.sessions[id].execute(sql`ROLLBACK;`); + delete this.sessions[id]; +}; diff --git a/packages/db-postgres/src/types.ts b/packages/db-postgres/src/types.ts index b08b4ee0d8..f37c669e1f 100644 --- a/packages/db-postgres/src/types.ts +++ b/packages/db-postgres/src/types.ts @@ -40,6 +40,7 @@ export type GenericRelation = Relations> export type PostgresAdapter = DatabaseAdapter & Args & { db: DrizzleDB + sessions: Record enums: Record relations: Record tables: Record From 0296c51324fecb42f839e45fcc035312271e7306 Mon Sep 17 00:00:00 2001 From: Dan Ribbens Date: Tue, 22 Aug 2023 11:07:52 -0400 Subject: [PATCH 2/2] testing rollback --- .migrations/drizzle-snapshot.json | 935 ++++++++++++++++++++++++++++++ test/postgres/config.ts | 27 +- 2 files changed, 961 insertions(+), 1 deletion(-) create mode 100644 .migrations/drizzle-snapshot.json diff --git a/.migrations/drizzle-snapshot.json b/.migrations/drizzle-snapshot.json new file mode 100644 index 0000000000..abdc184558 --- /dev/null +++ b/.migrations/drizzle-snapshot.json @@ -0,0 +1,935 @@ +{ + "id": "4ae32e6a-885c-4034-ac10-923edac1ff6b", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "5", + "dialect": "pg", + "tables": { + "posts_my_array_my_sub_array": { + "name": "posts_my_array_my_sub_array", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "sub_sub_field": { + "name": "sub_sub_field", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "posts_my_array_my_sub_array__parent_id_posts_my_array_id_fk": { + "name": "posts_my_array_my_sub_array__parent_id_posts_my_array_id_fk", + "tableFrom": "posts_my_array_my_sub_array", + "tableTo": "posts_my_array", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_my_array": { + "name": "posts_my_array", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "posts_my_array__parent_id_posts_id_fk": { + "name": "posts_my_array__parent_id_posts_id_fk", + "tableFrom": "posts_my_array", + "tableTo": "posts", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_my_array_locales": { + "name": "posts_my_array_locales", + "schema": "", + "columns": { + "sub_field": { + "name": "sub_field", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "posts_my_array_locales__parent_id_posts_my_array_id_fk": { + "name": "posts_my_array_locales__parent_id_posts_my_array_id_fk", + "tableFrom": "posts_my_array_locales", + "tableTo": "posts_my_array", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_block1": { + "name": "posts_block1", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "non_localized_text": { + "name": "non_localized_text", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "posts_block1__parent_id_posts_id_fk": { + "name": "posts_block1__parent_id_posts_id_fk", + "tableFrom": "posts_block1", + "tableTo": "posts", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_block1_locales": { + "name": "posts_block1_locales", + "schema": "", + "columns": { + "localized_text": { + "name": "localized_text", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "posts_block1_locales__parent_id_posts_block1_id_fk": { + "name": "posts_block1_locales__parent_id_posts_block1_id_fk", + "tableFrom": "posts_block1_locales", + "tableTo": "posts_block1", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_block2_block_array": { + "name": "posts_block2_block_array", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "sub_block_array": { + "name": "sub_block_array", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "posts_block2_block_array__parent_id_posts_block2_id_fk": { + "name": "posts_block2_block_array__parent_id_posts_block2_id_fk", + "tableFrom": "posts_block2_block_array", + "tableTo": "posts_block2", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_block2": { + "name": "posts_block2", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "number": { + "name": "number", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "posts_block2__parent_id_posts_id_fk": { + "name": "posts_block2__parent_id_posts_id_fk", + "tableFrom": "posts_block2", + "tableTo": "posts", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_my_group_group_array": { + "name": "posts_my_group_group_array", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "group_array_text": { + "name": "group_array_text", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "posts_my_group_group_array__parent_id_posts_id_fk": { + "name": "posts_my_group_group_array__parent_id_posts_id_fk", + "tableFrom": "posts_my_group_group_array", + "tableTo": "posts", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts": { + "name": "posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "my_group_sub_field": { + "name": "my_group_sub_field", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "my_group_sub_group_sub_sub_field": { + "name": "my_group_sub_group_sub_sub_field", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_locales": { + "name": "posts_locales", + "schema": "", + "columns": { + "title": { + "name": "title", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "number": { + "name": "number", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "my_group_sub_field_localized": { + "name": "my_group_sub_field_localized", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "my_group_sub_group_sub_sub_field_localized": { + "name": "my_group_sub_group_sub_sub_field_localized", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "posts_locales__parent_id_posts_id_fk": { + "name": "posts_locales__parent_id_posts_id_fk", + "tableFrom": "posts_locales", + "tableTo": "posts", + "columnsFrom": [ + "_parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "posts_relationships": { + "name": "posts_relationships", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "pages_id": { + "name": "pages_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "people_id": { + "name": "people_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "posts_id": { + "name": "posts_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "posts_relationships_parent_id_posts_id_fk": { + "name": "posts_relationships_parent_id_posts_id_fk", + "tableFrom": "posts_relationships", + "tableTo": "posts", + "columnsFrom": [ + "parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "posts_relationships_pages_id_pages_id_fk": { + "name": "posts_relationships_pages_id_pages_id_fk", + "tableFrom": "posts_relationships", + "tableTo": "pages", + "columnsFrom": [ + "pages_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "posts_relationships_people_id_people_id_fk": { + "name": "posts_relationships_people_id_people_id_fk", + "tableFrom": "posts_relationships", + "tableTo": "people", + "columnsFrom": [ + "people_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "posts_relationships_posts_id_posts_id_fk": { + "name": "posts_relationships_posts_id_posts_id_fk", + "tableFrom": "posts_relationships", + "tableTo": "posts", + "columnsFrom": [ + "posts_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "pages": { + "name": "pages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "people": { + "name": "people", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "full_name": { + "name": "full_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "reset_password_token": { + "name": "reset_password_token", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "salt": { + "name": "salt", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "hash": { + "name": "hash", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "login_attempts": { + "name": "login_attempts", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_idx": { + "name": "email_idx", + "columns": [ + "email" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "payload_preferences": { + "name": "payload_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "payload_preferences_relationships": { + "name": "payload_preferences_relationships", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "payload_preferences_relationships_parent_id_payload_preferences_id_fk": { + "name": "payload_preferences_relationships_parent_id_payload_preferences_id_fk", + "tableFrom": "payload_preferences_relationships", + "tableTo": "payload_preferences", + "columnsFrom": [ + "parent_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "payload_preferences_relationships_users_id_users_id_fk": { + "name": "payload_preferences_relationships_users_id_users_id_fk", + "tableFrom": "payload_preferences_relationships", + "tableTo": "users", + "columnsFrom": [ + "users_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "payload_migrations": { + "name": "payload_migrations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "batch": { + "name": "batch", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "schema": { + "name": "schema", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "_locales": { + "name": "_locales", + "values": { + "en": "en", + "es": "es" + } + } + }, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/test/postgres/config.ts b/test/postgres/config.ts index 6a6b530f83..bab3f6db3a 100644 --- a/test/postgres/config.ts +++ b/test/postgres/config.ts @@ -1,3 +1,4 @@ +import { PayloadRequest } from 'payload/types'; import { CollectionConfig } from '../../src/collections/config/types'; import { buildConfigWithDefaults } from '../buildConfigWithDefaults'; @@ -14,6 +15,17 @@ export const Posts: CollectionConfig = { type: 'number', localized: true, }, + { + name: 'throw', + type: 'checkbox', + hooks: { + afterChange: [(value) => { + if (value) { + throw new Error('Throwing error for testing'); + } + }], + }, + }, { name: 'myArray', type: 'array', @@ -182,8 +194,12 @@ const config = buildConfigWithDefaults({ // password: devUser.password, // }, // }); + const req = {} as PayloadRequest; + + req.transactionID = await payload.db.beginTransaction(); const page1 = await payload.create({ + req, collection: 'pages', data: { slug: 'first', @@ -191,12 +207,16 @@ const config = buildConfigWithDefaults({ }); const page2 = await payload.create({ + req, collection: 'pages', data: { slug: 'second', }, }); + await payload.db.commitTransaction(req.transactionID); + + const findResult = await payload.find({ collection: 'pages', where: { slug: { equals: 'second' } }, @@ -214,7 +234,10 @@ const config = buildConfigWithDefaults({ }, }); + req.transactionID = await payload.db.beginTransaction(); + const person2 = await payload.create({ + req, collection: 'people', data: { fullName: 'Elliot DeNolf', @@ -222,8 +245,10 @@ const config = buildConfigWithDefaults({ }); const post = await payload.create({ + req, collection: 'posts', data: { + throw: true, title: 'hello', number: 1337, myGroup: { @@ -303,7 +328,7 @@ const config = buildConfigWithDefaults({ ], }, }); - + await payload.db.commitTransaction(req.transactionID); await payload.update({ collection: 'posts', id: post.id,