Exemplo n.º 1
0
        public override LambdaExpression TryGetConvertExpression(Type @from, Type to)
        {
            if (@from != to &&
                @from.FullName == to.FullName &&
                @from.Namespace == "Microsoft.SqlServer.Types")
            {
                var p = Expression.Parameter(@from);

                return(Expression.Lambda(
                           Expression.Call(to, "Parse", new Type[0],
                                           Expression.New(
                                               MemberHelper.ConstructorOf(() => new SqlString("")),
                                               Expression.Call(
                                                   Expression.Convert(p, typeof(object)),
                                                   "ToString",
                                                   new Type[0]))),
                           p));
            }

            return(base.TryGetConvertExpression(@from, to));
        }
Exemplo n.º 2
0
        // TODO: move to SqlServerTypes.Configure?
        public override LambdaExpression?TryGetConvertExpression(Type @from, Type to)
        {
            if (@from != to &&
                @from.FullName == to.FullName &&
                @from.Namespace == SqlServerTypes.TypesNamespace)
            {
                var p = Expression.Parameter(@from);

                return(Expression.Lambda(
                           Expression.Call(to, "Parse", Array <Type> .Empty,
                                           Expression.New(
                                               MemberHelper.ConstructorOf(() => new SqlString("")),
                                               Expression.Call(
                                                   Expression.Convert(p, typeof(object)),
                                                   "ToString",
                                                   Array <Type> .Empty))),
                           p));
            }

            return(base.TryGetConvertExpression(@from, to));
        }
