Пример #1
0
    internal static RowDescriptionMessage CreateForReplication(
        ConnectorTypeMapper typeMapper, uint tableOID, FormatCode formatCode, IReadOnlyList <RelationMessage.Column> columns)
    {
        var msg       = new RowDescriptionMessage(columns.Count);
        var numFields = msg.Count = columns.Count;

        for (var i = 0; i < numFields; ++i)
        {
            var field  = msg._fields[i] = new();
            var column = columns[i];

            field.Populate(
                typeMapper,
                name:                  column.ColumnName,
                tableOID:              tableOID,
                columnAttributeNumber: checked ((short)i),
                oid:                   column.DataTypeId,
                typeSize:              0, // TODO: Confirm we don't have this in replication
                typeModifier:          column.TypeModifier,
                formatCode:            formatCode
                );

            if (!msg._nameIndex.ContainsKey(field.Name))
            {
                msg._nameIndex.Add(field.Name, i);
            }
        }

        return(msg);
    }
Пример #2
0
        internal RowDescriptionMessage Load(NpgsqlReadBuffer buf, ConnectorTypeMapper typeMapper)
        {
            Fields.Clear();
            _nameIndex.Clear();
            _caseInsensitiveNameIndex.Clear();

            var numFields = buf.ReadInt16();

            for (var i = 0; i != numFields; ++i)
            {
                // TODO: Recycle
                var field = new FieldDescription();
                field.Populate(
                    typeMapper,
                    buf.ReadNullTerminatedString(),  // Name
                    buf.ReadUInt32(),                // TableOID
                    buf.ReadInt16(),                 // ColumnAttributeNumber
                    buf.ReadUInt32(),                // TypeOID
                    buf.ReadInt16(),                 // TypeSize
                    buf.ReadInt32(),                 // TypeModifier
                    (FormatCode)buf.ReadInt16()      // FormatCode
                    );

                Fields.Add(field);
                if (!_nameIndex.ContainsKey(field.Name))
                {
                    _nameIndex.Add(field.Name, i);
                    if (!_caseInsensitiveNameIndex.ContainsKey(field.Name))
                    {
                        _caseInsensitiveNameIndex.Add(field.Name, i);
                    }
                }
            }
            return(this);
        }
Пример #3
0
 void Cleanup()
 {
     Log.Debug("COPY operation ended", _connector.Id);
     _connector  = null;
     _typeMapper = null;
     _buf        = null;
     _isDisposed = true;
 }
Пример #4
0
 internal NpgsqlBinaryExporter(NpgsqlConnector connector)
 {
     _connector        = connector;
     _buf              = connector.ReadBuffer;
     _typeMapper       = connector.TypeMapper;
     _columnLen        = int.MinValue; // Mark that the (first) column length hasn't been read yet
     _column           = -1;
     _typeHandlerCache = null !;
 }
Пример #5
0
        internal UnmappedCompositeHandler(INpgsqlNameTranslator nameTranslator, ConnectorTypeMapper typeMapper)
        {
            _nameTranslator = nameTranslator;

            // After construction the composite handler will have a reference to its PostgresCompositeType,
            // which contains information about the fields. But the actual binding of their type OIDs
            // to their type handlers is done only very late upon first usage of the handler,
            // allowing composite types to be activated in any order regardless of dependencies.

            _typeMapper = typeMapper;
        }
Пример #6
0
    public void Setup()
    {
        _conn       = BenchmarkEnvironment.OpenConnection();
        _typeMapper = (ConnectorTypeMapper)_conn.TypeMapper;

        if (NumPlugins > 0)
        {
            _typeMapper.UseNodaTime();
        }
        if (NumPlugins > 1)
        {
            _typeMapper.UseNetTopologySuite();
        }
    }
Пример #7
0
        internal void Populate(
            ConnectorTypeMapper typeMapper, string name, uint tableOID, short columnAttributeNumber,
            uint oid, short typeSize, int typeModifier, FormatCode formatCode
            )
        {
            _typeMapper           = typeMapper;
            Name                  = name;
            TableOID              = tableOID;
            ColumnAttributeNumber = columnAttributeNumber;
            TypeOID               = oid;
            TypeSize              = typeSize;
            TypeModifier          = typeModifier;
            FormatCode            = formatCode;

            ResolveHandler();
        }
Пример #8
0
        void Cleanup()
        {
            var connector = _connector;

            Log.Debug("COPY operation ended", connector?.Id ?? -1);

            if (connector != null)
            {
                connector.CurrentCopyOperation = null;
                _connector = null;
            }

            _typeMapper = null;
            _buf        = null;
            _isDisposed = true;
        }
