コード例 #1
0
        public static void Ctor_GivenDependentColumnsWithNullValue_ThrowsArgumentNullException()
        {
            const string expression = "lower(test_column)";
            var          columns    = new IDatabaseColumn[] { null };

            Assert.That(() => new DatabaseIndexColumn(expression, columns, IndexColumnOrder.Ascending), Throws.ArgumentNullException);
        }
コード例 #2
0
        /// <summary>
        /// Determines whether a given column is unique key column for the table.
        /// </summary>
        /// <param name="table">A database table.</param>
        /// <param name="column">A column in the given table.</param>
        /// <returns><c>true</c> if the column is a unique key column; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="table"/> is <c>null</c> or <paramref name="column"/> is <c>null</c>.</exception>
        protected static bool ColumnIsUniqueKey(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var uniqueKeys = table.UniqueKeys;

            if (uniqueKeys.Empty())
            {
                return(false);
            }

            foreach (var uniqueKey in uniqueKeys)
            {
                var ukColumns = uniqueKey.Columns;
                if (ukColumns.Count != 1)
                {
                    continue;
                }

                var ukColumn = ukColumns.First();
                if (column.Name.LocalName == ukColumn.Name.LocalName)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #3
0
        private static IEnumerable <AttributeListSyntax> BuildColumnAttributes(IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            if (propertyName == column.Name.LocalName)
            {
                return(Array.Empty <AttributeListSyntax>());
            }

            return(new[]
            {
                AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AliasAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(column.Name.LocalName)))))))
                    )
            });
        }
コード例 #4
0
        public static void Ctor_GivenColumnSetContainingNullColumn_ThrowsArgumentNullException()
        {
            Identifier            keyName = "test_key";
            const DatabaseKeyType keyType = DatabaseKeyType.Primary;
            var columns = new IDatabaseColumn[] { null };

            Assert.That(() => new PostgreSqlDatabaseKey(keyName, keyType, columns), Throws.ArgumentNullException);
        }
コード例 #5
0
        public static void Ctor_GivenIncludedColumnSetContainingNullColumn_ThrowsArgumentNullException()
        {
            Identifier indexName       = "test_index";
            const bool isUnique        = true;
            var        column          = Mock.Of <IDatabaseIndexColumn>();
            var        columns         = new[] { column };
            var        includedColumns = new IDatabaseColumn[] { null };

            Assert.That(() => new PostgreSqlDatabaseIndex(indexName, isUnique, columns, includedColumns), Throws.ArgumentNullException);
        }
コード例 #6
0
        /// <summary>
        /// Determines whether a column stores integer data.
        /// </summary>
        /// <param name="column">The column.</param>
        /// <returns><c>true</c> if the column stores integer data; otherwise <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="column"/> is <c>null</c>.</exception>
        protected static bool ColumnIsInteger(IDatabaseColumn column)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var integerTypes = new[] { DataType.BigInteger, DataType.Integer, DataType.SmallInteger };

            return(integerTypes.Contains(column.Type.DataType));
        }
コード例 #7
0
        public static void Ctor_GivenColumnsWithNullValue_ThrowsArgumentNullException()
        {
            Identifier tableName  = "test_table";
            var        columns    = new IDatabaseColumn[] { null };
            var        primaryKey = Option <IDatabaseKey> .None;
            var        uniqueKeys = Array.Empty <IDatabaseKey>();
            var        parentKeys = Array.Empty <IDatabaseRelationalKey>();
            var        childKeys  = Array.Empty <IDatabaseRelationalKey>();
            var        indexes    = Array.Empty <IDatabaseIndex>();
            var        checks     = Array.Empty <IDatabaseCheckConstraint>();
            var        triggers   = Array.Empty <IDatabaseTrigger>();

            Assert.That(() => new RelationalDatabaseTable(tableName, columns, primaryKey, uniqueKeys, parentKeys, childKeys, indexes, checks, triggers), Throws.ArgumentNullException);
        }
