private object ReadLargeObject(NpgsqlRowDescription.FieldData field_descr, int field_value_size) { var cms = new LargeMemoryStream(Stream, field_value_size); try { return (NpgsqlTypesHelper.ConvertBackendStringToSystemType( field_descr.TypeInfo, new StreamReader(cms, Encoding.UTF8), field_descr.TypeSize, field_descr.TypeModifier)); } catch (InvalidCastException ice) { return(ice); } catch (Exception ex) { return(new InvalidCastException(ex.Message, ex)); } }
protected override object ReadNext() { int fieldSize = GetThisFieldCount(); if (fieldSize >= _messageSize) { AbandonShip(); } _nextFieldSize = null; // Check if this field is null if (fieldSize == -1) // Null value { return(DBNull.Value); } NpgsqlRowDescription.FieldData field_descr = FieldData; if (fieldSize >= 32768) { return(ReadLargeObject(field_descr, fieldSize)); } try { if (field_descr.FormatCode == FormatCode.Text) { PGUtil.CheckedStreamRead(Stream, bytes.Large, 0, fieldSize); var str = UTF8Encoding.GetString(bytes.Large, 0, fieldSize); return (NpgsqlTypesHelper.ConvertBackendStringToSystemType( field_descr.TypeInfo, str, field_descr.TypeSize, field_descr.TypeModifier)); } else { var buffer = new byte[fieldSize]; PGUtil.CheckedStreamRead(Stream, buffer, 0, fieldSize); return (NpgsqlTypesHelper.ConvertBackendBytesToSystemType( field_descr.TypeInfo, buffer, fieldSize, field_descr.TypeModifier)); } } catch (IOException) { throw; } catch (InvalidCastException ice) { return(ice); } catch (Exception ex) { return(new InvalidCastException(ex.Message, ex)); } }
/// <summary> /// Creates a prepared version of the command on a PostgreSQL server. /// </summary> public override void Prepare() { // Check the connection state. CheckConnectionState(); // reset any responses just before getting new ones Connector.Mediator.ResetResponses(); // Set command timeout. m_Connector.Mediator.CommandTimeout = CommandTimeout; if (!m_Connector.SupportsPrepare) { return; // Do nothing. } using (m_Connector.BlockNotificationThread()) { try { // Use the extended query parsing... planName = m_Connector.NextPlanName(); String portalName = m_Connector.NextPortalName(); parse = new NpgsqlParse(planName, GetParseCommandText(), new Int32[] { }); m_Connector.Parse(parse); // We need that because Flush() doesn't cause backend to send // ReadyForQuery on error. Without ReadyForQuery, we don't return // from query extended processing. // We could have used Connector.Flush() which sends us back a // ReadyForQuery, but on postgresql server below 8.1 there is an error // with extended query processing which hinders us from using it. m_Connector.RequireReadyForQuery = false; m_Connector.Flush(); // Description... NpgsqlDescribe describe = new NpgsqlDescribe('S', planName); m_Connector.Describe(describe); NpgsqlRowDescription returnRowDesc = m_Connector.Sync(); Int16[] resultFormatCodes; if (returnRowDesc != null) { resultFormatCodes = new Int16[returnRowDesc.NumFields]; for (int i = 0; i < returnRowDesc.NumFields; i++) { NpgsqlRowDescription.FieldData returnRowDescData = returnRowDesc[i]; if (returnRowDescData.TypeInfo != null && returnRowDescData.TypeInfo.NpgsqlDbType == NpgsqlDbType.Bytea) { // Binary format resultFormatCodes[i] = (Int16)FormatCode.Binary; } else { // Text Format resultFormatCodes[i] = (Int16)FormatCode.Text; } } } else { resultFormatCodes = new Int16[] { 0 }; } bind = new NpgsqlBind("", planName, new Int16[Parameters.Count], null, resultFormatCodes); } catch (IOException e) { throw ClearPoolAndCreateException(e); } catch { // As per documentation: // "[...] When an error is detected while processing any extended-query message, // the backend issues ErrorResponse, then reads and discards messages until a // Sync is reached, then issues ReadyForQuery and returns to normal message processing.[...]" // So, send a sync command if we get any problems. m_Connector.Sync(); throw; } } }