chore(database): use naming functions for identifiers in metadata relations

This commit is contained in:
Ben Irvin 2024-02-26 12:27:58 +01:00 committed by GitHub
parent c29dcf0999
commit 3cea9ffa5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 88 additions and 53 deletions

View File

@ -1,9 +1,8 @@
import _ from 'lodash/fp';
import * as identifiers from '../utils/identifiers';
import * as types from '../utils/types';
import {
createRelation,
getJoinTableName,
isPolymorphic,
isBidirectional,
isAnyToOne,
@ -17,7 +16,6 @@ import type { Attribute, Model } from '../types';
export type { Metadata, Meta };
export {
getJoinTableName,
isPolymorphic,
isBidirectional,
isAnyToOne,
@ -87,6 +85,6 @@ export const createMetadata = (models: Model[] = []): Metadata => {
};
const createAttribute = (attributeName: string, attribute: Attribute) => {
const columnName = _.snakeCase(attributeName);
const columnName = identifiers.getColumnName(attributeName);
Object.assign(attribute, { columnName });
};

View File

@ -1,5 +1,6 @@
import _ from 'lodash/fp';
import * as identifiers from '../utils/identifiers';
import type { Meta, Metadata } from './metadata';
import type { RelationalAttribute, Relation, MorphJoinTable } from '../types';
@ -15,6 +16,10 @@ interface JoinTableOptions {
meta: Meta;
}
const ID = identifiers.ID_COLUMN;
const ORDER = identifiers.ORDER_COLUMN;
const FIELD = identifiers.FIELD_COLUMN;
const hasInversedBy = (
attr: RelationalAttribute
): attr is RelationalAttribute & { inversedBy: boolean } => 'inversedBy' in attr;
@ -57,9 +62,6 @@ const isOwner = (
const shouldUseJoinTable = (attribute: RelationalAttribute) =>
!('useJoinTable' in attribute) || attribute.useJoinTable !== false;
export const getJoinTableName = (tableName: string, attributeName: string) =>
_.snakeCase(`${tableName}_${attributeName}_links`);
export const hasOrderColumn = (attribute: RelationalAttribute) => isAnyToMany(attribute);
export const hasInverseOrderColumn = (attribute: RelationalAttribute) =>
isBidirectional(attribute) && isManyToAny(attribute);
@ -209,8 +211,8 @@ const createManyToMany = (
* set info in the traget
*/
const createMorphToOne = (attributeName: string, attribute: Relation.MorphToOne) => {
const idColumnName = 'target_id';
const typeColumnName = 'target_type';
const idColumnName = identifiers.getJoinColumnAttributeIdName('target');
const typeColumnName = identifiers.getMorphColumnTypeName('target');
if ('morphColumn' in attribute && attribute.morphColumn) {
return;
@ -225,7 +227,7 @@ const createMorphToOne = (attributeName: string, attribute: Relation.MorphToOne)
},
idColumn: {
name: idColumnName,
referencedColumn: 'id',
referencedColumn: ID,
},
},
});
@ -246,19 +248,19 @@ const createMorphToMany = (
return;
}
const joinTableName = _.snakeCase(`${meta.tableName}_${attributeName}_morphs`);
const joinTableName = identifiers.getMorphTableName(meta.tableName, attributeName);
const joinColumnName = identifiers.getMorphColumnJoinTableIdName(meta.singularName);
const idColumnName = identifiers.getMorphColumnAttributeIdName(attributeName);
const typeColumnName = identifiers.getMorphColumnTypeName(attributeName);
const joinColumnName = _.snakeCase(`${meta.singularName}_id`);
const morphColumnName = _.snakeCase(`${attributeName}`);
const idColumnName = `${morphColumnName}_id`;
const typeColumnName = `${morphColumnName}_type`;
const fkIndexName = identifiers.getFkIndexName(joinTableName);
metadata.add({
singularName: joinTableName,
uid: joinTableName,
tableName: joinTableName,
attributes: {
id: {
[ID]: {
type: 'increments',
},
[joinColumnName]: {
@ -276,10 +278,10 @@ const createMorphToMany = (
[typeColumnName]: {
type: 'string',
},
field: {
[FIELD]: {
type: 'string',
},
order: {
[ORDER]: {
type: 'float',
column: {
unsigned: true,
@ -288,12 +290,12 @@ const createMorphToMany = (
},
indexes: [
{
name: `${joinTableName}_fk`,
name: fkIndexName,
columns: [joinColumnName],
},
{
name: `${joinTableName}_order_index`,
columns: ['order'],
columns: [ORDER],
},
{
name: `${joinTableName}_id_column_index`,
@ -302,10 +304,10 @@ const createMorphToMany = (
],
foreignKeys: [
{
name: `${joinTableName}_fk`,
name: fkIndexName,
columns: [joinColumnName],
referencedColumns: ['id'],
referencedTable: meta.tableName,
referencedColumns: [ID],
referencedTable: identifiers.getTableName(meta.tableName),
onDelete: 'CASCADE',
},
],
@ -317,7 +319,7 @@ const createMorphToMany = (
name: joinTableName,
joinColumn: {
name: joinColumnName,
referencedColumn: 'id',
referencedColumn: ID,
},
morphColumn: {
typeColumn: {
@ -325,7 +327,7 @@ const createMorphToMany = (
},
idColumn: {
name: idColumnName,
referencedColumn: 'id',
referencedColumn: ID,
},
},
orderBy: {
@ -390,7 +392,7 @@ const createJoinColum = (metadata: Metadata, { attribute, attributeName }: JoinC
const joinColumnName = _.snakeCase(`${attributeName}_id`);
const joinColumn = {
name: joinColumnName,
referencedColumn: 'id',
referencedColumn: ID,
referencedTable: targetMeta.tableName,
};
@ -430,30 +432,34 @@ const createJoinTable = (
return;
}
const joinTableName = getJoinTableName(meta.tableName, attributeName);
const joinTableName = identifiers.getJoinTableName(meta.tableName, attributeName);
const joinColumnName = _.snakeCase(`${meta.singularName}_id`);
let inverseJoinColumnName = _.snakeCase(`${targetMeta.singularName}_id`);
const joinColumnName = identifiers.getJoinColumnIdName(meta.singularName);
let inverseJoinColumnName = identifiers.getJoinColumnIdName(targetMeta.singularName);
// if relation is self referencing
if (joinColumnName === inverseJoinColumnName) {
inverseJoinColumnName = `inv_${inverseJoinColumnName}`;
inverseJoinColumnName = identifiers.getInverseJoinColumnIdName(targetMeta.singularName);
}
const orderColumnName = _.snakeCase(`${targetMeta.singularName}_order`);
let inverseOrderColumnName = _.snakeCase(`${meta.singularName}_order`);
const orderColumnName = identifiers.getOrderColumnName(targetMeta.singularName);
// TODO: should this plus the conditional below be rolled into one method?
let inverseOrderColumnName = identifiers.getOrderColumnName(meta.singularName);
// if relation is self referencing
if (attribute.relation === 'manyToMany' && orderColumnName === inverseOrderColumnName) {
inverseOrderColumnName = `inv_${inverseOrderColumnName}`;
inverseOrderColumnName = identifiers.getInverseOrderColumnName(meta.singularName);
}
const fkIndexName = identifiers.getFkIndexName(joinTableName); // TODO: joinTableName is multipart, can we re-use those parts instead of shortening the combined string?
const invFkIndexName = identifiers.getInverseFkIndexName(joinTableName);
const metadataSchema: Meta = {
singularName: joinTableName,
uid: joinTableName,
tableName: joinTableName,
attributes: {
id: {
[ID]: {
type: 'increments',
},
[joinColumnName]: {
@ -472,32 +478,32 @@ const createJoinTable = (
},
indexes: [
{
name: `${joinTableName}_fk`,
name: fkIndexName,
columns: [joinColumnName],
},
{
name: `${joinTableName}_inv_fk`,
name: invFkIndexName,
columns: [inverseJoinColumnName],
},
{
name: `${joinTableName}_unique`,
name: identifiers.getUniqueIndexName(joinTableName),
columns: [joinColumnName, inverseJoinColumnName],
type: 'unique',
},
],
foreignKeys: [
{
name: `${joinTableName}_fk`,
name: fkIndexName,
columns: [joinColumnName],
referencedColumns: ['id'],
referencedTable: meta.tableName,
referencedColumns: [ID],
referencedTable: meta.tableName, // TODO: does this need to be wrapped or do we trust meta.tableName to be the right shortened version?
onDelete: 'CASCADE',
},
{
name: `${joinTableName}_inv_fk`,
name: invFkIndexName,
columns: [inverseJoinColumnName],
referencedColumns: ['id'],
referencedTable: targetMeta.tableName,
referencedColumns: [ID],
referencedTable: targetMeta.tableName, // TODO: does this need to be wrapped or do we trust meta.tableName to be the right shortened version?
onDelete: 'CASCADE',
},
],
@ -509,11 +515,11 @@ const createJoinTable = (
name: joinTableName,
joinColumn: {
name: joinColumnName,
referencedColumn: 'id',
referencedColumn: ID,
},
inverseJoinColumn: {
name: inverseJoinColumnName,
referencedColumn: 'id',
referencedColumn: ID,
},
pivotColumns: [joinColumnName, inverseJoinColumnName],
} as any;
@ -528,7 +534,7 @@ const createJoinTable = (
},
};
metadataSchema.indexes.push({
name: `${joinTableName}_order_fk`,
name: identifiers.getOrderFkIndexName(joinTableName), // TODO: should we send joinTableName as parts?
columns: [orderColumnName],
});
joinTable.orderColumnName = orderColumnName;
@ -546,7 +552,7 @@ const createJoinTable = (
};
metadataSchema.indexes.push({
name: `${joinTableName}_order_inv_fk`,
name: identifiers.getOrderInverseFkIndexName(joinTableName),
columns: [inverseOrderColumnName],
});

View File

@ -38,7 +38,7 @@ export const getNameFromTokens = (tokens: NameToken[], max: number = MAX_DB_IDEN
};
// Generic name handler used by all helper functions
export const getName = (names: NameInput, options: NameOptions) => {
export const getName = (names: NameInput, options: NameOptions = {}) => {
const tokens = _.castArray(names).map((name) => {
return {
name,
@ -61,7 +61,6 @@ export const getName = (names: NameInput, options: NameOptions) => {
* TABLES
*/
// Get a base table name for a model
export const getTableName = (name: string, options?: NameOptions) => {
const tokens = [
{
@ -93,7 +92,10 @@ export const getMorphTableName = (collectionName: string, attributeName: string)
* COLUMNS
*/
// Regular relation join tables
export const getColumnName = (attributeName: string) => {
return getName(attributeName);
};
export const getJoinColumnEntityIdName = () => {
return getName(ENTITY, { suffix: 'id' });
};
@ -102,7 +104,25 @@ export const getJoinColumnAttributeIdName = (attributeName: string) => {
return getName(attributeName, { suffix: 'id' });
};
// Morph Join Tables
export const getJoinColumnIdName = (singularName: string) => {
return getName(singularName, { suffix: 'id' });
};
export const getInverseJoinColumnIdName = (singularName: string) => {
return getName(singularName, { suffix: 'id', prefix: 'inv' });
};
export const getOrderColumnName = (singularName: string) => {
return getName(singularName, { suffix: 'order' });
};
export const getInverseOrderColumnName = (singularName: string) => {
return getName(singularName, { suffix: 'order', prefix: 'inv' });
};
/**
* Morph Join Tables
*/
export const getMorphColumnJoinTableIdName = (singularName: string) => {
return getName(singularName, { suffix: 'id' });
};
@ -127,6 +147,18 @@ export const getFkIndexName = (names: NameInput) => {
return getName(names, { suffix: 'fk' });
};
export const getInverseFkIndexName = (names: NameInput) => {
return getName(names, { suffix: 'inv_fk' });
};
export const getOrderFkIndexName = (names: NameInput) => {
return getName(names, { suffix: 'order_fk' });
};
export const getOrderInverseFkIndexName = (names: NameInput) => {
return getName(names, { suffix: 'order_inv_fk' });
};
export const getUniqueIndexName = (names: NameInput) => {
return getName(names, { suffix: 'unique' });
};

View File

@ -1,7 +1,6 @@
import { getJoinTableName } from '../../metadata';
import type { Database } from '../..';
import type { Relation } from '../../types';
import { getJoinTableName } from '../../utils/identifiers';
type Link = {
relation: Relation.Bidirectional & { inversedBy: string };