1 // created on 13/6/2002 at 21:06
3 // Npgsql.NpgsqlAsciiRow.cs
6 // Francisco Jr. (fxjrlists@yahoo.com.br)
8 // Copyright (C) 2002 The Npgsql Development Team
9 // npgsql-general@gborg.postgresql.org
10 // http://gborg.postgresql.org/project/npgsql/projdisplay.php
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 using System.Collections;
38 /// This class represents the AsciiRow message sent from PostgreSQL
42 internal sealed class NpgsqlAsciiRow
44 // Logging related values
45 private static readonly String CLASSNAME = "NpgsqlAsciiRow";
47 private ArrayList data;
48 private Byte[] null_map_array;
49 private Int16 num_fields;
50 private readonly Int16 READ_BUFFER_SIZE = 300; //[FIXME] Is this enough??
51 private NpgsqlRowDescription row_desc;
52 private Hashtable oid_to_name_mapping;
54 public NpgsqlAsciiRow(NpgsqlRowDescription rowDesc, Hashtable oidToNameMapping)
56 NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".NpgsqlAsciiRow()", LogLevel.Debug);
58 data = new ArrayList();
60 null_map_array = new Byte[(row_desc.NumFields + 7)/8];
61 oid_to_name_mapping = oidToNameMapping;
62 //num_fields = numFields;
68 public void ReadFromStream(Stream inputStream, Encoding encoding)
70 NpgsqlEventLog.LogMsg("Entering " + CLASSNAME + ".ReadFromStream()", LogLevel.Debug);
72 Byte[] input_buffer = new Byte[READ_BUFFER_SIZE];
74 Array.Clear(null_map_array, 0, null_map_array.Length);
76 // Read the null fields bitmap.
77 PGUtil.CheckedStreamRead(inputStream, null_map_array, 0, null_map_array.Length );
80 for (Int16 field_count = 0; field_count < row_desc.NumFields; field_count++)
83 // Check if this field isn't null
84 if (IsNull(field_count))
86 // Field is null just keep next field.
88 //[FIXME] See this[] method.
93 // Read the first data of the first row.
95 PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, 4);
97 Int32 field_value_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
99 Int32 bytes_left = field_value_size - 4;
101 StringBuilder result = new StringBuilder();
103 while (bytes_left > READ_BUFFER_SIZE)
105 // Now, read just the field value.
106 PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, READ_BUFFER_SIZE);
108 // Read the bytes as string.
109 result.Append(new String(encoding.GetChars(input_buffer, 0, READ_BUFFER_SIZE)));
111 bytes_left -= READ_BUFFER_SIZE;
114 // Now, read just the field value.
115 PGUtil.CheckedStreamRead(inputStream, input_buffer, 0, bytes_left);
117 // Read the bytes as string.
118 result.Append(new String(encoding.GetChars(input_buffer, 0, bytes_left)));
121 // Add them to the AsciiRow data.
122 data.Add(NpgsqlTypesHelper.ConvertBackendStringToSystemType(oid_to_name_mapping, result.ToString(), row_desc[field_count].type_oid, row_desc[field_count].type_modifier));
129 public Boolean IsNull(Int32 index)
131 // [FIXME] Check more optimized way of doing this.
132 // Should this be public or internal?
134 // Check valid index range.
135 if ((index < 0) || (index >= row_desc.NumFields))
136 throw new ArgumentOutOfRangeException("index");
138 // Check if the value (index) of the field is null
140 // Get the byte that holds the bit index position.
141 Byte test_byte = null_map_array[index/8];
143 // Now, check if index bit is set.
144 // To this, get its position in the byte, shift to
145 // MSB and test it with the byte 10000000.
146 return (((test_byte << (index%8)) & 0x80) == 0);
150 public Object this[Int32 index]
155 if ((index < 0) || (index >= row_desc.NumFields))
156 throw new ArgumentOutOfRangeException("this[] index value");
157 // [FIXME] Should return null or something else
160 //[FIXME] This code assumes that the data arraylist has the null and non null values
161 // in order, but just the non-null values are added.
162 // It is necessary to map the index value with the elements in the array list.
163 // For now, the workaround is to insert the null values in the array list.
164 // But this is a hack. :)
166 //return (IsNull(index) ? null : data[index]);