Skip to content

Commit

Permalink
Merge branch 'alpha' of github.com:prisma/prisma into alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
ejoebstl committed Feb 4, 2019
2 parents 6991e70 + 43d0fb8 commit 102a836
Show file tree
Hide file tree
Showing 19 changed files with 258 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ case class JdbcDeployMutactionExecutor(builder: JdbcDeployDatabaseMutationBuilde
case x: DeleteRelationTable => DeleteRelationInterpreter(builder).execute(x, schemaBeforeMigration)
case x: CreateInlineRelation => CreateInlineRelationInterpreter(builder).execute(x, schemaBeforeMigration)
case x: DeleteInlineRelation => DeleteInlineRelationInterpreter(builder).execute(x, schemaBeforeMigration)
case x: UpdateInlineRelation => UpdateInlineRelationInterpreter(builder).execute(x, schemaBeforeMigration)
}

runAttached(mutaction.project, action)
Expand All @@ -74,6 +75,7 @@ case class JdbcDeployMutactionExecutor(builder: JdbcDeployDatabaseMutationBuilde
case x: DeleteRelationTable => DeleteRelationInterpreter(builder).rollback(x, schemaBeforeMigration)
case x: CreateInlineRelation => CreateInlineRelationInterpreter(builder).rollback(x, schemaBeforeMigration)
case x: DeleteInlineRelation => DeleteInlineRelationInterpreter(builder).rollback(x, schemaBeforeMigration)
case x: UpdateInlineRelation => UpdateInlineRelationInterpreter(builder).rollback(x, schemaBeforeMigration)
}

runAttached(mutaction.project, action)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,21 @@ case class DeleteInlineRelationInterpreter(builder: JdbcDeployDatabaseMutationBu
)
}
}