コード例 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MySqlDatabaseIndexColumn"/> class.
        /// </summary>
        /// <param name="expression">An expression that represents the index column.</param>
        /// <param name="column">A database column the index is dependent on.</param>
        /// <exception cref="ArgumentNullException"><paramref name="column"/> is <c>null</c>. Alternatively if <paramref name="expression"/> is <c>null</c>, empty or whitespace.</exception>
        public MySqlDatabaseIndexColumn(string expression, IDatabaseColumn column)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (expression.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(expression));
            }

            Expression       = expression;
            DependentColumns = new[] { column };
        }
コード例 #9
0
        /// <summary>
        /// Determines whether a given column is a primary key column for the table.
        /// </summary>
        /// <param name="table">A database table.</param>
        /// <param name="column">A column in the given table.</param>
        /// <returns><c>true</c> if the column is a primary key column; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="table"/> is <c>null</c> or <paramref name="column"/> is <c>null</c>.</exception>
        protected static bool ColumnIsPrimaryKey(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            return(table.PrimaryKey
                   .Where(pk => pk.Columns.Count == 1 &&
                          column.Name.LocalName == pk.Columns.First().Name.LocalName)
                   .IsSome);
        }
コード例 #10
0
        private PropertyDeclarationSyntax BuildColumn(IDatabaseColumn column, Option <IRelationalDatabaseTableComments> comment, string className)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (className.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(className));
            }

            var clrType      = column.Type.ClrType;
            var propertyName = NameTranslator.ColumnToPropertyName(className, column.Name.LocalName);

            var columnTypeSyntax = column.IsNullable
                ? NullableType(ParseTypeName(clrType.FullName))
                : ParseTypeName(clrType.FullName);

            if (clrType.Namespace == nameof(System) && SyntaxUtilities.TypeSyntaxMap.ContainsKey(clrType.Name))
            {
                columnTypeSyntax = column.IsNullable
                    ? NullableType(SyntaxUtilities.TypeSyntaxMap[clrType.Name])
                    : SyntaxUtilities.TypeSyntaxMap[clrType.Name];
            }

            var baseProperty = PropertyDeclaration(
                columnTypeSyntax,
                Identifier(propertyName)
                );

            var columnSyntax = baseProperty
                               .AddAttributeLists(BuildColumnAttributes(column, propertyName).ToArray())
                               .WithModifiers(SyntaxTokenList.Create(Token(SyntaxKind.PublicKeyword)))
                               .WithAccessorList(SyntaxUtilities.PropertyGetSetDeclaration)
                               .WithLeadingTrivia(BuildColumnComment(column.Name, comment));

            var isNotNullRefType = !column.IsNullable && !column.Type.ClrType.IsValueType;

            if (!isNotNullRefType)
            {
                return(columnSyntax);
            }

            return(columnSyntax
                   .WithInitializer(SyntaxUtilities.NotNullDefault)
                   .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
        }
コード例 #11
0
ファイル: DbmlFormatter.cs プロジェクト: fagan2888/Schematic
        private static bool ColumnIsUniqueKey(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            return(table.UniqueKeys
                   .Any(
                       uk => uk.Columns.Count == 1 &&
                       uk.Columns.Single().Name.LocalName == column.Name.LocalName
                       ));
        }
コード例 #12
0
ファイル: DbmlFormatter.cs プロジェクト: fagan2888/Schematic
        private static bool ColumnIsPrimaryKey(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            return(table.PrimaryKey
                   .Match(
                       pk => pk.Columns.Count == 1 &&
                       pk.Columns.Single().Name.LocalName == column.Name.LocalName,
                       () => false
                       ));
        }
