microsoft/healthcare-shared-components

Public

mirrored from https://github.com/microsoft/healthcare-shared-componentsAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.0.0-1.0.79

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

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
6using System;
7using System.Linq;
8using Microsoft.CodeAnalysis.CSharp;
9using Microsoft.CodeAnalysis.CSharp.Syntax;
10using Microsoft.SqlServer.TransactSql.ScriptDom;
11using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
12
13namespace 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}