case class UpdateInlineRelationInterpreter(builder: JdbcDeployDatabaseMutationBuilder) extends SqlMutactionInterpreter[UpdateInlineRelation] {
override def execute(mutaction: UpdateInlineRelation, schemaBeforeMigration: DatabaseSchema) = {
builder.renameColumn(
project = mutaction.project,
tableName = mutaction.previous.relationTableName,
oldColumnName = mutaction.previous.inlineManifestation.get.referencingColumn,
newColumnName = mutaction.next.inlineManifestation.get.referencingColumn
)
}

override def rollback(mutaction: UpdateInlineRelation, schemaBeforeMigration: DatabaseSchema) = {
execute(
UpdateInlineRelation(project = mutaction.project, previous = mutaction.next, next = mutaction.previous),
schemaBeforeMigration
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ object MongoAnyMutactionInterpreter extends MongoMutactionInterpreter[DeployMuta
case x: DeleteRelationTable => DeleteRelationInterpreter.execute(x)
case x: CreateInlineRelation => CreateInlineRelationInterpreter.execute(x)
case x: DeleteInlineRelation => DeleteInlineRelationInterpreter.execute(x)
case x: UpdateInlineRelation => NoAction.unit
}
}

Expand All @@ -41,6 +42,7 @@ object MongoAnyMutactionInterpreter extends MongoMutactionInterpreter[DeployMuta
case x: DeleteRelationTable => DeleteRelationInterpreter.execute(x)
case x: CreateInlineRelation => CreateInlineRelationInterpreter.rollback(x)
case x: DeleteInlineRelation => DeleteInlineRelationInterpreter.rollback(x)
case x: UpdateInlineRelation => NoAction.unit
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ case class UpdateRelationTable(project: Project, previousRelation: Relation, nex

case class CreateInlineRelation(project: Project, relation: Relation, model: Model, references: Model, column: String) extends DeployMutaction
case class DeleteInlineRelation(project: Project, relation: Relation, model: Model, references: Model, column: String) extends DeployMutaction
case class UpdateInlineRelation(project: Project, previous: Relation, next: Relation) extends DeployMutaction
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,22 @@ case class MigrationStepMapperImpl(project: Project) extends MigrationStepMapper
createRelation(nextRelation)
)

case (_: EmbeddedRelationLink, _: EmbeddedRelationLink) =>
Vector(
deleteRelation(previousRelation),
createRelation(nextRelation)
)
case (previousLink: EmbeddedRelationLink, nextLink: EmbeddedRelationLink) =>
val previousModel = previousSchema.getModelByName_!(previousLink.inTableOfModelName)
val nextModel = nextSchema.getModelByName_!(nextLink.inTableOfModelName)
val tableDidNotChange = previousModel.stableIdentifier == nextModel.stableIdentifier

if (tableDidNotChange) {
Vector(
UpdateInlineRelation(project, previousRelation, nextRelation)
)
} else {
Vector(
deleteRelation(previousRelation),
createRelation(nextRelation)
)
}

case (_: RelationTable, _: RelationTable) =>
Vector(
UpdateRelationTable(project, previousRelation, nextRelation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class PubSubRouterAltSpec
router.router.routees.length shouldEqual 1

system.stop(probe.ref)
Thread.sleep(50)
Thread.sleep(500)
router.router.routees.length shouldEqual 0
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.prisma.deploy.migration.inference

import com.prisma.deploy.schema.UpdatedRelationAmbiguous
import com.prisma.shared.models.FieldBehaviour._
import com.prisma.shared.models._

trait MigrationStepsInferrer {
Expand All @@ -19,6 +20,8 @@ object MigrationStepsInferrer {
case class MigrationStepsInferrerImpl(previousSchema: Schema, nextSchema: Schema, renames: SchemaMapping) {
import com.prisma.util.Diff._

val isMigrationFromV1ToV2 = previousSchema.isLegacy && nextSchema.isV2

/**
* The following evaluation order considers all interdependencies:
* - Delete Relation
Expand Down Expand Up @@ -111,13 +114,34 @@ case class MigrationStepsInferrerImpl(previousSchema: Schema, nextSchema: Schema
nextField <- nextModel.fields.toVector
previousFieldName = renames.getPreviousFieldName(nextModel.name, nextField.name)
previousField <- previousModel.getFieldByName(previousFieldName)
if didSomethingChange(previousField.template, nextField.template)(_.name,
_.typeIdentifier,
_.isUnique,
_.isRequired,
_.isList,
_.manifestation,
_.behaviour)
didSomethingChangeInTheField = didSomethingChange(previousField.template, nextField.template)(
_.name,
_.typeIdentifier,
_.isUnique,
_.isRequired,
_.isList,
_.manifestation
)
didBehaviourChange = if (isMigrationFromV1ToV2) {
// this block just exists to ignore phantom changes that are only inferred during migration from v1 to v2
// TODO: remove this special casing once we remove the suppport for migrating from v1 to v2. Then we can just do the same things as with the checks above.
import ReservedFields._
() match {
case _ if previousField.name == createdAtFieldName && nextField.behaviour.contains(CreatedAtBehaviour) =>
false
case _ if previousField.name == updatedAtFieldName && nextField.behaviour.contains(UpdatedAtBehaviour) =>
false
case _ if previousField.name == idFieldName && nextField.behaviour.contains(IdBehaviour(IdStrategy.Auto)) =>
false
case _ if previousField.isScalarList && nextField.behaviour.contains(ScalarListBehaviour(ScalarListStrategy.Relation)) =>
false
case _ =>
previousField.behaviour != nextField.behaviour
}
} else {
previousField.behaviour != nextField.behaviour
}
if didSomethingChangeInTheField || didBehaviourChange
} yield {
UpdateField(
model = previousModelName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.prisma.deploy.migration.DirectiveTypes.{MongoInlineRelationDirective,
import com.prisma.deploy.migration.validation._
import com.prisma.deploy.schema.RelationNameNeeded
import com.prisma.deploy.validation.NameConstraints
import com.prisma.shared.models.ConnectorCapability.{LegacyDataModelCapability, MigrationsCapability, RelationLinkListCapability}
import com.prisma.shared.models.ConnectorCapability.{LegacyDataModelCapability, MigrationsCapability, RelationLinkListCapability, RelationLinkTableCapability}
import com.prisma.shared.models.FieldBehaviour.{IdBehaviour, IdStrategy}
import com.prisma.shared.models.Manifestations._
import com.prisma.shared.models.{OnDelete, RelationSide, ReservedFields, _}
Expand Down Expand Up @@ -304,7 +304,7 @@ case class SchemaInferrerImpl(
case (None, None) if relationField.isList => manifestationForField(relatedField.tpe, relatedField, relationName)
case (_, None) => manifestationForField(prismaType, relationField, relationName)
case (None, _) => manifestationForField(relatedField.tpe, relatedField, relationName)
case (_, _) => sys.error("must not happen")
case (_, _) => sys.error("Must not happen.")
}

case None =>
Expand All @@ -325,17 +325,15 @@ case class SchemaInferrerImpl(

private def manifestationForField(prismaType: PrismaType, relationField: RelationalPrismaField, relationName: String): Option[RelationLinkManifestation] = {
val activeStrategy = relationField.strategy match {
case Some(strat) => strat
case Some(strat) => strat
case None if prismaSdl.relationTable(relationName).isDefined => RelationStrategy.Table
case None if relationField.hasManyToManyRelation && capabilities.has(RelationLinkTableCapability) => RelationStrategy.Table
case None if relationField.hasManyToManyRelation && capabilities.has(RelationLinkListCapability) => RelationStrategy.Inline
case None if relationField.hasOneToManyRelation && relationField.isOne => RelationStrategy.Inline
case None =>
if (capabilities.has(RelationLinkListCapability)) {
RelationStrategy.Inline
} else if (relationField.hasManyToManyRelation) {
RelationStrategy.Table
} else if (relationField.hasOneToManyRelation && relationField.isOne) {
RelationStrategy.Inline
} else {
sys.error("One to one relations must not have the AUTO strategy")
}
sys.error(
s"The datamodel validation should have required an explicit strategy here. Relation field was ${relationField.name} and related field was ${relationField.relatedField
.map(_.name)}")
}

activeStrategy match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ object DeployWarning {
def global(description: String): DeployWarning = {
DeployWarning("Global", description, None)
}

def apply(`type`: String, field: String, description: String): DeployWarning = {
DeployWarning(`type`, description, Some(field))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ case class RelationalPrismaField(
def hasOneToManyRelation: Boolean = (isList && relatedField.forall(_.isOne)) || (isOne && relatedField.forall(_.isList))
def hasOneToOneRelation: Boolean = isOne && relatedField.exists(_.isOne)
def isOne: Boolean = !isList
def oneRelationField = if (isOne) Some(this) else relatedField
def oneRelationField = if (isOne) Some(this) else relatedField.filter(_.isOne)
}

case class PrismaEnum(name: String, values: Vector[String])(sdl: PrismaSdl)
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ object RelationDirective extends FieldDirective[RelationDirectiveData] {
override def postValidate(dataModel: PrismaSdl, capabilities: ConnectorCapabilities): Vector[DeployError] = {
validateIfRequiredStrategyIsProvided(dataModel, capabilities) ++
validateBackRelationFields(dataModel, capabilities) ++
validateStrategyIsProvidedExactlyOnce(dataModel, capabilities)
validateStrategyIsProvidedExactlyOnce(dataModel, capabilities) ++
validateIfProvidedStrategiesAreSupported(dataModel, capabilities)
}

private def validateBackRelationFields(dataModel: PrismaSdl, capabilities: ConnectorCapabilities): Vector[DeployError] = {
Expand All @@ -67,15 +68,14 @@ object RelationDirective extends FieldDirective[RelationDirectiveData] {
}

private def validateIfRequiredStrategyIsProvided(dataModel: PrismaSdl, capabilities: ConnectorCapabilities): Vector[DeployError] = {
val isMongo = capabilities.has(RelationLinkListCapability)
for {
modelType <- dataModel.modelTypes
relationField <- modelType.relationFields
relatedType = relationField.relatedType
relatedField = relationField.relatedField
strategies = relationField.strategy ++ relatedField.flatMap(_.strategy)
if strategies.isEmpty
if isMongo || relationField.hasOneToOneRelation
if capabilities.has(RelationLinkListCapability) || relationField.hasOneToOneRelation
if modelType.isNotEmbedded && relatedType.isNotEmbedded
} yield {
val inlineMode = capabilities.has(JoinRelationLinksCapability).toOption("`@relation(link: INLINE)`")
Expand All @@ -85,6 +85,26 @@ object RelationDirective extends FieldDirective[RelationDirectiveData] {
}
}

private def validateIfProvidedStrategiesAreSupported(dataModel: PrismaSdl, capabilities: ConnectorCapabilities): Vector[DeployError] = {
for {
modelType <- dataModel.modelTypes
relationField <- modelType.relationFields
if relationField.isList
if relationField.strategy.contains(RelationStrategy.Inline)
if capabilities.hasNot(RelationLinkListCapability)
} yield {
val hint = relationField.relatedField match {
case Some(relatedField) if relatedField.isOne =>
s"You could fix this by putting `link: INLINE` on the opposite field `${relatedField.name}` in the model `${relatedField.tpe.name}`."
case _ =>
// currently a connector either supports Relation Link Lists or Link Tables. So we know it is available in this case.
require(capabilities.has(RelationLinkTableCapability))
s"You could fix this by using the strategy `TABLE` instead."
}
DeployError(modelType.name, relationField.name, s"This connector does not support the `INLINE` strategy for list relation fields. $hint")
}
}

override def value(document: Document, typeDef: ObjectTypeDefinition, fieldDef: FieldDefinition, capabilities: ConnectorCapabilities) = {
if (fieldDef.isRelationField(document)) {
val relationName = fieldDef.directive(name).flatMap(nameArgument.value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import com.prisma.deploy.connector.persistence.ProjectPersistence
import com.prisma.deploy.schema.InvalidProjectId
import com.prisma.messagebus.PubSubPublisher
import com.prisma.messagebus.pubsub.Only
import com.prisma.shared.models.ConnectorCapability.EmbeddedTypesCapability
import com.prisma.shared.models._

import scala.concurrent.{ExecutionContext, Future}
Expand All @@ -30,12 +29,11 @@ case class DeleteProjectMutation(
projectOpt <- projectPersistence.load(projectId)
project = validate(projectOpt)
_ <- projectPersistence.delete(projectId)
// _ <- if (deployConnector.isActive && !deployConnector.capabilities.has(EmbeddedTypesCapability)) deployConnector.deleteProjectDatabase(projectId)
// else Future.successful(())
_ <- if (connectorCapabilities.isDataModelV2) {
Future.successful(())
if (!deployConnector.capabilities.isMongo) deployConnector.deleteProjectDatabase(project.id)
else Future.successful(())
} else {
if (deployConnector.isActive && !deployConnector.capabilities.has(EmbeddedTypesCapability)) deployConnector.deleteProjectDatabase(project.id)
if (deployConnector.isActive && !deployConnector.capabilities.isMongo) deployConnector.deleteProjectDatabase(project.id)
else Future.successful(())
}
_ = invalidationPubSub.publish(Only(projectId), projectId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ case class DeployMutation(
functions <- FutureOr(getFunctionModels(inferredNextSchema, args.functions))
steps <- FutureOr(inferMigrationSteps(inferredNextSchema, schemaMapping))
destructiveWarnings <- FutureOr(checkForDestructiveChanges(inferredNextSchema, steps))
isMigratingFromV1ToV2 = project.schema.version.isEmpty && inferredNextSchema.version.contains(Schema.version.v2)
isMigratingFromV1ToV2 = project.schema.isLegacy && inferredNextSchema.isV2
v1ToV2Warning = isMigratingFromV1ToV2.toOption {
DeployWarning.global(
"You are migrating from the old datamodel syntax to the new one. Make sure that you understand the listed changes because the semantics are different now. Then perform the deployment with the `--force` flag.")
Expand Down
Loading

0 comments on commit 102a836

Please sign in to comment.