microsoft/healthcare-shared-components
Publicmirrored from https://github.com/microsoft/healthcare-shared-componentsAvailable
tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Sql/CreateTableVisitor.cs
97lines · modecode
| 1 | // ------------------------------------------------------------------------------------------------- |
| 2 | // Copyright (c) Microsoft Corporation. All rights reserved. |
| 3 | // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. |
| 4 | // ------------------------------------------------------------------------------------------------- |
| 5 | |
| 6 | using System; |
| 7 | using System.Linq; |
| 8 | using Microsoft.CodeAnalysis.CSharp; |
| 9 | using Microsoft.CodeAnalysis.CSharp.Syntax; |
| 10 | using Microsoft.SqlServer.TransactSql.ScriptDom; |
| 11 | using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; |
| 12 | |
| 13 | namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator.Sql |
| 14 | { |
| 15 | /// <summary> |
| 16 | /// Visits a SQL AST, created a class for each CREATE TABLE statement. |
| 17 | /// </summary> |
| 18 | internal class CreateTableVisitor : SqlVisitor |
| 19 | { |
| 20 | public override int ArtifactSortOder => 0; |
| 21 | |
| 22 | public override void Visit(CreateTableStatement node) |
| 23 | { |
| 24 | string tableName = node.SchemaObjectName.BaseIdentifier.Value; |
| 25 | string schemaQualifiedTableName = $"{node.SchemaObjectName.SchemaIdentifier.Value}.{tableName}"; |
| 26 | string className = GetClassNameForTable(tableName); |
| 27 | |
| 28 | ClassDeclarationSyntax classDeclarationSyntax = |
| 29 | ClassDeclaration(className) |
| 30 | .WithModifiers(TokenList(Token(SyntaxKind.InternalKeyword))) |
| 31 | .WithBaseList( |
| 32 | BaseList( |
| 33 | SingletonSeparatedList<BaseTypeSyntax>( |
| 34 | SimpleBaseType( |
| 35 | IdentifierName("Table"))))) |
| 36 | .AddMembers( |
| 37 | ConstructorDeclaration( |
| 38 | Identifier(className)) |
| 39 | .WithModifiers( |
| 40 | TokenList( |
| 41 | Token(SyntaxKind.InternalKeyword))) |
| 42 | .WithInitializer( |
| 43 | ConstructorInitializer( |
| 44 | SyntaxKind.BaseConstructorInitializer, |
| 45 | ArgumentList( |
| 46 | SingletonSeparatedList( |
| 47 | Argument( |
| 48 | LiteralExpression( |
| 49 | SyntaxKind.StringLiteralExpression, |
| 50 | Literal(schemaQualifiedTableName))))))) |
| 51 | .WithBody(Block())) |
| 52 | .AddMembers(node.Definition.ColumnDefinitions.Select(CreatePropertyForColumn).ToArray()); |
| 53 | |
| 54 | FieldDeclarationSyntax field = CreateStaticFieldForClass(className, tableName); |
| 55 | |
| 56 | MembersToAdd.Add(field.AddSortingKey(this, tableName)); |
| 57 | MembersToAdd.Add(classDeclarationSyntax.AddSortingKey(this, tableName)); |
| 58 | |
| 59 | base.Visit(node); |
| 60 | } |
| 61 | |
| 62 | public override void Visit(CreateIndexStatement node) |
| 63 | { |
| 64 | string indexName = node.Name.Value; |
| 65 | |
| 66 | var indexClassName = IdentifierName("Index"); |
| 67 | FieldDeclarationSyntax indexNameField = |
| 68 | FieldDeclaration( |
| 69 | VariableDeclaration(indexClassName) |
| 70 | .AddVariables( |
| 71 | VariableDeclarator(Identifier(indexName)) |
| 72 | .WithInitializer( |
| 73 | EqualsValueClause( |
| 74 | ObjectCreationExpression(indexClassName).AddArgumentListArguments( |
| 75 | Argument( |
| 76 | LiteralExpression( |
| 77 | SyntaxKind.StringLiteralExpression, |
| 78 | Literal(indexName)))))))) |
| 79 | .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.ReadOnlyKeyword)); |
| 80 | |
| 81 | string tableClassName = GetClassNameForTable(node.OnName.BaseIdentifier.Value); |
| 82 | |
| 83 | var memberIndex = MembersToAdd.FindIndex(m => m is ClassDeclarationSyntax c && c.Identifier.ValueText == tableClassName); |
| 84 | |
| 85 | if (memberIndex < 0) |
| 86 | { |
| 87 | throw new InvalidOperationException($"Index '{node.Name.Value}' is declared on an unrecognized type '{node.OnName.BaseIdentifier.Value}'"); |
| 88 | } |
| 89 | |
| 90 | MembersToAdd[memberIndex] = ((ClassDeclarationSyntax)MembersToAdd[memberIndex]).AddMembers(indexNameField); |
| 91 | |
| 92 | base.Visit(node); |
| 93 | } |
| 94 | |
| 95 | private static string GetClassNameForTable(string tableName) => $"{tableName}Table"; |
| 96 | } |
| 97 | } |