void BindArrayType(NpgsqlTypeHandler elementHandler, PostgresArrayType pgArrayType, NpgsqlDbType?elementNpgsqlDbType, Type[] elementClrTypes) { var arrayHandler = elementHandler.CreateArrayHandler(pgArrayType); var arrayNpgsqlDbType = elementNpgsqlDbType.HasValue ? NpgsqlDbType.Array | elementNpgsqlDbType.Value : (NpgsqlDbType?)null; BindType(arrayHandler, pgArrayType, arrayNpgsqlDbType); // Note that array handlers aren't registered in ByClrType like base types, because they handle all // dimension types and not just one CLR type (e.g. int[], int[,], int[,,]). // So the by-type lookup is special and goes via _arrayHandlerByClrType, see this[Type type] // TODO: register single-dimensional in _byType as a specific optimization? But do PSV as well... if (elementClrTypes != null) { foreach (var elementType in elementClrTypes) { if (_arrayHandlerByClrType.ContainsKey(elementType)) { throw new Exception( $"Two array type handlers registered on same .NET type {elementType}: {_arrayHandlerByClrType[elementType].GetType().Name} and {arrayHandler.GetType().Name}"); } _arrayHandlerByClrType[elementType] = arrayHandler; } } }
/// <inheritdoc /> protected ArrayHandler(PostgresType arrayPostgresType, NpgsqlTypeHandler elementHandler, ArrayNullabilityMode arrayNullabilityMode, int lowerBound = 1) : base(arrayPostgresType) { LowerBound = lowerBound; ElementHandler = elementHandler; ArrayNullabilityMode = arrayNullabilityMode; }
internal bool TryGetByOID(uint oid, out NpgsqlTypeHandler handler) { if (_byOID.TryGetValue(oid, out handler)) { return(true); } // TODO: Late activation (composite/enum) return(false); }
internal static void ThrowInvalidCastException_NotSupportedType(NpgsqlTypeHandler handler, NpgsqlParameter?parameter, Type type) { var parameterName = parameter is null ? null : parameter.TrimmedName == string.Empty ? $"${parameter.Collection!.IndexOf(parameter) + 1}" : parameter.TrimmedName; throw new InvalidCastException(parameterName is null ? $"Cannot write a value of CLR type '{type}' as database type '{handler.PgDisplayName}'." : $"Cannot write a value of CLR type '{type}' as database type '{handler.PgDisplayName}' for parameter '{parameterName}'."); }
async ValueTask <T> DoRead <T>(NpgsqlTypeHandler handler, bool async) { try { await ReadColumnLenIfNeeded(async); if (_columnLen == -1) { #pragma warning disable CS8653 // A default expression introduces a null value when 'T' is a non-nullable reference type. // When T is a Nullable<T>, we support returning null if (NullableHandler <T> .Exists) { return(default);
void BindType(NpgsqlTypeHandler handler, PostgresType pgType, NpgsqlDbType?npgsqlDbType = null, DbType[] dbTypes = null, Type[] clrTypes = null) { _byOID[pgType.OID] = handler; _byTypeName[pgType.FullName] = handler; _byTypeName[pgType.Name] = handler; if (npgsqlDbType.HasValue) { var value = npgsqlDbType.Value; if (_byNpgsqlDbType.ContainsKey(value)) { throw new InvalidOperationException($"Two type handlers registered on same NpgsqlDbType '{npgsqlDbType}': {_byNpgsqlDbType[value].GetType().Name} and {handler.GetType().Name}"); } _byNpgsqlDbType[npgsqlDbType.Value] = handler; } if (dbTypes != null) { foreach (var dbType in dbTypes) { if (_byDbType.ContainsKey(dbType)) { throw new InvalidOperationException($"Two type handlers registered on same DbType {dbType}: {_byDbType[dbType].GetType().Name} and {handler.GetType().Name}"); } _byDbType[dbType] = handler; } } if (clrTypes != null) { foreach (var type in clrTypes) { if (_byClrType.ContainsKey(type)) { throw new InvalidOperationException($"Two type handlers registered on same .NET type '{type}': {_byClrType[type].GetType().Name} and {handler.GetType().Name}"); } _byClrType[type] = handler; } } if (pgType.Array != null) { BindArrayType(handler, pgType.Array, npgsqlDbType, clrTypes); } if (pgType.Range != null) { BindRangeType(handler, pgType.Range, npgsqlDbType, clrTypes); } }
public CompositeClassMemberHandler(FieldInfo fieldInfo, PostgresType postgresType, NpgsqlTypeHandler handler) : base(fieldInfo, postgresType) { var composite = Expression.Parameter(typeof(TComposite), "composite"); var value = Expression.Parameter(typeof(TMember), "value"); _get = Expression .Lambda <GetMember>(Expression.Field(composite, fieldInfo), composite) .Compile(); _set = Expression .Lambda <SetMember>(Expression.Assign(Expression.Field(composite, fieldInfo), value), composite, value) .Compile(); _handler = handler; }
async ValueTask <T> DoRead <T>(NpgsqlTypeHandler handler, bool async, CancellationToken cancellationToken = default) { try { using var registration = _connector.StartNestedCancellableOperation(cancellationToken); await ReadColumnLenIfNeeded(async); if (_columnLen == -1) { #pragma warning disable CS8653 // A default expression introduces a null value when 'T' is a non-nullable reference type. // When T is a Nullable<T>, we support returning null if (NullableHandler <T> .Exists) { return(default !);
void BindRangeType(NpgsqlTypeHandler elementHandler, PostgresRangeType pgRangeType, NpgsqlDbType?elementNpgsqlDbType, Type[]?elementClrTypes) { var rangeHandler = elementHandler.CreateRangeHandler(pgRangeType); var rangeNpgsqlDbType = elementNpgsqlDbType.HasValue ? NpgsqlDbType.Range | elementNpgsqlDbType.Value : (NpgsqlDbType?)null; // We only want to bind supported range CLR types whose element CLR types are being bound as well. var clrTypes = elementClrTypes is null ? null : rangeHandler.SupportedRangeClrTypes .Where(r => elementClrTypes.Contains(r.GenericTypeArguments[0])) .ToArray(); BindType((NpgsqlTypeHandler)rangeHandler, pgRangeType, rangeNpgsqlDbType, null, clrTypes); }
internal NodaTimeTypeHandlerResolver(NpgsqlConnector connector) { _databaseInfo = connector.DatabaseInfo; _timestampHandler = LegacyTimestampBehavior ? new LegacyTimestampHandler(PgType("timestamp without time zone")) : new TimestampHandler(PgType("timestamp without time zone")); _timestampTzHandler = LegacyTimestampBehavior ? new LegacyTimestampTzHandler(PgType("timestamp with time zone")) : new TimestampTzHandler(PgType("timestamp with time zone")); _dateHandler = new DateHandler(PgType("date")); _timeHandler = new TimeHandler(PgType("time without time zone")); _timeTzHandler = new TimeTzHandler(PgType("time with time zone")); _intervalHandler = new IntervalHandler(PgType("interval")); // Note that the range handlers are absent on some pseudo-PostgreSQL databases (e.g. CockroachDB), and multirange types // were only introduced in PG14. So we resolve these lazily. _arrayNullabilityMode = connector.Settings.ArrayNullabilityMode; }
public CompositeClassMemberHandler(PropertyInfo propertyInfo, PostgresType postgresType, NpgsqlTypeHandler handler) : base(propertyInfo, postgresType) { var getMethod = propertyInfo.GetGetMethod(); if (getMethod != null) { _get = (GetMember)Delegate.CreateDelegate(typeof(GetMember), getMethod); } var setMethod = propertyInfo.GetSetMethod(); if (setMethod != null) { _set = (SetMember)Delegate.CreateDelegate(typeof(SetMember), setMethod); } Debug.Assert(setMethod != null || getMethod != null); _handler = handler; }
void BindRangeType(NpgsqlTypeHandler elementHandler, PostgresRangeType pgRangeType, NpgsqlDbType?elementNpgsqlDbType, Type[] elementClrTypes) { var rangeHandler = elementHandler.CreateRangeHandler(pgRangeType); var rangeNpgsqlDbType = elementNpgsqlDbType.HasValue ? NpgsqlDbType.Range | elementNpgsqlDbType.Value : (NpgsqlDbType?)null; Type[] clrTypes = null; if (elementClrTypes != null) { // Somewhat hacky. Although the element may have more than one CLR mapping, // its range will only be mapped to the "main" one for now. var defaultElementType = elementHandler.GetFieldType(); clrTypes = elementClrTypes.Contains(defaultElementType) ? new[] { rangeHandler.GetFieldType() } : null; } BindType(rangeHandler, pgRangeType, rangeNpgsqlDbType, null, clrTypes); }
T DoRead <T>(NpgsqlTypeHandler handler) { try { ReadColumnLenIfNeeded(); if (_columnLen == -1) { throw new InvalidCastException("Column is null"); } // If we know the entire column is already in memory, use the code path without async var result = _columnLen <= _buf.ReadBytesLeft ? handler.Read <T>(_buf, _columnLen) : handler.Read <T>(_buf, _columnLen, false).GetAwaiter().GetResult(); _leftToReadInDataMsg -= _columnLen; _columnLen = int.MinValue; // Mark that the (next) column length hasn't been read yet _column++; return(result); } catch { _connector.Break(); Cleanup(); throw; } }
public DateRangeHandler(PostgresType rangePostgresType, NpgsqlTypeHandler subtypeHandler) : base(rangePostgresType, subtypeHandler) { }
public CompositeParameterHandler(NpgsqlTypeHandler handler, ParameterInfo parameterInfo) { Handler = handler; ParameterType = parameterInfo.ParameterType; ParameterPosition = parameterInfo.Position; }
internal bool TryGetByOID(uint oid, out NpgsqlTypeHandler handler) => _byOID.TryGetValue(oid, out handler);
/// <inheritdoc /> protected ArrayHandler(PostgresType arrayPostgresType, NpgsqlTypeHandler elementHandler, int lowerBound = 1) : base(arrayPostgresType) { LowerBound = lowerBound; ElementHandler = elementHandler; }
public ColumnInfo(uint typeOid, int bufferPos, NpgsqlTypeHandler typeHandler) { TypeOid = typeOid; BufferPos = bufferPos; TypeHandler = typeHandler; }
public ArrayHandlerWithPsv(NpgsqlTypeHandler elementHandler) : base(elementHandler) { }
/// <inheritdoc /> public RangeHandler(PostgresType rangePostgresType, NpgsqlTypeHandler subtypeHandler) : base(rangePostgresType) => SubtypeHandler = subtypeHandler;
/// <inheritdoc /> protected RangeHandler(PostgresType rangePostgresType, NpgsqlTypeHandler elementHandler, Type[] supportedElementClrTypes) : base(rangePostgresType) { _elementHandler = elementHandler; SupportedRangeClrTypes = supportedElementClrTypes; }
public CrateDbObjectArrayHandler(NpgsqlTypeHandler elementHandler) : base(elementHandler) { }
public RangeHandler(NpgsqlTypeHandler <TElement> elementHandler) { ElementHandler = elementHandler; }
/// <inheritdoc /> public RangeHandler(PostgresType rangePostgresType, NpgsqlTypeHandler subtypeHandler) : this(rangePostgresType, subtypeHandler, new[] { typeof(NpgsqlRange <TElement>) }) { }
public CompositeParameterHandler(NpgsqlTypeHandler handler, ParameterInfo parameterInfo) : base(handler, parameterInfo) { }
/// <inheritdoc /> protected RangeHandler(PostgresType rangePostgresType, NpgsqlTypeHandler subtypeHandler, Type[] supportedSubtypeClrTypes) { PostgresType = rangePostgresType; _subtypeHandler = subtypeHandler; SupportedRangeClrTypes = supportedSubtypeClrTypes; }
internal void ResolveHandler() => Handler = IsBinaryFormat ? _typeMapper.GetByOID(TypeOID) : _typeMapper.UnrecognizedTypeHandler;
public TimestampTzRangeHandler(PostgresType rangePostgresType, NpgsqlTypeHandler subtypeHandler) : base(rangePostgresType, subtypeHandler) { }