コード例 #13
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PostgreSqlDatabaseIndexColumn"/> class.
        /// </summary>
        /// <param name="expression">An expression that represents the index column.</param>
        /// <param name="column">A database column the index is dependent on.</param>
        /// <param name="order">The sorting order applied to the index column.</param>
        /// <exception cref="ArgumentNullException"><paramref name="column"/> is <c>null</c>. Alternatively if <paramref name="expression"/> is <c>null</c>, empty or whitespace.</exception>
        /// <exception cref="ArgumentException"><paramref name="order"/> is an invalid enum value.</exception>
        public PostgreSqlDatabaseIndexColumn(string expression, IDatabaseColumn column, IndexColumnOrder order)
        {
            if (expression.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(expression));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (!order.IsValid())
            {
                throw new ArgumentException($"The { nameof(IndexColumnOrder) } provided must be a valid enum.", nameof(order));
            }

            Expression       = expression;
            DependentColumns = new[] { column };
            Order            = order;
        }
コード例 #14
0
        /// <summary>
        /// Determines whether a given column is a unique index column for the table.
        /// </summary>
        /// <param name="table">A database table.</param>
        /// <param name="column">A column in the given table.</param>
        /// <returns><c>true</c> if the column is a unique index column; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="table"/> is <c>null</c> or <paramref name="column"/> is <c>null</c>.</exception>
        protected static bool ColumnIsUniqueIndex(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var indexes = table.Indexes.Where(i => i.IsUnique).ToList();

            if (indexes.Empty())
            {
                return(false);
            }

            foreach (var index in indexes)
            {
                var columns = index.Columns;
                if (columns.Count > 1)
                {
                    continue;
                }

                var indexColumn      = columns.First();
                var dependentColumns = indexColumn.DependentColumns;
                if (dependentColumns.Count > 1)
                {
                    continue;
                }

                var dependentColumn = dependentColumns[0];
                if (dependentColumn.Name.LocalName == column.Name.LocalName)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #15
0
        private static IEnumerable <AttributeListSyntax> BuildColumnAttributes(IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            var columnAttributeArgs = new List <AttributeArgumentSyntax>();

            if (propertyName != column.Name.LocalName)
            {
                var quotedColumnName = LiteralExpression(
                    SyntaxKind.StringLiteralExpression,
                    Literal(column.Name.LocalName));
                columnAttributeArgs.Add(AttributeArgument(quotedColumnName));
            }
            columnAttributeArgs.Add(
                AttributeArgument(
                    AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        IdentifierName(nameof(ColumnAttribute.TypeName)),
                        Token(SyntaxKind.EqualsToken),
                        LiteralExpression(
                            SyntaxKind.StringLiteralExpression,
                            Literal(column.Type.TypeName.LocalName)))));

            return(new[]
            {
                AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(ColumnAttribute)),
                            AttributeArgumentList(
                                SeparatedList(columnAttributeArgs)))))
            });
        }
コード例 #16
0
ファイル: DbmlFormatter.cs プロジェクト: fagan2888/Schematic
        private static string RenderColumnLine(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var columnName = column.Name.ToVisibleName();

            var options = new List <string> {
                column.IsNullable ? "null" : "not null"
            };

            if (column.AutoIncrement.IsSome)
            {
                options.Add("increment");
            }

            if (ColumnIsPrimaryKey(table, column))
            {
                options.Add("primary key");
            }
            else if (ColumnIsUniqueKey(table, column))
            {
                options.Add("unique key");
            }

            column.DefaultValue.IfSome(def => options.Add("default: \"" + def.Replace("\"", "\\\"") + "\""));

            var columnOptions = options.Count > 0
                ? " [" + options.Join(", ") + "]"
                : string.Empty;

            return(Indent + columnName + " " + column.Type.Definition.RemoveQuotingCharacters() + columnOptions);
        }
