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); }
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); }
void Cleanup() { Log.Debug("COPY operation ended", _connector.Id); _connector = null; _typeMapper = null; _buf = null; _isDisposed = true; }
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 !; }
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; }
public void Setup() { _conn = BenchmarkEnvironment.OpenConnection(); _typeMapper = (ConnectorTypeMapper)_conn.TypeMapper; if (NumPlugins > 0) { _typeMapper.UseNodaTime(); } if (NumPlugins > 1) { _typeMapper.UseNetTopologySuite(); } }
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(); }
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; }
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; } }
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); }
public CompositeHandler(PostgresCompositeType postgresType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator) : base(postgresType) { _typeMapper = typeMapper; _nameTranslator = nameTranslator; }
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; } } }
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); }
public RecordHandler(PostgresType postgresType, ConnectorTypeMapper typeMapper) : base(postgresType) { _typeMapper = typeMapper; }
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); }
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); }
public RecordHandler(PostgresType postgresType, ConnectorTypeMapper typeMapper) { PostgresType = postgresType; _typeMapper = typeMapper; }
public RecordHandler(ConnectorTypeMapper typeMapper) { _typeMapper = typeMapper; }