Skip to content

Commit

Permalink
refactor: deduplicate and abstract SQL schema building (#9987)
Browse files Browse the repository at this point in the history
### What?
Abstracts SQL schema building, significantly reducing code duplication
for SQLite / Postgres

db-sqlite lines count From:
```sh
 wc -l **/*.ts
      62 src/connect.ts
      32 src/countDistinct.ts
       9 src/createJSONQuery/convertPathToJSONTraversal.ts
      86 src/createJSONQuery/index.ts
      15 src/defaultSnapshot.ts
       6 src/deleteWhere.ts
      21 src/dropDatabase.ts
      15 src/execute.ts
     178 src/index.ts
     139 src/init.ts
      19 src/insert.ts
      19 src/requireDrizzleKit.ts
     544 src/schema/build.ts
      27 src/schema/createIndex.ts
      38 src/schema/getIDColumn.ts
      13 src/schema/idToUUID.ts
      28 src/schema/setColumnID.ts
     787 src/schema/traverseFields.ts
      18 src/schema/withDefault.ts
     248 src/types.ts
    2304 total
```

To:
```sh
wc -l **/*.ts
      62 src/connect.ts
      32 src/countDistinct.ts
       9 src/createJSONQuery/convertPathToJSONTraversal.ts
      86 src/createJSONQuery/index.ts
      15 src/defaultSnapshot.ts
       6 src/deleteWhere.ts
      21 src/dropDatabase.ts
      15 src/execute.ts
     180 src/index.ts
      39 src/init.ts
      19 src/insert.ts
      19 src/requireDrizzleKit.ts
     149 src/schema/buildDrizzleTable.ts
      32 src/schema/setColumnID.ts
     258 src/types.ts
     942 total
```

Builds abstract schema in shared drizzle package that later gets
converted by SQLite/ Postgres specific implementation into drizzle
schema.
This, apparently can also help here
#9953. It should be very
trivial to implement a MySQL adapter with this as well.
  • Loading branch information
r1tsuu authored Dec 16, 2024
1 parent c187bff commit 727fba7
Show file tree
Hide file tree
Showing 30 changed files with 1,872 additions and 2,486 deletions.
2 changes: 2 additions & 0 deletions packages/db-postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
packageName: '@payloadcms/db-postgres',
payload,
queryDrafts,
rawRelations: {},
rawTables: {},
rejectInitializing,
requireDrizzleKit,
resolveInitializing,
Expand Down
2 changes: 2 additions & 0 deletions packages/db-sqlite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ export function sqliteAdapter(args: Args): DatabaseAdapterObj<SQLiteAdapter> {
operators,
prodMigrations: args.prodMigrations,
push: args.push,
rawRelations: {},
rawTables: {},
relations: {},
relationshipsSuffix: args.relationshipsSuffix || '_rels',
schema: {},
Expand Down
138 changes: 19 additions & 119 deletions packages/db-sqlite/src/init.ts
Original file line number Diff line number Diff line change
@@ -1,138 +1,38 @@
import type { DrizzleAdapter } from '@payloadcms/drizzle/types'
import type { Init, SanitizedCollectionConfig } from 'payload'
import type { Init } from 'payload'

import { createTableName, executeSchemaHooks } from '@payloadcms/drizzle'
import { uniqueIndex } from 'drizzle-orm/sqlite-core'
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload'
import toSnakeCase from 'to-snake-case'
import { buildDrizzleRelations, buildRawSchema, executeSchemaHooks } from '@payloadcms/drizzle'

import type { BaseExtraConfig } from './schema/build.js'
import type { SQLiteAdapter } from './types.js'

import { buildTable } from './schema/build.js'
import { buildDrizzleTable } from './schema/buildDrizzleTable.js'
import { setColumnID } from './schema/setColumnID.js'

export const init: Init = async function init(this: SQLiteAdapter) {
let locales: [string, ...string[]] | undefined
await executeSchemaHooks({ type: 'beforeSchemaInit', adapter: this })
let locales: string[] | undefined

this.rawRelations = {}
this.rawTables = {}

if (this.payload.config.localization) {
locales = this.payload.config.localization.locales.map(({ code }) => code) as [
string,
...string[],
]
locales = this.payload.config.localization.locales.map(({ code }) => code)
}

this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
createTableName({
adapter: this as unknown as DrizzleAdapter,
config: collection,
})

if (collection.versions) {
createTableName({
adapter: this as unknown as DrizzleAdapter,
config: collection,
versions: true,
versionsCustomName: true,
})
}
})
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
const tableName = this.tableNameMap.get(toSnakeCase(collection.slug))
const config = this.payload.config

const baseExtraConfig: BaseExtraConfig = {}

if (collection.upload.filenameCompoundIndex) {
const indexName = `${tableName}_filename_compound_idx`

baseExtraConfig.filename_compound_index = (cols) => {
const colsConstraint = collection.upload.filenameCompoundIndex.map((f) => {
return cols[f]
})
return uniqueIndex(indexName).on(colsConstraint[0], ...colsConstraint.slice(1))
}
}
const adapter = this as unknown as DrizzleAdapter

if (collection.upload.filenameCompoundIndex) {
const indexName = `${tableName}_filename_compound_idx`

baseExtraConfig.filename_compound_index = (cols) => {
const colsConstraint = collection.upload.filenameCompoundIndex.map((f) => {
return cols[f]
})
return uniqueIndex(indexName).on(colsConstraint[0], ...colsConstraint.slice(1))
}
}

buildTable({
adapter: this,
disableNotNull: !!collection?.versions?.drafts,
disableUnique: false,
fields: collection.flattenedFields,
locales,
tableName,
timestamps: collection.timestamps,
versions: false,
})

if (collection.versions) {
const versionsTableName = this.tableNameMap.get(
`_${toSnakeCase(collection.slug)}${this.versionsSuffix}`,
)
const versionFields = buildVersionCollectionFields(config, collection, true)

buildTable({
adapter: this,
disableNotNull: !!collection.versions?.drafts,
disableUnique: true,
fields: versionFields,
locales,
tableName: versionsTableName,
timestamps: true,
versions: true,
})
}
buildRawSchema({
adapter,
setColumnID,
})

this.payload.config.globals.forEach((global) => {
const tableName = createTableName({
adapter: this as unknown as DrizzleAdapter,
config: global,
})

buildTable({
adapter: this,
disableNotNull: !!global?.versions?.drafts,
disableUnique: false,
fields: global.flattenedFields,
locales,
tableName,
timestamps: false,
versions: false,
})
await executeSchemaHooks({ type: 'beforeSchemaInit', adapter: this })

if (global.versions) {
const versionsTableName = createTableName({
adapter: this as unknown as DrizzleAdapter,
config: global,
versions: true,
versionsCustomName: true,
})
const config = this.payload.config
const versionFields = buildVersionGlobalFields(config, global, true)
for (const tableName in this.rawTables) {
buildDrizzleTable({ adapter, locales, rawTable: this.rawTables[tableName] })
}

buildTable({
adapter: this,
disableNotNull: !!global.versions?.drafts,
disableUnique: true,
fields: versionFields,
locales,
tableName: versionsTableName,
timestamps: true,
versions: true,
})
}
buildDrizzleRelations({
adapter,
})

await executeSchemaHooks({ type: 'afterSchemaInit', adapter: this })
Expand Down
Loading

0 comments on commit 727fba7

Please sign in to comment.