コード例 #17
0
        /// <summary>
        /// Determines whether a given column is a foreign key column for the table.
        /// </summary>
        /// <param name="table">A database table.</param>
        /// <param name="column">A column in the given table.</param>
        /// <returns><c>true</c> if the column is a foreign key column; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="table"/> is <c>null</c> or <paramref name="column"/> is <c>null</c>.</exception>
        protected static bool ColumnIsForeignKey(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var foreignKeys = table.ParentKeys;

            if (foreignKeys.Empty())
            {
                return(false);
            }

            foreach (var foreignKey in foreignKeys)
            {
                if (foreignKey.ParentKey.KeyType != DatabaseKeyType.Primary)
                {
                    continue; // ormlite only supports FK to primary key
                }
                var childColumns = foreignKey.ChildKey.Columns;
                if (childColumns.Count > 1)
                {
                    continue;
                }

                var childColumn = childColumns.First();
                if (childColumn.Name.LocalName == column.Name.LocalName)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #18
0
        private async Task <bool> NullableColumnHasValueAsyncCore(IRelationalDatabaseTable table, IDatabaseColumn column,
                                                                  CancellationToken cancellationToken)
        {
            var sql = await GetNullableColumnHasValueQueryAsync(table.Name, column.Name).ConfigureAwait(false);

            return(await DbConnection.ExecuteScalarAsync <bool>(sql, cancellationToken).ConfigureAwait(false));
        }
コード例 #19
0
        /// <summary>
        /// Determines whether a nullable column has any non-null values.
        /// </summary>
        /// <param name="table">A database table.</param>
        /// <param name="column">A column from the table provided by <paramref name="table"/>.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns><c>true</c> if the column has any non-null values; otherwise <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="table"/> or <paramref name="column"/> is <c>null</c>.</exception>
        protected Task <bool> NullableColumnHasValueAsync(IRelationalDatabaseTable table, IDatabaseColumn column,
                                                          CancellationToken cancellationToken)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            return(NullableColumnHasValueAsyncCore(table, column, cancellationToken));
        }
コード例 #20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DatabaseIndexColumn"/> class.
 /// </summary>
 /// <param name="expression">A textual expression defining the index column.</param>
 /// <param name="column">A column that the index column is dependent upon.</param>
 /// <param name="order">The index column ordering.</param>
 /// <exception cref="ArgumentNullException"><paramref name="column"/> is <c>null</c>. Alternatively if <paramref name="expression"/> is <c>null</c>, empty or whitespace.</exception>
 /// <exception cref="ArgumentException"><paramref name="order"/> is an invalid enum.</exception>
 public DatabaseIndexColumn(string expression, IDatabaseColumn column, IndexColumnOrder order)
     : this(expression, new[] { column }, order)
 {
 }
コード例 #21
0
 public static void Ctor_GivenColumnSetContainingNullColumn_ThrowsArgumentNullException()
 {
     var columns = new IDatabaseColumn[] { null };
     Assert.That(() => new MySqlDatabasePrimaryKey(columns), Throws.ArgumentNullException);
 }
コード例 #22
0
        private static IEnumerable <AttributeListSyntax> BuildColumnAttributes(IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            var attributes = new List <AttributeListSyntax>();
            var clrType    = column.Type.ClrType;

            var isConstrainedType = clrType == typeof(string) || clrType == typeof(byte[]);

            if (isConstrainedType && column.Type.MaxLength > 0)
            {
                var maxLengthAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(MaxLengthAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(column.Type.MaxLength))))))));
                attributes.Add(maxLengthAttribute);
            }

            if (!clrType.IsValueType && !column.IsNullable)
            {
                var requiredAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(RequiredAttribute)))));
                attributes.Add(requiredAttribute);
            }

            column.AutoIncrement.IfSome(_ =>
            {
                var databaseGeneratedAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(DatabaseGeneratedAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            IdentifierName(nameof(DatabaseGeneratedOption)),
                                            IdentifierName(nameof(DatabaseGeneratedOption.Identity)))))))));
                attributes.Add(databaseGeneratedAttribute);
            });

            var columnAttributeArgs = new List <AttributeArgumentSyntax>();

            if (propertyName != column.Name.LocalName)
            {
                var quotedColumnName = LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(column.Name.LocalName));
                columnAttributeArgs.Add(AttributeArgument(quotedColumnName));
            }
            columnAttributeArgs.Add(
                AttributeArgument(
                    AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        IdentifierName(nameof(ColumnAttribute.TypeName)),
                        Token(SyntaxKind.EqualsToken),
                        LiteralExpression(
                            SyntaxKind.StringLiteralExpression,
                            Literal(column.Type.TypeName.LocalName))))
                );

            var columnAttribute = AttributeList(
                SingletonSeparatedList(
                    Attribute(
                        SyntaxUtilities.AttributeName(nameof(ColumnAttribute)),
                        AttributeArgumentList(
                            SeparatedList(columnAttributeArgs)))));

            attributes.Add(columnAttribute);

            return(attributes);
        }
