NpgsqlArrayTypeMapping.cs 4.3 KB
Newer Older
S
License  
Shay Rojansky 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#region License
// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph and the following two paragraphs appear in all copies.
//
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#endregion

using System;
S
Shay Rojansky 已提交
25
using System.Collections.Generic;
S
Shay Rojansky 已提交
26
using System.Text;
27

28
namespace Microsoft.EntityFrameworkCore.Storage.Internal
29
{
S
Shay Rojansky 已提交
30
    public sealed class NpgsqlArrayTypeMapping : RelationalTypeMapping
31
    {
S
Shay Rojansky 已提交
32
        public RelationalTypeMapping ElementMapping { get; }
S
Shay Rojansky 已提交
33

S
Shay Rojansky 已提交
34 35 36 37
        /// <summary>
        /// Creates the default array mapping (i.e. for the single-dimensional CLR array type)
        /// </summary>
        internal NpgsqlArrayTypeMapping(RelationalTypeMapping elementMapping)
38 39
            : this(elementMapping, elementMapping.ClrType.MakeArrayType())
        {}
S
Shay Rojansky 已提交
40 41

        internal NpgsqlArrayTypeMapping(RelationalTypeMapping elementMapping, Type arrayType)
42
            : base(GenerateArrayTypeName(elementMapping.StoreType), arrayType)
43
        {
S
Shay Rojansky 已提交
44
            ElementMapping = elementMapping;
45
        }
S
Shay Rojansky 已提交
46

S
Shay Rojansky 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
        static readonly Dictionary<string, string> SpecialArrayTypeNames = new Dictionary<string, string>
        {
            { "bigint",            "_int8"                },
            { "bit varying",       "_varbit"              },
            { "boolean",           "_bool"                },
            { "character",         "_char"                },
            { "character varying", "_varchar"             },
            { "double precision",  "_float8 "             },
            { "integer",           "_int4"                },
            { "int",               "_int4"                },
            { "numeric",           "_decimal"             },
            { "real",              "_float4"              },
            { "smallint",          "_int2"                },
            { "time with time zone", "_timetz"            },
            { "time without time zone", "_time"           },
            { "timestamp with time zone", "_timestamptz"  },
            { "timestamp without time zone", "_timestamp" }
        };

        static string GenerateArrayTypeName(string elementTypeName)
        {
            // In PostgreSQL, the array type name is the element type name prefixed by an underscore.
            // However, in some specific cases the user-displayed type name isn't the one used in the array type
            // (integer -> _int4, decimal -> _numeric) so we use a lookup table
            return SpecialArrayTypeNames.TryGetValue(elementTypeName, out var specialName)
                ? specialName
                : '_' + elementTypeName;
        }

S
Shay Rojansky 已提交
76
        public override RelationalTypeMapping Clone(string storeType, int? size)
77
            => new NpgsqlArrayTypeMapping(ElementMapping);
S
Shay Rojansky 已提交
78 79

        protected override string GenerateNonNullSqlLiteral(object value)
S
Shay Rojansky 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
        {
            // Only support one-dimensional arrays (at least for now)
            var arr = (Array)value;

            if (arr.Rank != 1)
                throw new NotSupportedException("Multidimensional array literals aren't supported yet");

            var sb = new StringBuilder();
            sb.Append("ARRAY[");
            for (var i = 0; i < arr.Length; i++)
            {
                sb.Append(ElementMapping.GenerateSqlLiteral(arr.GetValue(i)));
                if (i < arr.Length - 1)
                    sb.Append(",");
            }
            sb.Append("]");
            return sb.ToString();
        }
98 99
    }
}