Пример #9
0
        internal NpgsqlBinaryExporter(NpgsqlConnector connector, string copyToCommand)
        {
            _connector  = connector;
            _buf        = connector.ReadBuffer;
            _typeMapper = connector.TypeMapper;
            _columnLen  = int.MinValue;  // Mark that the (first) column length hasn't been read yet
            _column     = -1;

            try
            {
                _connector.SendQuery(copyToCommand);

                CopyOutResponseMessage copyOutResponse;
                var msg = _connector.ReadMessage();
                switch (msg.Code)
                {
                case BackendMessageCode.CopyOutResponse:
                    copyOutResponse = (CopyOutResponseMessage)msg;
                    if (!copyOutResponse.IsBinary)
                    {
                        throw new ArgumentException("copyToCommand triggered a text transfer, only binary is allowed", nameof(copyToCommand));
                    }
                    break;

                case BackendMessageCode.CompletedResponse:
                    throw new InvalidOperationException(
                              "This API only supports import/export from the client, i.e. COPY commands containing TO/FROM STDIN. " +
                              "To import/export with files on your PostgreSQL machine, simply execute the command with ExecuteNonQuery. " +
                              "Note that your data has been successfully imported/exported.");

                default:
                    throw _connector.UnexpectedMessageReceived(msg.Code);
                }

                NumColumns        = copyOutResponse.NumColumns;
                _typeHandlerCache = new NpgsqlTypeHandler[NumColumns];
                ReadHeader();
            }
            catch
            {
                _connector.Break();
                throw;
            }
        }
Пример #10
0
        internal RowDescriptionMessage Load(NpgsqlReadBuffer buf, ConnectorTypeMapper typeMapper)
        {
            _nameIndex.Clear();
            _insensitiveIndex?.Clear();

            var numFields = Count = buf.ReadInt16();

            if (_fields.Length < numFields)
            {
                var oldFields = _fields;
                _fields = new FieldDescription[numFields];
                Array.Copy(oldFields, _fields, oldFields.Length);
            }

            for (var i = 0; i < numFields; ++i)
            {
                var field = _fields[i] ??= new();

                field.Populate(
                    typeMapper,
                    buf.ReadNullTerminatedString(), // Name
                    buf.ReadUInt32(),               // TableOID
                    buf.ReadInt16(),                // ColumnAttributeNumber
                    buf.ReadUInt32(),               // TypeOID
                    buf.ReadInt16(),                // TypeSize
                    buf.ReadInt32(),                // TypeModifier
                    (FormatCode)buf.ReadInt16()     // FormatCode
                    );

                if (!_nameIndex.ContainsKey(field.Name))
                {
                    _nameIndex.Add(field.Name, i);
                }
            }

            return(this);
        }
Пример #11
0
 public CompositeHandler(PostgresCompositeType postgresType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator)
     : base(postgresType)
 {
     _typeMapper     = typeMapper;
     _nameTranslator = nameTranslator;
 }
Пример #12
0
        static CompositeMemberHandler <T>[] CreateMemberHandlers(PostgresCompositeType pgType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator)
        {
            var pgFields = pgType.Fields;

            var clrType               = typeof(T);
            var clrMemberHandlers     = new CompositeMemberHandler <T> [pgFields.Count];
            var clrMemberHandlerCount = 0;
            var clrMemberHandlerType  = IsValueType <T> .Value
                ? typeof(CompositeStructMemberHandler <,>)
                : typeof(CompositeClassMemberHandler <,>);

            foreach (var clrProperty in clrType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                CreateMemberHandler(clrProperty, clrProperty.PropertyType);
            }

            foreach (var clrField in clrType.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                CreateMemberHandler(clrField, clrField.FieldType);
            }

            if (clrMemberHandlerCount != pgFields.Count)
            {
                var notMappedFields = string.Join(", ", clrMemberHandlers
                                                  .Select((member, memberIndex) => member == null ? $"'{pgFields[memberIndex].Name}'" : null)
                                                  .Where(member => member != null));
                throw new InvalidOperationException($"PostgreSQL composite type {pgType.DisplayName} contains fields {notMappedFields} which could not match any on CLR type {clrType.Name}");
            }

            return(clrMemberHandlers);

            void CreateMemberHandler(MemberInfo clrMember, Type clrMemberType)
            {
                var attr = clrMember.GetCustomAttribute <PgNameAttribute>();
                var name = attr?.PgName ?? nameTranslator.TranslateMemberName(clrMember.Name);

                for (var pgFieldIndex = pgFields.Count - 1; pgFieldIndex >= 0; --pgFieldIndex)
                {
                    var pgField = pgFields[pgFieldIndex];
                    if (pgField.Name != name)
                    {
                        continue;
                    }

                    if (clrMemberHandlers[pgFieldIndex] != null)
                    {
                        throw new AmbiguousMatchException($"Multiple class members are mapped to the '{pgField.Name}' field.");
                    }

                    if (!typeMapper.TryGetByOID(pgField.Type.OID, out var handler))
                    {
                        throw new NpgsqlException($"PostgreSQL composite type {pgType.DisplayName} has field {pgField.Type.DisplayName} with an unknown type (OID = {pgField.Type.OID}).");
                    }

                    clrMemberHandlerCount++;
                    clrMemberHandlers[pgFieldIndex] = (CompositeMemberHandler <T>)Activator.CreateInstance(
                        clrMemberHandlerType.MakeGenericType(clrType, clrMemberType),
                        BindingFlags.Instance | BindingFlags.Public,
                        binder: null,
                        args: new object[] { clrMember, pgField.Type, handler },
                        culture: null) !;

                    break;
                }
            }
        }