コード例 #23
0
        private InvocationExpressionSyntax BuildTableColumnPropertyForBuilder(IRelationalDatabaseTable table, IDatabaseColumn column)
        {
            if (table == null)
            {
                throw new ArgumentNullException(nameof(table));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var schemaNamespace    = NameTranslator.SchemaToNamespace(table.Name);
            var className          = NameTranslator.TableToClassName(table.Name);
            var qualifiedClassName = !schemaNamespace.IsNullOrWhiteSpace()
                ? schemaNamespace + "." + className
                : className;

            var entity       = GetEntityBuilder(qualifiedClassName);
            var propertyName = NameTranslator.ColumnToPropertyName(className, column.Name.LocalName);
            var property     = InvocationExpression(
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    entity,
                    IdentifierName(nameof(EntityTypeBuilder.Property))))
                               .WithArgumentList(
                ArgumentList(
                    SingletonSeparatedList(
                        Argument(
                            SimpleLambdaExpression(
                                Parameter(
                                    Identifier(EntityLambdaParameterName)),
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    IdentifierName(EntityLambdaParameterName),
                                    IdentifierName(propertyName)))))));

            column.DefaultValue.IfSome(def =>
            {
                property = InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        property,
                        IdentifierName(nameof(RelationalPropertyBuilderExtensions.HasDefaultValue))))
                           .WithArgumentList(
                    ArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                LiteralExpression(
                                    SyntaxKind.StringLiteralExpression,
                                    Literal(def))))));
            });

            if (column.IsComputed && column is IDatabaseComputedColumn computedColumn)
            {
                computedColumn.Definition.IfSome(def =>
                {
                    property = InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            property,
                            IdentifierName(nameof(RelationalPropertyBuilderExtensions.HasComputedColumnSql))))
                               .WithArgumentList(
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    LiteralExpression(
                                        SyntaxKind.StringLiteralExpression,
                                        Literal(def))))));
                });
            }

            return(property);
        }