Exemplo n.º 3
0
        protected override void OnConnectionTypeCreated(Type connectionType)
        {
            BitStringType        = connectionType.Assembly.GetType("NpgsqlTypes.BitString", false);
            NpgsqlIntervalType   = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlInterval", false);
            NpgsqlInetType       = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlInet", true);
            NpgsqlTimeType       = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlTime", false);
            NpgsqlTimeTZType     = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlTimeTZ", false);
            NpgsqlPointType      = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlPoint", true);
            NpgsqlLSegType       = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlLSeg", true);
            NpgsqlBoxType        = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlBox", true);
            NpgsqlPathType       = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlPath", true);
            _npgsqlTimeStamp     = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlTimeStamp", false);
            _npgsqlTimeStampTZ   = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlTimeStampTZ", false);
            _npgsqlDate          = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlDate", true);
            _npgsqlDateTime      = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlDateTime", true);
            NpgsqlMacAddressType = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlMacAddress", false);
            NpgsqlCircleType     = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlCircle", true);
            NpgsqlPolygonType    = connectionType.Assembly.GetType("NpgsqlTypes.NpgsqlPolygon", true);

            if (BitStringType != null)
            {
                SetProviderField(BitStringType, BitStringType, "GetBitString");
            }
            if (NpgsqlIntervalType != null)
            {
                SetProviderField(NpgsqlIntervalType, NpgsqlIntervalType, "GetInterval");
            }
            if (NpgsqlTimeType != null)
            {
                SetProviderField(NpgsqlTimeType, NpgsqlTimeType, "GetTime");
            }
            if (NpgsqlTimeTZType != null)
            {
                SetProviderField(NpgsqlTimeTZType, NpgsqlTimeTZType, "GetTimeTZ");
            }
            if (_npgsqlTimeStamp != null)
            {
                SetProviderField(_npgsqlTimeStamp, _npgsqlTimeStamp, "GetTimeStamp");
            }
            if (_npgsqlTimeStampTZ != null)
            {
                SetProviderField(_npgsqlTimeStampTZ, _npgsqlTimeStampTZ, "GetTimeStampTZ");
            }
            if (NpgsqlMacAddressType != null)
            {
                SetProviderField(NpgsqlMacAddressType, NpgsqlMacAddressType, "GetProviderSpecificValue");
            }
            if (_npgsqlDateTime != null)
            {
                SetProviderField(_npgsqlDateTime, _npgsqlDateTime, "GetTimeStamp");
            }

            SetProviderField(NpgsqlInetType, NpgsqlInetType, "GetProviderSpecificValue");
            SetProviderField(_npgsqlDate, _npgsqlDate, "GetDate");

            if (_npgsqlTimeStampTZ != null)
            {
                // SetProviderField2<NpgsqlDataReader,DateTimeOffset,NpgsqlTimeStampTZ>((r,i) => (NpgsqlTimeStampTZ)r.GetProviderSpecificValue(i));

                var dataReaderParameter = Expression.Parameter(DataReaderType, "r");
                var indexParameter      = Expression.Parameter(typeof(int), "i");

                ReaderExpressions[new ReaderInfo {
                                      ToType = typeof(DateTimeOffset), ProviderFieldType = _npgsqlTimeStampTZ
                                  }] =
                    Expression.Lambda(
                        Expression.Convert(
                            Expression.Call(dataReaderParameter, "GetProviderSpecificValue", null, indexParameter),
                            _npgsqlTimeStampTZ),
                        dataReaderParameter,
                        indexParameter);
            }

            _setMoney     = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Money");
            _setVarBinary = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Bytea");
            _setBoolean   = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Boolean");
            _setXml       = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Xml");
            _setText      = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Text");
            _setBit       = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Bit");
            _setHstore    = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", "NpgsqlTypes.NpgsqlDbType", "Hstore");


            if (BitStringType != null)
            {
                MappingSchema.AddScalarType(BitStringType);
            }
            if (NpgsqlIntervalType != null)
            {
                MappingSchema.AddScalarType(NpgsqlIntervalType);
            }
            if (NpgsqlTimeType != null)
            {
                MappingSchema.AddScalarType(NpgsqlTimeType);
            }
            if (NpgsqlTimeTZType != null)
            {
                MappingSchema.AddScalarType(NpgsqlTimeTZType);
            }
            if (_npgsqlTimeStamp != null)
            {
                MappingSchema.AddScalarType(_npgsqlTimeStamp);
            }
            if (_npgsqlTimeStampTZ != null)
            {
                MappingSchema.AddScalarType(_npgsqlTimeStampTZ);
            }
            if (NpgsqlMacAddressType != null)
            {
                MappingSchema.AddScalarType(NpgsqlMacAddressType);
            }
            if (_npgsqlDateTime != null)
            {
                MappingSchema.AddScalarType(_npgsqlDateTime);
            }

            MappingSchema.AddScalarType(NpgsqlInetType);
            MappingSchema.AddScalarType(NpgsqlPointType);
            MappingSchema.AddScalarType(NpgsqlLSegType);
            MappingSchema.AddScalarType(NpgsqlBoxType);
            MappingSchema.AddScalarType(NpgsqlPathType);
            MappingSchema.AddScalarType(NpgsqlCircleType);
            MappingSchema.AddScalarType(_npgsqlDate);
            MappingSchema.AddScalarType(NpgsqlPolygonType);

            if (_npgsqlTimeStampTZ != null)
            {
                // SetConvertExpression<NpgsqlTimeStampTZ,DateTimeOffset>(
                //     d => new DateTimeOffset(d.Year, d.Month, d.Day, d.Hours, d.Minutes, d.Seconds, d.Milliseconds,
                //         new TimeSpan(d.TimeZone.Hours, d.TimeZone.Minutes, d.TimeZone.Seconds)));

                var p = Expression.Parameter(_npgsqlTimeStampTZ, "p");

                MappingSchema.SetConvertExpression(_npgsqlTimeStampTZ, typeof(DateTimeOffset),
                                                   Expression.Lambda(
                                                       Expression.New(
                                                           MemberHelper.ConstructorOf(() => new DateTimeOffset(0L, new TimeSpan())),
                                                           Expression.PropertyOrField(p, "Ticks"),
                                                           Expression.New(
                                                               MemberHelper.ConstructorOf(() => new TimeSpan(0, 0, 0)),
                                                               Expression.PropertyOrField(Expression.PropertyOrField(p, "TimeZone"), "Hours"),
                                                               Expression.PropertyOrField(Expression.PropertyOrField(p, "TimeZone"), "Minutes"),
                                                               Expression.PropertyOrField(Expression.PropertyOrField(p, "TimeZone"), "Seconds"))),
                                                       p
                                                       ));
            }

            if (_npgsqlDateTime != null)
            {
                var p = Expression.Parameter(_npgsqlDateTime, "p");

                MappingSchema.SetConvertExpression(_npgsqlDateTime, typeof(DateTimeOffset),
                                                   Expression.Lambda(
                                                       Expression.New(
                                                           MemberHelper.ConstructorOf(() => new DateTimeOffset(new DateTime())),
                                                           Expression.PropertyOrField(p, "DateTime")), p));
            }
        }
        protected override void OnConnectionTypeCreated(Type connectionType)
        {
            var npgSql = connectionType.AssemblyEx();

            // NpgsqlInterval was renamed to NpgsqlTimeSpan
            NpgsqlIntervalType = npgSql.GetType("NpgsqlTypes.NpgsqlInterval", false);
            NpgsqlIntervalType = NpgsqlIntervalType ?? npgSql.GetType("NpgsqlTypes.NpgsqlTimeSpan", false);

            BitStringType        = npgSql.GetType("NpgsqlTypes.BitString", false);
            NpgsqlInetType       = npgSql.GetType("NpgsqlTypes.NpgsqlInet", true);
            NpgsqlTimeType       = npgSql.GetType("NpgsqlTypes.NpgsqlTime", false);
            NpgsqlTimeTZType     = npgSql.GetType("NpgsqlTypes.NpgsqlTimeTZ", false);
            NpgsqlPointType      = npgSql.GetType("NpgsqlTypes.NpgsqlPoint", true);
            NpgsqlLineType       = npgSql.GetType("NpgsqlTypes.NpgsqlLine", false);
            NpgsqlLSegType       = npgSql.GetType("NpgsqlTypes.NpgsqlLSeg", true);
            NpgsqlBoxType        = npgSql.GetType("NpgsqlTypes.NpgsqlBox", true);
            NpgsqlPathType       = npgSql.GetType("NpgsqlTypes.NpgsqlPath", true);
            _npgsqlTimeStamp     = npgSql.GetType("NpgsqlTypes.NpgsqlTimeStamp", false);
            _npgsqlTimeStampTZ   = npgSql.GetType("NpgsqlTypes.NpgsqlTimeStampTZ", false);
            NpgsqlDateType       = npgSql.GetType("NpgsqlTypes.NpgsqlDate", true);
            NpgsqlDateTimeType   = npgSql.GetType("NpgsqlTypes.NpgsqlDateTime", false);
            NpgsqlMacAddressType = npgSql.GetType("NpgsqlTypes.NpgsqlMacAddress", false);
            NpgsqlCircleType     = npgSql.GetType("NpgsqlTypes.NpgsqlCircle", true);
            NpgsqlPolygonType    = npgSql.GetType("NpgsqlTypes.NpgsqlPolygon", true);
            NpgsqlDbType         = npgSql.GetType("NpgsqlTypes.NpgsqlDbType", true);

            // https://www.postgresql.org/docs/current/static/datatype.html
            // not all types are supported now
            // numeric types
            TryAddType("smallint", "Smallint");
            TryAddType("integer", "Integer");
            TryAddType("bigint", "Bigint");
            TryAddType("numeric", "Numeric");
            TryAddType("real", "Real");
            TryAddType("double precision", "Double");
            // monetary types
            TryAddType("money", "Money");
            // character types
            TryAddType("character", "Char");
            TryAddType("character varying", "Varchar");
            TryAddType("text", "Text");
            TryAddType("name", "Name");
            TryAddType("char", "InternalChar");
            // binary types
            TryAddType("bytea", "Bytea");
            // date/time types (reltime missing from enum)
            TryAddType("timestamp", "Timestamp");
            if (!TryAddType("timestamp with time zone", "TimestampTz"))
            {
                TryAddType("timestamp with time zone", "TimestampTZ");
            }
            TryAddType("date", "Date");
            TryAddType("time", "Time");
            if (!TryAddType("time with time zone", "TimeTz"))
            {
                TryAddType("time with time zone", "TimeTZ");
            }
            TryAddType("interval", "Interval");
            TryAddType("abstime", "Abstime");
            // boolean type
            TryAddType("boolean", "Boolean");
            // geometric types
            TryAddType("point", "Point");
            TryAddType("line", "Line");
            TryAddType("lseg", "LSeg");
            TryAddType("box", "Box");
            TryAddType("path", "Path");
            TryAddType("polygon", "Polygon");
            TryAddType("circle", "Circle");
            // network address types
            TryAddType("cidr", "Cidr");
            TryAddType("inet", "Inet");
            TryAddType("macaddr", "MacAddr");
            HasMacAddr8 = TryAddType("macaddr8", "MacAddr8");
            // bit string types
            TryAddType("bit", "Bit");
            TryAddType("bit varying", "Varbit");
            // text search types
            TryAddType("tsvector", "TsVector");
            TryAddType("tsquery", "TsQuery");
            // UUID type
            TryAddType("uuid", "Uuid");
            // XML type
            TryAddType("xml", "Xml");
            // JSON types
            TryAddType("json", "Json");
            TryAddType("jsonb", "Jsonb");
            // Object Identifier Types (only supported by npgsql)
            TryAddType("oid", "Oid");
            TryAddType("regtype", "Regtype");
            TryAddType("xid", "Xid");
            TryAddType("cid", "Cid");
            TryAddType("tid", "Tid");
            // other types
            TryAddType("citext", "Citext");
            TryAddType("hstore", "Hstore");
            TryAddType("refcursor", "Refcursor");
            TryAddType("oidvector", "Oidvector");
            TryAddType("int2vector", "Int2Vector");

            _npgsqlTypeArrayFlag = (int)Enum.Parse(NpgsqlDbType, "Array");
            _npgsqlTypeRangeFlag = (int)Enum.Parse(NpgsqlDbType, "Range");

            // https://github.com/linq2db/linq2db/pull/718
            //if (npgSql.GetName().Version >= new Version(3, 1, 9))
            //{
            //	_commandBehavior = CommandBehavior.KeyInfo;
            //}

            if (BitStringType != null)
            {
                SetProviderField(BitStringType, BitStringType, "GetBitString");
            }
            if (NpgsqlIntervalType != null)
            {
                SetProviderField(NpgsqlIntervalType, NpgsqlIntervalType, "GetInterval");
            }
            if (NpgsqlTimeType != null)
            {
                SetProviderField(NpgsqlTimeType, NpgsqlTimeType, "GetTime");
            }
            if (NpgsqlTimeTZType != null)
            {
                SetProviderField(NpgsqlTimeTZType, NpgsqlTimeTZType, "GetTimeTZ");
            }
            if (_npgsqlTimeStamp != null)
            {
                SetProviderField(_npgsqlTimeStamp, _npgsqlTimeStamp, "GetTimeStamp");
            }
            if (_npgsqlTimeStampTZ != null)
            {
                SetProviderField(_npgsqlTimeStampTZ, _npgsqlTimeStampTZ, "GetTimeStampTZ");
            }
            if (NpgsqlMacAddressType != null)
            {
                SetProviderField(NpgsqlMacAddressType, NpgsqlMacAddressType, "GetProviderSpecificValue");
            }
            if (NpgsqlDateTimeType != null)
            {
                SetProviderField(NpgsqlDateTimeType, NpgsqlDateTimeType, "GetTimeStamp");
            }

            SetProviderField(NpgsqlInetType, NpgsqlInetType, "GetProviderSpecificValue");
            SetProviderField(NpgsqlDateType, NpgsqlDateType, "GetDate");

            if (_npgsqlTimeStampTZ != null)
            {
                // SetProviderField2<NpgsqlDataReader,DateTimeOffset,NpgsqlTimeStampTZ>((r,i) => (NpgsqlTimeStampTZ)r.GetProviderSpecificValue(i));

                var dataReaderParameter = Expression.Parameter(DataReaderType, "r");
                var indexParameter      = Expression.Parameter(typeof(int), "i");

                ReaderExpressions[new ReaderInfo {
                                      ToType = typeof(DateTimeOffset), ProviderFieldType = _npgsqlTimeStampTZ
                                  }] =
                    Expression.Lambda(
                        Expression.Convert(
                            Expression.Call(dataReaderParameter, "GetProviderSpecificValue", null, indexParameter),
                            _npgsqlTimeStampTZ),
                        dataReaderParameter,
                        indexParameter);
            }

            _setMoney     = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Money");
            _setVarBinary = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Bytea");
            _setBoolean   = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Boolean");
            _setXml       = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Xml");
            _setText      = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Text");
            _setBit       = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Bit");
            _setHstore    = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Hstore");
            _setJson      = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Json");
            _setJsonb     = GetSetParameter(connectionType, "NpgsqlParameter", "NpgsqlDbType", NpgsqlDbType, "Jsonb");

            if (BitStringType != null)
            {
                MappingSchema.AddScalarType(BitStringType);
            }
            if (NpgsqlTimeType != null)
            {
                MappingSchema.AddScalarType(NpgsqlTimeType);
            }
            if (NpgsqlTimeTZType != null)
            {
                MappingSchema.AddScalarType(NpgsqlTimeTZType);
            }
            if (_npgsqlTimeStamp != null)
            {
                MappingSchema.AddScalarType(_npgsqlTimeStamp);
            }
            if (_npgsqlTimeStampTZ != null)
            {
                MappingSchema.AddScalarType(_npgsqlTimeStampTZ);
            }
            if (NpgsqlMacAddressType != null)
            {
                MappingSchema.AddScalarType(NpgsqlMacAddressType);
            }

            AddUdtType(NpgsqlIntervalType);
            AddUdtType(NpgsqlDateType);
            AddUdtType(NpgsqlDateTimeType);

            AddUdtType(NpgsqlInetType);
            AddUdtType(typeof(IPAddress));
            AddUdtType(typeof(PhysicalAddress));

            AddUdtType(NpgsqlPointType);
            AddUdtType(NpgsqlLSegType);
            AddUdtType(NpgsqlBoxType);
            AddUdtType(NpgsqlPathType);
            AddUdtType(NpgsqlCircleType);
            AddUdtType(NpgsqlPolygonType);
            AddUdtType(NpgsqlLineType);

            if (_npgsqlTimeStampTZ != null)
            {
                // SetConvertExpression<NpgsqlTimeStampTZ,DateTimeOffset>(
                //     d => new DateTimeOffset(d.Year, d.Month, d.Day, d.Hours, d.Minutes, d.Seconds, d.Milliseconds,
                //         new TimeSpan(d.TimeZone.Hours, d.TimeZone.Minutes, d.TimeZone.Seconds)));

                var p = Expression.Parameter(_npgsqlTimeStampTZ, "p");

                MappingSchema.SetConvertExpression(_npgsqlTimeStampTZ, typeof(DateTimeOffset),
                                                   Expression.Lambda(
                                                       Expression.New(
                                                           MemberHelper.ConstructorOf(() => new DateTimeOffset(0L, new TimeSpan())),
                                                           Expression.PropertyOrField(p, "Ticks"),
                                                           Expression.New(
                                                               MemberHelper.ConstructorOf(() => new TimeSpan(0, 0, 0)),
                                                               Expression.PropertyOrField(Expression.PropertyOrField(p, "TimeZone"), "Hours"),
                                                               Expression.PropertyOrField(Expression.PropertyOrField(p, "TimeZone"), "Minutes"),
                                                               Expression.PropertyOrField(Expression.PropertyOrField(p, "TimeZone"), "Seconds"))),
                                                       p
                                                       ));
            }

            if (NpgsqlDateTimeType != null)
            {
                var p  = Expression.Parameter(NpgsqlDateTimeType, "p");
                var pi = p.Type.GetPropertyEx("DateTime");

                Expression expr;

                if (pi != null)
                {
                    expr = Expression.Property(p, pi);
                }
                else
                {
                    expr = Expression.Call(p, "ToDateTime", null);
                }

                MappingSchema.SetConvertExpression(NpgsqlDateTimeType, typeof(DateTimeOffset),
                                                   Expression.Lambda(
                                                       Expression.New(
                                                           MemberHelper.ConstructorOf(() => new DateTimeOffset(new DateTime())),
                                                           expr), p));
            }
        }
