static FuzzyTableModel ParseTablePrimaryKey(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax expression, FuzzyDatabaseModel partialDatabase) { var innerModel = ParseTableChain(context, expression, partialDatabase); var arguments = AH.ParseArguments(context, expression); var keyColumnsArg = arguments["keyColumns"]; var nameArg = arguments["name"]; var clusteredArg = arguments["clustered"]; var columns = new Optional <ImmutableArray <(SortOrder, FuzzyColumnModel)> >(); if (AH.IsNull(context, keyColumnsArg)) { context.ReportDiagnostic(BuilderError.ArgumentNull("keyColumns").MakeDiagnostic(keyColumnsArg.GetLocation())); } else { var props = AH.ParseOrderedMultiProperty(context, keyColumnsArg); if (props.HasValue) { columns = AH.MatchColumns(context, props.Value, innerModel.Columns, ToString(innerModel.Name)); } } var fuzzyPrimaryKey = new FuzzyPrimaryKeyModel() { Columns = columns, IsClustered = AH.ParseConstantArgument(context, clusteredArg, () => AH.Just(true)), Name = AH.ParseConstantArgument(context, nameArg, () => (!innerModel.Name.HasValue || !innerModel.Schema.HasValue || !columns.HasValue || columns.Value.Any(c => !c.Item2.Name.HasValue)) ? new Optional <string>() : AH.Just(BuildDefaultKeyName("PK", innerModel.Schema.Value, innerModel.Name.Value, columns.Value.Select(c => c.Item2.Name.Value)))) }; innerModel.PrimaryKey = fuzzyPrimaryKey; return(innerModel); }
static void ParseDatabaseBuild(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax expression) { var innerModel = ParseDatabaseChain(context, expression); foreach (var table in innerModel.Tables) { foreach (var foreignKey in table.ForeignKeys) { if (foreignKey.ReferenceTableSelector.HasValue) { var referenceTable = innerModel.Tables.FirstOrDefault(t => t.Property.HasValue && t.Property.Value.Name == foreignKey.ReferenceTableSelector.Value.Item1.Name); if (referenceTable == null) { context.ReportDiagnostic(BuilderError.SelectorNotMappedToTable(foreignKey.ReferenceTableSelector.Value.Item1.Name, ToString(innerModel.Name)).MakeDiagnostic(foreignKey.ReferenceTableSelector.Value.Item2)); foreignKey.ReferenceTable = new Optional <FuzzyTableModel>(); break; } else { foreignKey.ReferenceTable = new Optional <FuzzyTableModel>(referenceTable); } foreignKey.ReferenceColumns = AH.MatchColumns(context, foreignKey.ReferenceColumnSelectors.Value, referenceTable.Columns, ToString(referenceTable.Name)); if (!foreignKey.Name.HasValue && table.Schema.HasValue && table.Name.HasValue && foreignKey.KeyColumns.HasValue && foreignKey.KeyColumns.Value.All(k => k.Model.Name.HasValue) && foreignKey.ReferenceTable.HasValue && foreignKey.ReferenceTable.Value.Schema.HasValue && foreignKey.ReferenceTable.Value.Name.HasValue) { foreignKey.Name = BuilderHelper.GenerateForeignKeyName(table.Schema.Value, table.Name.Value, foreignKey.KeyColumns.Value.Select(k => k.Model.Name.Value), foreignKey.ReferenceTable.Value.Schema.Value, foreignKey.ReferenceTable.Value.Name.Value); } if (foreignKey.KeyColumns.HasValue) { foreach (var columnPair in foreignKey.KeyColumns.Value.Zip(foreignKey.ReferenceColumns.Value, (l, r) => (l, r))) { if (columnPair.Item1.Model.Type.HasValue && columnPair.Item2.Model.Type.HasValue && columnPair.Item1.Model.Type.Value != columnPair.Item2.Model.Type.Value) { context.ReportDiagnostic(ModelBuilderError.ForeignKeyColumnTypesDontMatch(foreignKeyName: ToString(foreignKey.Name), keyColumnName: ToString(columnPair.Item1.Model.Name), keyColumnType: columnPair.Item1.Model.Type.Value.ToString(), referenceColumnName: ToString(columnPair.Item2.Model.Name), referenceColumnType: columnPair.Item2.Model.Type.Value.ToString()).MakeDiagnostic(columnPair.Item1.Location, new List <Location>() { columnPair.Item2.Location })); } } } } } } }
static FuzzyTableModel ParseTableForeignKey(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax expression, FuzzyDatabaseModel partialDatabase) { var innerModel = ParseTableChain(context, expression, partialDatabase); var arguments = AH.ParseArguments(context, expression); var keyColumnsArg = arguments["keyColumns"]; var referenceTableArg = arguments["referenceTable"]; var referenceColumnsArg = arguments["referenceColumns"]; var updateActionArg = arguments["updateAction"]; var deleteActionArg = arguments["deleteAction"]; var nameArg = arguments["name"]; var fuzzyForeignKey = new FuzzyForeignKeyModel(); if (AH.IsNull(context, keyColumnsArg)) { context.ReportDiagnostic(BuilderError.ArgumentNull("keyColumns").MakeDiagnostic(keyColumnsArg.Expression.GetLocation())); fuzzyForeignKey.KeyColumns = new Optional <ImmutableArray <(FuzzyColumnModel, Location)> >(); } else { var keyColumns = AH.ParseMultiProperty(context, keyColumnsArg); if (keyColumns.HasValue) { fuzzyForeignKey.KeyColumns = AH.MatchColumns(context, keyColumns.Value, innerModel.Columns, ToString(innerModel.Name)); } } if (AH.IsNull(context, referenceTableArg)) { context.ReportDiagnostic(BuilderError.ArgumentNull("referenceTable").MakeDiagnostic(referenceTableArg.Expression.GetLocation())); fuzzyForeignKey.ReferenceTableSelector = new Optional <(FuzzyProperty, Location)>(); } else { var selector = AH.ParseSelector(context, referenceTableArg); fuzzyForeignKey.ReferenceTableSelector = selector.HasValue ? AH.Just((selector.Value, (referenceTableArg.Expression as LambdaExpressionSyntax).Body.GetLocation())) : new Optional <(FuzzyProperty, Location)>(); } if (AH.IsNull(context, referenceColumnsArg)) { context.ReportDiagnostic(BuilderError.ArgumentNull("referenceColumns").MakeDiagnostic(referenceColumnsArg.Expression.GetLocation())); fuzzyForeignKey.ReferenceColumnSelectors = new Optional <ImmutableArray <(FuzzyProperty, Location)> >(); } else { fuzzyForeignKey.ReferenceColumnSelectors = AH.ParseMultiProperty(context, referenceColumnsArg); } if (fuzzyForeignKey.KeyColumns.HasValue && fuzzyForeignKey.ReferenceColumnSelectors.HasValue && fuzzyForeignKey.KeyColumns.Value.Length != fuzzyForeignKey.ReferenceColumnSelectors.Value.Length) { context.ReportDiagnostic(ModelBuilderError.ForeignKeyColumnCountsDontMatch().MakeDiagnostic(AH.DeconstructLambda(keyColumnsArg).Body.GetLocation(), new List <Location>() { AH.DeconstructLambda(referenceColumnsArg).Body.GetLocation() })); } fuzzyForeignKey.UpdateAction = AH.ParseConstantArgument(context, updateActionArg, () => AH.Just(ForeignKeyAction.Cascade)); fuzzyForeignKey.DeleteAction = AH.ParseConstantArgument(context, deleteActionArg, () => AH.Just(ForeignKeyAction.Cascade)); innerModel.ForeignKeys.Add(fuzzyForeignKey); return(innerModel); }
static FuzzyTableModel ParseTableIndex(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax expression, FuzzyDatabaseModel partialDatabase) { var innerModel = ParseTableChain(context, expression, partialDatabase); var arguments = AH.ParseArguments(context, expression); var keyColumnsArg = arguments["keyColumns"]; var uniqueArg = arguments["unique"]; var nameArg = arguments["name"]; var clusteredArg = arguments["clustered"]; var includedColumnsArg = arguments["includedColumns"]; var keyColumns = new Optional <ImmutableArray <(SortOrder, FuzzyColumnModel)> >(); if (AH.IsNull(context, keyColumnsArg)) { context.ReportDiagnostic(BuilderError.ArgumentNull("keyColumns").MakeDiagnostic(keyColumnsArg.GetLocation())); } else { var props = AH.ParseOrderedMultiProperty(context, keyColumnsArg); if (props.HasValue) { keyColumns = AH.MatchColumns(context, props.Value, innerModel.Columns, ToString(innerModel.Name)); } } var includedColumns = new Optional <ImmutableArray <FuzzyColumnModel> >(); if (!AH.IsNull(context, includedColumnsArg)) { var props = AH.ParseMultiProperty(context, includedColumnsArg); if (props.HasValue) { var match = AH.MatchColumns(context, props.Value, innerModel.Columns, ToString(innerModel.Name)); includedColumns = match.HasValue ? AH.Just(match.Value.Select(m => m.Item1).ToImmutableArray()) : new Optional <ImmutableArray <FuzzyColumnModel> >(); if (keyColumns.HasValue) { var column = props.Value.Select(v => ((FuzzyProperty, Location)?)v) .FirstOrDefault(i => keyColumns.Value.Any(k => k.Item2.Property.HasValue && k.Item2.Property.Value.Name == i.Value.Item1.Name)); if (column != null) { context.ReportDiagnostic(ModelBuilderError.IndexIncludedColumnAlreadyInKeyColumns(column.Value.Item1.Name).MakeDiagnostic(column.Value.Item2)); } } } } var fuzzyIndex = new FuzzyIndexModel() { KeyColumns = keyColumns, IsUnique = AH.ParseConstantArgument(context, uniqueArg, () => AH.Just(false)), IsClustered = AH.ParseConstantArgument(context, clusteredArg, () => AH.Just(false)), IncludedColumns = includedColumns, Name = AH.ParseConstantArgument(context, nameArg, () => (!innerModel.Name.HasValue || !innerModel.Schema.HasValue || !keyColumns.HasValue || keyColumns.Value.Any(c => !c.Item2.Name.HasValue)) ? new Optional <string>() : AH.Just(BuildDefaultKeyName("IX", innerModel.Schema.Value, innerModel.Name.Value, keyColumns.Value.Select(c => c.Item2.Name.Value)))) }; if (fuzzyIndex.IsClustered.HasValue && fuzzyIndex.IsClustered.Value == true) { var priorClustered = (innerModel.PrimaryKey?.IsClustered)?.HasValue == true && innerModel.PrimaryKey.IsClustered.Value ? innerModel.PrimaryKey.Name.Value : innerModel.Indexes.FirstOrDefault(i => i.IsClustered.HasValue && i.IsClustered.Value)?.Name.Value; if (priorClustered != null) { context.ReportDiagnostic(ModelBuilderError.IndexClusteredAlreadySpecified(priorClustered).MakeDiagnostic(clusteredArg.Expression.GetLocation())); } } innerModel.Indexes.Add(fuzzyIndex); return(innerModel); }