コード例 #24
0
        private IEnumerable <AttributeListSyntax> BuildColumnAttributes(IRelationalDatabaseTable table, IDatabaseColumn column, string propertyName)
        {
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }
            if (propertyName.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(propertyName));
            }

            var attributes = new List <AttributeListSyntax>();
            var clrType    = column.Type.ClrType;

            if (clrType == typeof(string) && column.Type.MaxLength > 0)
            {
                var maxLengthAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(StringLengthAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            Literal(column.Type.MaxLength))))))));
                attributes.Add(maxLengthAttribute);
            }

            if (!clrType.IsValueType && !column.IsNullable)
            {
                var requiredAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(RequiredAttribute)))));
                attributes.Add(requiredAttribute);
            }

            var isPrimaryKey = ColumnIsPrimaryKey(table, column);

            if (isPrimaryKey)
            {
                var primaryKeyAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(PrimaryKeyAttribute)))));
                attributes.Add(primaryKeyAttribute);
            }

            if (column.AutoIncrement.IsSome)
            {
                var autoIncrementAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AutoIncrementAttribute)))));
                attributes.Add(autoIncrementAttribute);
            }

            var isNonUniqueIndex = ColumnIsNonUniqueIndex(table, column);
            var isUniqueIndex    = ColumnIsUniqueIndex(table, column);
            var isIndex          = isNonUniqueIndex || isUniqueIndex;

            if (isIndex)
            {
                var indexAttribute = Attribute(
                    SyntaxUtilities.AttributeName(nameof(IndexAttribute))
                    );
                var indexAttributeList = AttributeList(SingletonSeparatedList(indexAttribute));

                if (isNonUniqueIndex)
                {
                    attributes.Add(indexAttributeList);
                }
                else
                {
                    var uniqueIndexAttribute = indexAttribute
                                               .WithArgumentList(
                        AttributeArgumentList(
                            SingletonSeparatedList(
                                AttributeArgument(
                                    LiteralExpression(SyntaxKind.TrueLiteralExpression)))));

                    var uniqueIndexAttributeList = AttributeList(SingletonSeparatedList(uniqueIndexAttribute));
                    attributes.Add(uniqueIndexAttributeList);
                }
            }

            var isUniqueKey = ColumnIsUniqueKey(table, column);

            if (isUniqueKey)
            {
                var uniqueKeyAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(UniqueAttribute)))));
                attributes.Add(uniqueKeyAttribute);
            }

            column.DefaultValue.IfSome(def =>
            {
                var defaultAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(DefaultAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(def))))))));
                attributes.Add(defaultAttribute);
            });

            var isForeignKey = ColumnIsForeignKey(table, column);

            if (isForeignKey)
            {
                var relationalKey = ColumnRelationalKey(table, column);
                if (relationalKey == null)
                {
                    throw new InvalidOperationException("Could not find parent key for foreign key relationship. Expected to find one for " + column.Name.LocalName + "." + column.Name.LocalName);
                }

                var parentTable     = relationalKey.ParentTable;
                var parentClassName = NameTranslator.TableToClassName(parentTable);
                // TODO check that this is not implicit -- i.e. there is a naming convention applied
                //      so explicitly declaring via [References(...)] may not be necessary

                var fkAttributeArgs = new List <AttributeArgumentSyntax>
                {
                    AttributeArgument(TypeOfExpression(ParseTypeName(parentClassName)))
                };

                relationalKey.ChildKey.Name.IfSome(fkName =>
                {
                    var foreignKeyNameArg = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(ForeignKeyAttribute.ForeignKeyName)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(fkName.LocalName))));
                    fkAttributeArgs.Add(foreignKeyNameArg);
                });

                if (relationalKey.DeleteAction != ReferentialAction.NoAction)
                {
                    var deleteAction          = ForeignKeyAction[relationalKey.DeleteAction];
                    var foreignKeyOnDeleteArg = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(ForeignKeyAttribute.OnDelete)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(deleteAction))));
                    fkAttributeArgs.Add(foreignKeyOnDeleteArg);
                }

                if (relationalKey.UpdateAction != ReferentialAction.NoAction)
                {
                    var updateAction          = ForeignKeyAction[relationalKey.UpdateAction];
                    var foreignKeyOnUpdateArg = AttributeArgument(
                        AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName(nameof(ForeignKeyAttribute.OnUpdate)),
                            Token(SyntaxKind.EqualsToken),
                            LiteralExpression(
                                SyntaxKind.StringLiteralExpression,
                                Literal(updateAction))));
                    fkAttributeArgs.Add(foreignKeyOnUpdateArg);
                }

                var foreignKeyAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(ForeignKeyAttribute)),
                            AttributeArgumentList(SeparatedList(fkAttributeArgs)))));
                attributes.Add(foreignKeyAttribute);
            }

            if (propertyName != column.Name.LocalName)
            {
                var aliasAttribute = AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            SyntaxUtilities.AttributeName(nameof(AliasAttribute)),
                            AttributeArgumentList(
                                SingletonSeparatedList(
                                    AttributeArgument(
                                        LiteralExpression(
                                            SyntaxKind.StringLiteralExpression,
                                            Literal(column.Name.LocalName))))))));
                attributes.Add(aliasAttribute);
            }

            return(attributes);
        }