Skip to content

Commit

Permalink
field names truncating removed, added for unique constraint, keeped f…
Browse files Browse the repository at this point in the history
…or relation names
  • Loading branch information
irvinzz committed Aug 4, 2024
1 parent ff642ae commit 420c116
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 37 deletions.
4 changes: 0 additions & 4 deletions packages/runtime/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,3 @@ export const PRISMA_MINIMUM_VERSION = '5.0.0';
* Prefix for auxiliary relation field generated for delegated models
*/
export const DELEGATE_AUX_RELATION_PREFIX = 'delegate_aux';

// Some database providers like postgres and mysql have default limit to the length of identifiers
// Here we use a conservative value that should work for most cases, and truncate names if needed
export const IDENTIFIER_NAME_MAX_LENGTH = 50 - DELEGATE_AUX_RELATION_PREFIX.length;
24 changes: 0 additions & 24 deletions packages/runtime/src/cross/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { lowerCaseFirst } from 'lower-case-first';
import { requireField, type ModelInfo, type ModelMeta } from '.';
import { IDENTIFIER_NAME_MAX_LENGTH } from '../constants';

/**
* Gets field names in a data model entity, filtering out internal fields.
Expand Down Expand Up @@ -76,26 +75,3 @@ export function getModelInfo<Throw extends boolean = false>(
export function isDelegateModel(modelMeta: ModelMeta, model: string) {
return !!getModelInfo(modelMeta, model)?.attributes?.some((attr) => attr.name === '@@delegate');
}

const shortNameMap = new Map<string, string[]>();
export function truncate(name: string) {
if (name.length <= IDENTIFIER_NAME_MAX_LENGTH) {
return name;
}

const shortName = name.slice(0, IDENTIFIER_NAME_MAX_LENGTH);
const entry = shortNameMap.get(shortName);
if (!entry) {
shortNameMap.set(shortName, [name]);
return `${shortName}_0`;
} else {
const index = entry.findIndex((n) => n === name);
if (index >= 0) {
return `${shortName}_${index}`;
} else {
const newIndex = entry.length;
entry.push(name);
return `${shortName}_${newIndex}`;
}
}
}
3 changes: 1 addition & 2 deletions packages/runtime/src/enhancements/delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
getModelInfo,
isDelegateModel,
resolveField,
truncate,
} from '../cross';
import type { CrudContract, DbClientContract } from '../types';
import type { InternalEnhancementOptions } from './create-enhancement';
Expand Down Expand Up @@ -1041,7 +1040,7 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
}

private makeAuxRelationName(model: ModelInfo) {
return `${DELEGATE_AUX_RELATION_PREFIX}_${truncate(lowerCaseFirst(model.name))}`;
return `${DELEGATE_AUX_RELATION_PREFIX}_${(lowerCaseFirst(model.name))}`;
}

private getModelName(model: string) {
Expand Down
40 changes: 33 additions & 7 deletions packages/schema/src/plugins/prisma/schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { getPrismaVersion } from '@zenstackhq/sdk/prisma';
import { match, P } from 'ts-pattern';
import { getIdFields } from '../../utils/ast-utils';

import { DELEGATE_AUX_RELATION_PREFIX, PRISMA_MINIMUM_VERSION, truncate } from '@zenstackhq/runtime';
import { DELEGATE_AUX_RELATION_PREFIX, PRISMA_MINIMUM_VERSION } from '@zenstackhq/runtime';
import {
getAttribute,
getAttributeArg,
Expand Down Expand Up @@ -82,6 +82,10 @@ const MODEL_PASSTHROUGH_ATTR = '@@prisma.passthrough';
const FIELD_PASSTHROUGH_ATTR = '@prisma.passthrough';
const PROVIDERS_SUPPORTING_NAMED_CONSTRAINTS = ['postgresql', 'mysql', 'cockroachdb'];

// Some database providers like postgres and mysql have default limit to the length of identifiers
// Here we use a conservative value that should work for most cases, and truncate names if needed
export const IDENTIFIER_NAME_MAX_LENGTH = 50 - DELEGATE_AUX_RELATION_PREFIX.length;

/**
* Generates Prisma schema file
*/
Expand Down Expand Up @@ -314,7 +318,7 @@ export class PrismaSchemaGenerator {

// generate an optional relation field in delegate base model to each concrete model
concreteModels.forEach((concrete) => {
const auxName = `${DELEGATE_AUX_RELATION_PREFIX}_${truncate(lowerCaseFirst(concrete.name))}`;
const auxName = `${DELEGATE_AUX_RELATION_PREFIX}_${(lowerCaseFirst(concrete.name))}`;
model.addField(auxName, new ModelFieldType(concrete.name, false, true));
});
}
Expand All @@ -335,7 +339,7 @@ export class PrismaSchemaGenerator {
const idFields = getIdFields(base);

// add relation fields
const relationField = `${DELEGATE_AUX_RELATION_PREFIX}_${truncate(lowerCaseFirst(base.name))}`;
const relationField = `${DELEGATE_AUX_RELATION_PREFIX}_${(lowerCaseFirst(base.name))}`;
model.addField(relationField, base.name, [
new PrismaFieldAttribute('@relation', [
new PrismaAttributeArg(
Expand Down Expand Up @@ -401,7 +405,7 @@ export class PrismaSchemaGenerator {
// e.g., delegate_aux_User_myAsset_Video
const auxRelationName = `${dataModel.name}_${field.name}_${concrete.name}`;
const auxRelationField = model.addField(
`${DELEGATE_AUX_RELATION_PREFIX}_${truncate(auxRelationName)}`,
`${DELEGATE_AUX_RELATION_PREFIX}_${this.truncate(auxRelationName)}`,
new ModelFieldType(concrete.name, field.type.array, field.type.optional)
);

Expand Down Expand Up @@ -483,15 +487,15 @@ export class PrismaSchemaGenerator {

// fix its name
const addedFkFieldName = `${dataModel.name}_${origForeignKey.name}_${concreteModel.name}`;
addedFkField.name = `${DELEGATE_AUX_RELATION_PREFIX}_${truncate(addedFkFieldName)}`;
addedFkField.name = `${DELEGATE_AUX_RELATION_PREFIX}_${(addedFkFieldName)}`;

// we also need to make sure `@unique` constraint's `map` parameter is fixed to avoid conflict
const uniqueAttr = addedFkField.attributes.find(
(attr) => (attr as PrismaFieldAttribute).name === '@unique'
) as PrismaFieldAttribute;
if (uniqueAttr) {
const mapArg = uniqueAttr.args.find((arg) => arg.name === 'map');
const constraintName = `${addedFkField.name}_unique`;
const constraintName = `${this.truncate(addedFkField.name)}_unique`;
if (mapArg) {
mapArg.value = new AttributeArgValue('String', constraintName);
} else {
Expand Down Expand Up @@ -548,6 +552,28 @@ export class PrismaSchemaGenerator {
}
}

private truncate(name: string) {
if (name.length <= IDENTIFIER_NAME_MAX_LENGTH) {
return name;
}

const shortName = name.slice(0, IDENTIFIER_NAME_MAX_LENGTH);
const entry = this.shortNameMap.get(shortName);
if (!entry) {
this.shortNameMap.set(shortName, [name]);
return `${shortName}_0`;
} else {
const index = entry.findIndex((n) => n === name);
if (index >= 0) {
return `${shortName}_${index}`;
} else {
const newIndex = entry.length;
entry.push(name);
return `${shortName}_${newIndex}`;
}
}
}

private nameRelationsInheritedFromDelegate(model: PrismaDataModel, decl: DataModel) {
if (this.mode !== 'logical') {
return;
Expand Down Expand Up @@ -594,7 +620,7 @@ export class PrismaSchemaGenerator {
// relation name format: delegate_aux_[relationType]_[oppositeRelationField]_[concrete]
const relAttr = getAttribute(f, '@relation');
const name = `${fieldType.name}_${oppositeRelationField.name}_${decl.name}`;
const relName = `${DELEGATE_AUX_RELATION_PREFIX}_${truncate(name)}`;
const relName = `${DELEGATE_AUX_RELATION_PREFIX}_${this.truncate(name)}`;

if (relAttr) {
const nameArg = getAttributeArg(relAttr, 'name');
Expand Down

0 comments on commit 420c116

Please sign in to comment.