Пример #13
0
        static CompositeConstructorHandler <T>?CreateConstructorHandler(PostgresCompositeType pgType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator)
        {
            var pgFields = pgType.Fields;
            var clrType  = typeof(T);

            ConstructorInfo?clrDefaultConstructor = null;

            foreach (var clrConstructor in clrType.GetConstructors())
            {
                var clrParameters = clrConstructor.GetParameters();
                if (clrParameters.Length != pgFields.Count)
                {
                    if (clrParameters.Length == 0)
                    {
                        clrDefaultConstructor = clrConstructor;
                    }

                    continue;
                }

                var clrParameterHandlerCount = 0;
                var clrParametersMapped      = new ParameterInfo[pgFields.Count];

                foreach (var clrParameter in clrParameters)
                {
                    var attr = clrParameter.GetCustomAttribute <PgNameAttribute>();
                    var name = attr?.PgName ?? (clrParameter.Name is string clrName ? nameTranslator.TranslateMemberName(clrName) : null);
                    if (name is null)
                    {
                        break;
                    }

                    for (var pgFieldIndex = pgFields.Count - 1; pgFieldIndex >= 0; --pgFieldIndex)
                    {
                        var pgField = pgFields[pgFieldIndex];
                        if (pgField.Name != name)
                        {
                            continue;
                        }

                        if (clrParametersMapped[pgFieldIndex] != null)
                        {
                            throw new AmbiguousMatchException($"Multiple constructor parameters are mapped to the '{pgField.Name}' field.");
                        }

                        clrParameterHandlerCount++;
                        clrParametersMapped[pgFieldIndex] = clrParameter;

                        break;
                    }
                }

                if (clrParameterHandlerCount < pgFields.Count)
                {
                    continue;
                }

                var clrParameterHandlers = new CompositeParameterHandler[pgFields.Count];
                for (var pgFieldIndex = 0; pgFieldIndex < pgFields.Count; ++pgFieldIndex)
                {
                    var pgField = pgFields[pgFieldIndex];

                    if (!typeMapper.TryGetByOID(pgField.Type.OID, out var handler))
                    {
                        throw new NpgsqlException($"PostgreSQL composite type {pgType.DisplayName} has field {pgField.Type.DisplayName} with an unknown type (OID = {pgField.Type.OID}).");
                    }

                    var clrParameter            = clrParametersMapped[pgFieldIndex];
                    var clrParameterHandlerType = typeof(CompositeParameterHandler <>)
                                                  .MakeGenericType(clrParameter.ParameterType);

                    clrParameterHandlers[pgFieldIndex] = (CompositeParameterHandler)Activator.CreateInstance(
                        clrParameterHandlerType,
                        BindingFlags.Instance | BindingFlags.Public,
                        binder: null,
                        args: new object[] { handler, clrParameter },
                        culture: null) !;
                }

                return(CompositeConstructorHandler <T> .Create(pgType, clrConstructor, clrParameterHandlers));
            }

            if (clrDefaultConstructor is null && !clrType.IsValueType)
            {
                throw new InvalidOperationException($"No parameterless constructor defined for type '{clrType}'.");
            }

            return(null);
        }
Пример #14
0
 public RecordHandler(PostgresType postgresType, ConnectorTypeMapper typeMapper)
     : base(postgresType)
 {
     _typeMapper = typeMapper;
 }
Пример #15
0
 internal ParseMessage Populate(string sql, string statementName, List <NpgsqlParameter> inputParameters, ConnectorTypeMapper typeMapper)
 {
     Populate(sql, statementName);
     foreach (var inputParam in inputParameters)
     {
         inputParam.ResolveHandler(typeMapper);
         ParameterTypeOIDs.Add(inputParam.Handler.PostgresType.OID);
     }
     return(this);
 }
Пример #16
0
 internal ParseMessage Populate(string sql, string statementName, List <NpgsqlParameter> inputParameters, ConnectorTypeMapper typeMapper)
 {
     Populate(sql, statementName);
     foreach (var inputParam in inputParameters)
     {
         Debug.Assert(inputParam.Handler != null, "Input parameter doesn't have a resolved handler when populating Parse message");
         ParameterTypeOIDs.Add(inputParam.Handler.PostgresType.OID);
     }
     return(this);
 }
Пример #17
0
 public RecordHandler(PostgresType postgresType, ConnectorTypeMapper typeMapper)
 {
     PostgresType = postgresType;
     _typeMapper  = typeMapper;
 }
Пример #18
0
 public RecordHandler(ConnectorTypeMapper typeMapper)
 {
     _typeMapper = typeMapper;
 }