Exemplo n.º 5
0
        public static NpgsqlProviderAdapter GetInstance()
        {
            if (_instance == null)
            {
                lock (_syncRoot)
                    if (_instance == null)
                    {
                        var assembly = Tools.TryLoadAssembly(AssemblyName, null);
                        if (assembly == null)
                        {
                            throw new InvalidOperationException($"Cannot load assembly {AssemblyName}");
                        }

                        var connectionType     = assembly.GetType($"{ClientNamespace}.NpgsqlConnection", true) !;
                        var parameterType      = assembly.GetType($"{ClientNamespace}.NpgsqlParameter", true) !;
                        var dataReaderType     = assembly.GetType($"{ClientNamespace}.NpgsqlDataReader", true) !;
                        var commandType        = assembly.GetType($"{ClientNamespace}.NpgsqlCommand", true) !;
                        var transactionType    = assembly.GetType($"{ClientNamespace}.NpgsqlTransaction", true) !;
                        var dbType             = assembly.GetType($"{TypesNamespace}.NpgsqlDbType", true) !;
                        var npgsqlDateType     = assembly.GetType($"{TypesNamespace}.NpgsqlDate", true) !;
                        var npgsqlPointType    = assembly.GetType($"{TypesNamespace}.NpgsqlPoint", true) !;
                        var npgsqlLSegType     = assembly.GetType($"{TypesNamespace}.NpgsqlLSeg", true) !;
                        var npgsqlBoxType      = assembly.GetType($"{TypesNamespace}.NpgsqlBox", true) !;
                        var npgsqlCircleType   = assembly.GetType($"{TypesNamespace}.NpgsqlCircle", true) !;
                        var npgsqlPathType     = assembly.GetType($"{TypesNamespace}.NpgsqlPath", true) !;
                        var npgsqlPolygonType  = assembly.GetType($"{TypesNamespace}.NpgsqlPolygon", true) !;
                        var npgsqlLineType     = assembly.GetType($"{TypesNamespace}.NpgsqlLine", true) !;
                        var npgsqlInetType     = assembly.GetType($"{TypesNamespace}.NpgsqlInet", true) !;
                        var npgsqlTimeSpanType = assembly.GetType($"{TypesNamespace}.NpgsqlTimeSpan", true) !;
                        var npgsqlDateTimeType = assembly.GetType($"{TypesNamespace}.NpgsqlDateTime", true) !;
                        var npgsqlRangeTType   = assembly.GetType($"{TypesNamespace}.NpgsqlRange`1", true) !;

                        var npgsqlBinaryImporterType = assembly.GetType($"{ClientNamespace}.NpgsqlBinaryImporter", true) !;

                        var typeMapper = new TypeMapper();
                        typeMapper.RegisterTypeWrapper <NpgsqlConnection>(connectionType);
                        typeMapper.RegisterTypeWrapper <NpgsqlParameter>(parameterType);
                        typeMapper.RegisterTypeWrapper <NpgsqlDbType>(dbType);
                        typeMapper.RegisterTypeWrapper <NpgsqlBinaryImporter>(npgsqlBinaryImporterType);
                        typeMapper.FinalizeMappings();

                        var paramMapper   = typeMapper.Type <NpgsqlParameter>();
                        var dbTypeBuilder = paramMapper.Member(p => p.NpgsqlDbType);

                        var pConnection = Expression.Parameter(typeof(IDbConnection));
                        var pCommand    = Expression.Parameter(typeof(string));

                        var beginBinaryImport = Expression.Lambda <Func <IDbConnection, string, NpgsqlBinaryImporter> >(
                            typeMapper.MapExpression((IDbConnection conn, string command) => typeMapper.Wrap <NpgsqlBinaryImporter>(((NpgsqlConnection)conn).BeginBinaryImport(command)), pConnection, pCommand),
                            pConnection, pCommand)
                                                .CompileExpression();

                        // create mapping schema
                        var mappingSchema = new MappingSchema();

                        // date/time types
                        AddUdtType(npgsqlDateType);
                        AddUdtType(npgsqlDateTimeType);
                        mappingSchema.SetDataType(npgsqlTimeSpanType, DataType.Interval);
                        mappingSchema.SetDataType(npgsqlTimeSpanType.AsNullable(), DataType.Interval);
                        // NpgsqlDateTimeType => DateTimeOffset
                        {
                            var p  = Expression.Parameter(npgsqlDateTimeType, "p");
                            var pi = p.Type.GetProperty("DateTime");

                            Expression expr;

                            if (pi != null)
                            {
                                // < 3.2.0
                                // https://github.com/npgsql/npgsql/commit/3894175f970b611f6428757a932b6393749da958#diff-c792076ac0455dd0f2852822ea38b0aaL166
                                expr = Expression.Property(p, pi);
                            }
                            else
                            {
                                // 3.2.0+
                                expr = Expression.Call(p, "ToDateTime", null);
                            }

                            var npgsqlDateTimeToDateTimeOffsetMapper = Expression.Lambda(
                                Expression.New(
                                    MemberHelper.ConstructorOf(() => new DateTimeOffset(new DateTime())),
                                    expr),
                                p);
                            mappingSchema.SetConvertExpression(npgsqlDateTimeType, typeof(DateTimeOffset), npgsqlDateTimeToDateTimeOffsetMapper);
                        }

                        // inet types
                        AddUdtType(npgsqlInetType);
                        AddUdtType(typeof(IPAddress));
                        AddUdtType(typeof(PhysicalAddress));
                        // npgsql4 obsoletes NpgsqlInetType and returns ValueTuple<IPAddress, int>
                        // still while it is here, we should be able to map it properly
                        // (IPAddress, int) => NpgsqlInet
                        {
                            var valueTypeType = Type.GetType("System.ValueTuple`2", false);
                            if (valueTypeType != null)
                            {
                                var inetTupleType = valueTypeType.MakeGenericType(typeof(IPAddress), typeof(int));
                                var p             = Expression.Parameter(inetTupleType, "p");

                                var tupleToInetTypeMapper = Expression.Lambda(
                                    Expression.New(
                                        npgsqlInetType.GetConstructor(new[] { typeof(IPAddress), typeof(int) }) !,
                                        ExpressionHelper.Field(p, "Item1"),
                                        ExpressionHelper.Field(p, "Item2")),
                                    p);
                                mappingSchema.SetConvertExpression(inetTupleType !, npgsqlInetType, tupleToInetTypeMapper);
                            }
                        }

                        // ranges
                        AddUdtType(npgsqlRangeTType);
                        {
                            void SetRangeConversion <T>(string?fromDbType = null, DataType fromDataType = DataType.Undefined, string?toDbType = null, DataType toDataType = DataType.Undefined)
                            {
                                var rangeType  = npgsqlRangeTType.MakeGenericType(typeof(T));
                                var fromType   = new DbDataType(rangeType, fromDataType, fromDbType);
                                var toType     = new DbDataType(typeof(DataParameter), toDataType, toDbType);
                                var rangeParam = Expression.Parameter(rangeType, "p");

                                mappingSchema.SetConvertExpression(fromType, toType,
                                                                   Expression.Lambda(
                                                                       Expression.New(
                                                                           MemberHelper.ConstructorOf(
                                                                               () => new DataParameter("", null, DataType.Undefined, toDbType)),
                                                                           Expression.Constant(""),
                                                                           Expression.Convert(rangeParam, typeof(object)),
                                                                           Expression.Constant(toDataType),
                                                                           Expression.Constant(toDbType, typeof(string))
                                                                           )
                                                                       , rangeParam)
                                                                   );
                            }

                            SetRangeConversion <byte>();
                            SetRangeConversion <int>();
                            SetRangeConversion <double>();
                            SetRangeConversion <float>();
                            SetRangeConversion <decimal>();

                            SetRangeConversion <DateTime>(fromDbType: "daterange", toDbType: "daterange");

                            SetRangeConversion <DateTime>(fromDbType: "tsrange", toDbType: "tsrange");
                            SetRangeConversion <DateTime>(toDbType: "tsrange");

                            SetRangeConversion <DateTime>(fromDbType: "tstzrange", toDbType: "tstzrange");

                            SetRangeConversion <DateTimeOffset>("tstzrange");
                        }

                        // spatial types
                        AddUdtType(npgsqlPointType);
                        AddUdtType(npgsqlLSegType);
                        AddUdtType(npgsqlBoxType);
                        AddUdtType(npgsqlPathType);
                        AddUdtType(npgsqlCircleType);
                        AddUdtType(npgsqlPolygonType);
                        AddUdtType(npgsqlLineType);

                        _instance = new NpgsqlProviderAdapter(
                            connectionType,
                            dataReaderType,
                            parameterType,
                            commandType,
                            transactionType,
                            dbType,

                            mappingSchema,

                            npgsqlDateType,
                            npgsqlPointType,
                            npgsqlLSegType,
                            npgsqlBoxType,
                            npgsqlCircleType,
                            npgsqlPathType,
                            npgsqlPolygonType,
                            npgsqlLineType,
                            npgsqlInetType,
                            npgsqlTimeSpanType,
                            npgsqlDateTimeType,
                            npgsqlRangeTType,

                            typeMapper.BuildWrappedFactory((string connectionString) => new NpgsqlConnection(connectionString)),

                            dbTypeBuilder.BuildSetter <IDbDataParameter>(),
                            dbTypeBuilder.BuildGetter <IDbDataParameter>(),

                            beginBinaryImport);

                        void AddUdtType(Type type)
                        {
                            if (!type.IsValueType)
                            {
                                mappingSchema.AddScalarType(type, null, true, DataType.Udt);
                            }
                            else
                            {
                                mappingSchema.AddScalarType(type, DataType.Udt);
                                mappingSchema.AddScalarType(type.AsNullable(), null, true, DataType.Udt);
                            }
                        }
                    }
            }

            return(_instance);
        }
Exemplo n.º 6
0
        protected override void OnConnectionTypeCreated(Type connectionType)
        {
            var typesNamespace = OracleTools.AssemblyName + ".Types.";

            _oracleBFile        = connectionType.AssemblyEx().GetType(typesNamespace + "OracleBFile", true);
            _oracleBinary       = connectionType.AssemblyEx().GetType(typesNamespace + "OracleBinary", true);
            _oracleBlob         = connectionType.AssemblyEx().GetType(typesNamespace + "OracleBlob", true);
            _oracleClob         = connectionType.AssemblyEx().GetType(typesNamespace + "OracleClob", true);
            _oracleDate         = connectionType.AssemblyEx().GetType(typesNamespace + "OracleDate", true);
            _oracleDecimal      = connectionType.AssemblyEx().GetType(typesNamespace + "OracleDecimal", true);
            _oracleIntervalDS   = connectionType.AssemblyEx().GetType(typesNamespace + "OracleIntervalDS", true);
            _oracleIntervalYM   = connectionType.AssemblyEx().GetType(typesNamespace + "OracleIntervalYM", true);
            _oracleRefCursor    = connectionType.AssemblyEx().GetType(typesNamespace + "OracleRefCursor", true);
            _oracleString       = connectionType.AssemblyEx().GetType(typesNamespace + "OracleString", true);
            _oracleTimeStamp    = connectionType.AssemblyEx().GetType(typesNamespace + "OracleTimeStamp", true);
            _oracleTimeStampLTZ = connectionType.AssemblyEx().GetType(typesNamespace + "OracleTimeStampLTZ", true);
            _oracleTimeStampTZ  = connectionType.AssemblyEx().GetType(typesNamespace + "OracleTimeStampTZ", true);
            _oracleRef          = connectionType.AssemblyEx().GetType(typesNamespace + "OracleRef", false);
            _oracleXmlType      = connectionType.AssemblyEx().GetType(typesNamespace + "OracleXmlType", false);
            _oracleXmlStream    = connectionType.AssemblyEx().GetType(typesNamespace + "OracleXmlStream", false);

            SetProviderField(_oracleBFile, _oracleBFile, "GetOracleBFile");
            SetProviderField(_oracleBinary, _oracleBinary, "GetOracleBinary");
            SetProviderField(_oracleBlob, _oracleBlob, "GetOracleBlob");
            SetProviderField(_oracleClob, _oracleClob, "GetOracleClob");
            SetProviderField(_oracleDate, _oracleDate, "GetOracleDate");
            SetProviderField(_oracleDecimal, _oracleDecimal, "GetOracleDecimal");
            SetProviderField(_oracleIntervalDS, _oracleIntervalDS, "GetOracleIntervalDS");
            SetProviderField(_oracleIntervalYM, _oracleIntervalYM, "GetOracleIntervalYM");
            SetProviderField(_oracleString, _oracleString, "GetOracleString");
            SetProviderField(_oracleTimeStamp, _oracleTimeStamp, "GetOracleTimeStamp");
            SetProviderField(_oracleTimeStampLTZ, _oracleTimeStampLTZ, "GetOracleTimeStampLTZ");
            SetProviderField(_oracleTimeStampTZ, _oracleTimeStampTZ, "GetOracleTimeStampTZ");

            try
            {
                if (_oracleRef != null)
                {
                    SetProviderField(_oracleRef, _oracleRef, "GetOracleRef");
                }
            }
            catch
            {
            }

            try
            {
                if (_oracleXmlType != null)
                {
                    SetProviderField(_oracleXmlType, _oracleXmlType, "GetOracleXmlType");
                }
            }
            catch
            {
            }

            var dataReaderParameter = Expression.Parameter(DataReaderType, "r");
            var indexParameter      = Expression.Parameter(typeof(int), "i");

            {
                // static DateTimeOffset GetOracleTimeStampTZ(OracleDataReader rd, int idx)
                // {
                //     var tstz = rd.GetOracleTimeStampTZ(idx);
                //     return new DateTimeOffset(
                //         tstz.Year, tstz.Month,  tstz.Day,
                //         tstz.Hour, tstz.Minute, tstz.Second, (int)tstz.Millisecond,
                //         TimeSpan.Parse(tstz.TimeZone.TrimStart('+')));
                // }

                var tstz = Expression.Parameter(_oracleTimeStampTZ, "tstz");

                ReaderExpressions[new ReaderInfo {
                                      ToType = typeof(DateTimeOffset), ProviderFieldType = _oracleTimeStampTZ
                                  }] =
                    Expression.Lambda(
                        Expression.Block(
                            new[] { tstz },
                            new Expression[]
                {
                    Expression.Assign(tstz, Expression.Call(dataReaderParameter, "GetOracleTimeStampTZ", null, indexParameter)),
                    Expression.New(
                        MemberHelper.ConstructorOf(() => new DateTimeOffset(0, 0, 0, 0, 0, 0, 0, new TimeSpan())),
                        Expression.PropertyOrField(tstz, "Year"),
                        Expression.PropertyOrField(tstz, "Month"),
                        Expression.PropertyOrField(tstz, "Day"),
                        Expression.PropertyOrField(tstz, "Hour"),
                        Expression.PropertyOrField(tstz, "Minute"),
                        Expression.PropertyOrField(tstz, "Second"),
                        Expression.Convert(Expression.PropertyOrField(tstz, "Millisecond"), typeof(int)),
                        Expression.Call(
                            MemberHelper.MethodOf(() => TimeSpan.Parse("")),
                            Expression.Call(
                                Expression.PropertyOrField(tstz, "TimeZone"),
                                MemberHelper.MethodOf(() => "".TrimStart(' ')),
                                Expression.NewArrayInit(typeof(char), Expression.Constant('+'))))
                        )
                }),
                        dataReaderParameter,
                        indexParameter);
            }

            {
                // static DateTimeOffset GetOracleTimeStampLTZ(OracleDataReader rd, int idx)
                // {
                //     var tstz = rd.GetOracleTimeStampLTZ(idx).ToOracleTimeStampTZ();
                //     return new DateTimeOffset(
                //         tstz.Year, tstz.Month,  tstz.Day,
                //         tstz.Hour, tstz.Minute, tstz.Second, (int)tstz.Millisecond,
                //         TimeSpan.Parse(tstz.TimeZone.TrimStart('+')));
                // }

                var tstz = Expression.Parameter(_oracleTimeStampTZ, "tstz");

                ReaderExpressions[new ReaderInfo {
                                      ToType = typeof(DateTimeOffset), ProviderFieldType = _oracleTimeStampLTZ
                                  }] =
                    Expression.Lambda(
                        Expression.Block(
                            new[] { tstz },
                            new Expression[]
                {
                    Expression.Assign(
                        tstz,
                        Expression.Call(
                            Expression.Call(dataReaderParameter, "GetOracleTimeStampLTZ", null, indexParameter),
                            "ToOracleTimeStampTZ",
                            null,
                            null)),
                    Expression.New(
                        MemberHelper.ConstructorOf(() => new DateTimeOffset(0, 0, 0, 0, 0, 0, 0, new TimeSpan())),
                        Expression.PropertyOrField(tstz, "Year"),
                        Expression.PropertyOrField(tstz, "Month"),
                        Expression.PropertyOrField(tstz, "Day"),
                        Expression.PropertyOrField(tstz, "Hour"),
                        Expression.PropertyOrField(tstz, "Minute"),
                        Expression.PropertyOrField(tstz, "Second"),
                        Expression.Convert(Expression.PropertyOrField(tstz, "Millisecond"), typeof(int)),
                        Expression.Call(
                            MemberHelper.MethodOf(() => TimeSpan.Parse("")),
                            Expression.Call(
                                Expression.PropertyOrField(tstz, "TimeZone"),
                                MemberHelper.MethodOf(() => "".TrimStart(' ')),
                                Expression.NewArrayInit(typeof(char), Expression.Constant('+'))))
                        )
                }),
                        dataReaderParameter,
                        indexParameter);
            }


            {
                // value = new OracleTimeStampTZ(dto.Year, dto.Month, dto.Day, dto.Hour, dto.Minute, dto.Second, dto.Millisecond, zone);

                var dto  = Expression.Parameter(typeof(DateTimeOffset), "dto");
                var zone = Expression.Parameter(typeof(string), "zone");

                _createOracleTimeStampTZ =
                    Expression.Lambda <Func <DateTimeOffset, string, object> >(
                        Expression.Convert(
                            Expression.New(
                                _oracleTimeStampTZ.GetConstructorEx(new[]
                {
                    typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(string)
                }),
                                Expression.PropertyOrField(dto, "Year"),
                                Expression.PropertyOrField(dto, "Month"),
                                Expression.PropertyOrField(dto, "Day"),
                                Expression.PropertyOrField(dto, "Hour"),
                                Expression.PropertyOrField(dto, "Minute"),
                                Expression.PropertyOrField(dto, "Second"),
                                Expression.PropertyOrField(dto, "Millisecond"),
                                zone),
                            typeof(object)),
                        dto,
                        zone
                        ).Compile();
            }

            _setSingle         = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "BinaryFloat");
            _setDouble         = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "BinaryDouble");
            _setText           = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Clob");
            _setNText          = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "NClob");
            _setImage          = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Blob");
            _setBinary         = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Blob");
            _setVarBinary      = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Blob");
            _setDate           = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Date");
            _setSmallDateTime  = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Date");
            _setDateTime2      = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "TimeStamp");
            _setDateTimeOffset = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "TimeStampTZ");
            _setGuid           = GetSetParameter(connectionType, "OracleParameter", "OracleDbType", "OracleDbType", "Raw");

            MappingSchema.AddScalarType(_oracleBFile, GetNullValue(_oracleBFile), true, DataType.VarChar);                              // ?
            MappingSchema.AddScalarType(_oracleBinary, GetNullValue(_oracleBinary), true, DataType.VarBinary);
            MappingSchema.AddScalarType(_oracleBlob, GetNullValue(_oracleBlob), true, DataType.Blob);                                   // ?
            MappingSchema.AddScalarType(_oracleClob, GetNullValue(_oracleClob), true, DataType.NText);
            MappingSchema.AddScalarType(_oracleDate, GetNullValue(_oracleDate), true, DataType.DateTime);
            MappingSchema.AddScalarType(_oracleDecimal, GetNullValue(_oracleDecimal), true, DataType.Decimal);
            MappingSchema.AddScalarType(_oracleIntervalDS, GetNullValue(_oracleIntervalDS), true, DataType.Time);                       // ?
            MappingSchema.AddScalarType(_oracleIntervalYM, GetNullValue(_oracleIntervalYM), true, DataType.Date);                       // ?
            MappingSchema.AddScalarType(_oracleRefCursor, GetNullValue(_oracleRefCursor), true, DataType.Binary);                       // ?
            MappingSchema.AddScalarType(_oracleString, GetNullValue(_oracleString), true, DataType.NVarChar);
            MappingSchema.AddScalarType(_oracleTimeStamp, GetNullValue(_oracleTimeStamp), true, DataType.DateTime2);
            MappingSchema.AddScalarType(_oracleTimeStampLTZ, GetNullValue(_oracleTimeStampLTZ), true, DataType.DateTimeOffset);
            MappingSchema.AddScalarType(_oracleTimeStampTZ, GetNullValue(_oracleTimeStampTZ), true, DataType.DateTimeOffset);

            if (_oracleRef != null)
            {
                MappingSchema.AddScalarType(_oracleRef, GetNullValue(_oracleRef), true, DataType.Binary);                 // ?
            }
            if (_oracleXmlType != null)
            {
                MappingSchema.AddScalarType(_oracleXmlType, GetNullValue(_oracleXmlType), true, DataType.Xml);
            }

            if (_oracleXmlStream != null)
            {
                MappingSchema.AddScalarType(_oracleXmlStream, GetNullValue(_oracleXmlStream), true, DataType.Xml);                 // ?
            }
        }