/// <summary> /// Serialise the enumeration or array. /// </summary> public byte[] ArrayToArrayText(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { MemoryStream array = new MemoryStream(); if (! forExtendedQuery) { if (! options.UseConformantStrings && options.Supports_E_StringPrefix) { array.WriteByte((byte)ASCIIBytes.E); } array.WriteByte((byte)ASCIIBytes.SingleQuote); } if (! WriteItemText(TypeInfo, NativeData, array, forExtendedQuery, options)) { array.Write(ASCIIArrayByteArrays.EmptyArray, 0, ASCIIArrayByteArrays.EmptyArray.Length); } if (! forExtendedQuery) { array.WriteByte((byte)ASCIIBytes.SingleQuote); } return array.ToArray(); }
private byte[] ConvertToBackendPlainQuery(Object NativeData, NativeToBackendTypeConverterOptions options, bool arrayElement) { if ((NativeData == DBNull.Value) || (NativeData == null)) { return(ASCIIByteArrays.NULL); // Plain queries exptects null values as string NULL. } if (_ConvertNativeToBackendText != null) { byte[] backendSerialization; // This path is responsible for escaping, and may also add quoting and the E prefix. backendSerialization = (_ConvertNativeToBackendText(this, NativeData, false, options, arrayElement)); if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, false, arrayElement); } return(backendSerialization); } else if (NativeData is Enum) { byte[] backendSerialization; // Do a special handling of Enum values. // Translate enum value to its underlying type. backendSerialization = BackendEncoding.UTF8Encoding.GetBytes( (String)Convert.ChangeType( Enum.Format(NativeData.GetType(), NativeData, "d"), typeof(String), CultureInfo.InvariantCulture ) ); backendSerialization = QuoteASCIIString(backendSerialization, false, arrayElement); return(backendSerialization); } else { byte[] backendSerialization; if (NativeData is IFormattable) { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(((IFormattable)NativeData).ToString(null, ni)); } else { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(NativeData.ToString()); } if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, false, arrayElement); } return(backendSerialization); } }
private byte[] ConvertToBackendExtendedQuery(Object NativeData, NativeToBackendTypeConverterOptions options, bool arrayElement) { if ((NativeData == DBNull.Value) || (NativeData == null)) { return(null); // Extended query expects null values be represented as null. } if (!NpgsqlTypesHelper.SuppressBinaryBackendEncoding && _ConvertNativeToBackendBinary != null) { return(_ConvertNativeToBackendBinary(this, NativeData, options)); } else if (_ConvertNativeToBackendText != null) { byte[] backendSerialization; backendSerialization = _ConvertNativeToBackendText(this, NativeData, true, options, arrayElement); if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, true, arrayElement); } return(backendSerialization); } else { byte[] backendSerialization; if (NativeData is Enum) { // Do a special handling of Enum values. // Translate enum value to its underlying type. backendSerialization = BackendEncoding.UTF8Encoding.GetBytes((String) Convert.ChangeType(Enum.Format(NativeData.GetType(), NativeData, "d"), typeof(String), CultureInfo.InvariantCulture)); } else if (NativeData is IFormattable) { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(((IFormattable)NativeData).ToString(null, ni)); } else { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(NativeData.ToString()); } if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, true, arrayElement); } return(backendSerialization); } }
/// <summary> /// Perform a data conversion from a native object to /// a backend representation. /// DBNull and null values are handled differently depending if a plain query is used /// When /// </summary> /// <param name="NativeData">Native .NET object to be converted.</param> /// <param name="forExtendedQuery">Specifies that the value should be formatted for the extended query syntax.</param> /// <param name="options">Options to guide serialization. If null, a default options set is used.</param> /// <param name="arrayElement">Specifies that the value should be formatted as an extended query array element.</param> public byte[] ConvertToBackend(Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options = null, bool arrayElement = false) { if (options == null) { options = NativeToBackendTypeConverterOptions.Default; } if (forExtendedQuery) { return(ConvertToBackendExtendedQuery(NativeData, options, arrayElement)); } else { return(ConvertToBackendPlainQuery(NativeData, options, arrayElement)); } }
/// <summary> /// Convert a System.Array to PG binary format. /// Write the array header and prepare to write array data to the stream. /// </summary> public byte[] ArrayToArrayBinary(NpgsqlNativeTypeInfo TypeInfo, object oNativeData, NativeToBackendTypeConverterOptions options) { Array NativeData = (Array)oNativeData; MemoryStream dst = new MemoryStream(); // Write the number of dimensions in the array. PGUtil.WriteInt32(dst, NativeData.Rank); // Placeholder for null bitmap flag, which isn't used? PGUtil.WriteInt32(dst, 0); // Write the OID of the elements of the array. PGUtil.WriteInt32(dst, options.OidToNameMapping[_elementConverter.Name].OID); // White dimension descriptors. for (int i = 0; i < NativeData.Rank; i++) { // Number of elements in the dimension. PGUtil.WriteInt32(dst, NativeData.GetLength(i)); // Lower bounds of the dimension, 1-based for SQL. PGUtil.WriteInt32(dst, NativeData.GetLowerBound(i) + 1); } int[] dimensionOffsets = new int[NativeData.Rank]; // Write all array data. WriteBinaryArrayData(TypeInfo, NativeData, options, dst, 0, dimensionOffsets); return(dst.ToArray()); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, MemoryStream array, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { // As this prcedure handles both prepared and plain query representations, in order to not keep if's inside the loops // we simply set a placeholder here for both openElement ( '{' or '[' ) and closeElement ( '}', or ']' ) byte openElement = (byte)(forExtendedQuery ? ASCIIBytes.BraceCurlyLeft : ASCIIBytes.BraceSquareLeft); byte closeElement = (byte)(forExtendedQuery ? ASCIIBytes.BraceCurlyRight : ASCIIBytes.BraceSquareRight); bool writtenSomething = false; bool firstItem = true; array.WriteByte(openElement); //write each item with a comma between them. foreach (object item in col) { if (firstItem) { firstItem = false; } else { array.WriteByte((byte)ASCIIBytes.Comma); } writtenSomething |= WriteItemText(TypeInfo, item, array, forExtendedQuery, options); } if (writtenSomething) { array.WriteByte(closeElement); } return writtenSomething; }
private bool WriteItem(NpgsqlNativeTypeInfo TypeInfo, object item, StringBuilder sb, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { //item could be: //an Ienumerable - in which case we call WriteEnumeration //an element - in which case we call the NpgsqlNativeTypeInfo for that type to serialise it. //an array - in which case we call WriteArray, // Even an string being an IEnumerable, it shouldn't be processed. It will be processed on the last else. // See http://pgfoundry.org/tracker/?func=detail&atid=592&aid=1010514&group_id=1000140 for more info. if(item == null || NpgsqlTypesHelper.DefinedType(item)) { sb.Append(_elementConverter.ConvertToBackend(item, forExtendedQuery, options)); return true; } else if (item is Array) { return WriteArray(TypeInfo, item as Array, sb, forExtendedQuery, options); } else if (item is IEnumerable) { return WriteEnumeration(TypeInfo, item as IEnumerable, sb, forExtendedQuery, options); } else {//This shouldn't really be reachable. sb.Append(_elementConverter.ConvertToBackend(item, forExtendedQuery, options)); return true; } }
/// <summary> /// Serialise the enumeration or array. /// </summary> public string FromArray(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { if (forExtendedQuery) { StringBuilder sb = new StringBuilder(""); if (WriteItem(TypeInfo, NativeData, sb, forExtendedQuery, options)) { return(sb.ToString()); } else { return("{}"); } } else { //just prepend "array" and then pass to WriteItem. StringBuilder sb = new StringBuilder("array"); if (WriteItem(TypeInfo, NativeData, sb, forExtendedQuery, options)) { return(sb.ToString()); } else { return("'{}'"); } } }
/// <summary> /// Append all array data to the binary stream. /// </summary> private void WriteBinaryArrayData(NpgsqlNativeTypeInfo TypeInfo, Array nativeData, NativeToBackendTypeConverterOptions options, MemoryStream dst, int dimensionOffset, int[] dimensionOffsets) { int dimensionLength = nativeData.GetLength(dimensionOffset); int dimensionLBound = nativeData.GetLowerBound(dimensionOffset); if (dimensionOffset < nativeData.Rank - 1) { // Drill down recursively until we hit a single dimension array. for (int i = dimensionLBound ; i < dimensionLBound + dimensionLength ; i++) { dimensionOffsets[dimensionOffset] = i; WriteBinaryArrayData(TypeInfo, nativeData, options, dst, dimensionOffset + 1, dimensionOffsets); } } else { // Write the individual array elements to the output stream. for (int i = dimensionLBound ; i < dimensionLBound + dimensionLength ; i++) { object elementNative; dimensionOffsets[dimensionOffset] = i; elementNative = nativeData.GetValue(dimensionOffsets); if (elementNative == null || elementNative == DBNull.Value) { // Write length identifier -1 indicating NULL value. dst.WriteInt32(-1); } else { byte[] elementBinary; elementBinary = (byte[])_elementConverter.ConvertToBackend(elementNative, true, options); // Write lenght identifier. dst.WriteInt32(elementBinary.Length); // Write element data. dst.Write(elementBinary, 0, elementBinary.Length); } } } }
private byte[] ConvertToBackendExtendedQuery(Object NativeData, NativeToBackendTypeConverterOptions options, bool arrayElement) { if ((NativeData == DBNull.Value) || (NativeData == null)) { return null; // Extended query expects null values be represented as null. } if (! NpgsqlTypesHelper.SuppressBinaryBackendEncoding && _ConvertNativeToBackendBinary != null) { return _ConvertNativeToBackendBinary(this, NativeData, options); } else if (_ConvertNativeToBackendText != null) { byte[] backendSerialization; backendSerialization = _ConvertNativeToBackendText(this, NativeData, true, options, arrayElement); if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, true, arrayElement); } return backendSerialization; } else { byte[] backendSerialization; if (NativeData is Enum) { // Do a special handling of Enum values. // Translate enum value to its underlying type. backendSerialization = BackendEncoding.UTF8Encoding.GetBytes((String) Convert.ChangeType(Enum.Format(NativeData.GetType(), NativeData, "d"), typeof (String), CultureInfo.InvariantCulture)); } else if (NativeData is IFormattable) { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(((IFormattable) NativeData).ToString(null, ni)); } else { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(NativeData.ToString()); } if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, true, arrayElement); } return backendSerialization; } }
/// <summary> /// Convert to a postgresql boolean binary format. /// </summary> internal static byte[] BooleanToBooleanBinary(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, NativeToBackendTypeConverterOptions options) { return(((bool)NativeData) ? ASCIIByteArrays.Byte_1 : ASCIIByteArrays.Byte_0); }
/// <summary> /// Perform a data conversion from a native object to /// a backend representation. /// DBNull and null values are handled differently depending if a plain query is used /// When /// </summary> /// <param name="NativeData">Native .NET object to be converted.</param> /// <param name="forExtendedQuery">Specifies that the value should be formatted for the extended query syntax.</param> /// <param name="options">Options to guide serialization. If null, a default options set is used.</param> /// <param name="arrayElement">Specifies that the value should be formatted as an extended query array element.</param> public byte[] ConvertToBackend(Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options = null, bool arrayElement = false) { if (options == null) { options = NativeToBackendTypeConverterOptions.Default; } if (forExtendedQuery) { return ConvertToBackendExtendedQuery(NativeData, options, arrayElement); } else { return ConvertToBackendPlainQuery(NativeData, options, arrayElement); } }
private byte[] ConvertToBackendPlainQuery(Object NativeData, NativeToBackendTypeConverterOptions options, bool arrayElement) { if ((NativeData == DBNull.Value) || (NativeData == null)) { return ASCIIByteArrays.NULL; // Plain queries exptects null values as string NULL. } if (_ConvertNativeToBackendText != null) { byte[] backendSerialization; // This path is responsible for escaping, and may also add quoting and the E prefix. backendSerialization = (_ConvertNativeToBackendText(this, NativeData, false, options, arrayElement)); if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, false, arrayElement); } return backendSerialization; } else if (NativeData is Enum) { byte[] backendSerialization; // Do a special handling of Enum values. // Translate enum value to its underlying type. backendSerialization = BackendEncoding.UTF8Encoding.GetBytes( (String)Convert.ChangeType( Enum.Format(NativeData.GetType(), NativeData, "d"), typeof(String), CultureInfo.InvariantCulture ) ); backendSerialization = QuoteASCIIString(backendSerialization, false, arrayElement); return backendSerialization; } else { byte[] backendSerialization; if (NativeData is IFormattable) { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(((IFormattable)NativeData).ToString(null, ni)); } else { backendSerialization = BackendEncoding.UTF8Encoding.GetBytes(NativeData.ToString()); } if (Quote) { backendSerialization = QuoteASCIIString(backendSerialization, false, arrayElement); } return backendSerialization; } }
internal void Bind(NativeToBackendTypeConverterOptions nativeToBackendTypeConverterOptions) { BoundValue = TypeInfo.ConvertToBackend(NpgsqlValue, true, nativeToBackendTypeConverterOptions); if (BoundValue == null) { BoundFormatCode = (short)FormatCode.Binary; } else { BoundFormatCode = TypeInfo.SupportsBinaryBackendData ? (short)FormatCode.Binary : (short)FormatCode.Text; } IsBound = true; }
internal void SetTypeOID(int oid, NativeToBackendTypeConverterOptions nativeToBackendTypeConverterOptions) { TypeOID = oid; // If the db backend specified another type, we have to use that one. NpgsqlBackendTypeInfo backendTypeInfo; nativeToBackendTypeConverterOptions.OidToNameMapping.TryGetValue(TypeOID, out backendTypeInfo); if (backendTypeInfo != null && backendTypeInfo.Name != TypeInfo.Name && !explicitUnknown) { NpgsqlDbType = backendTypeInfo.NpgsqlDbType; Value = NpgsqlValue; } }
static NativeToBackendTypeConverterOptions() { _default = new NativeToBackendTypeConverterOptions(true, false, true, false, null); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, MemoryStream array, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { bool writtenSomething = false; bool firstItem = true; //write each item with a comma between them. foreach (object item in col) { if (firstItem) { array.WriteByte((byte)ASCIIBytes.BraceCurlyLeft); firstItem = false; } else { array.WriteByte((byte)ASCIIBytes.Comma); } writtenSomething |= WriteItemText(TypeInfo, item, array, forExtendedQuery, options); } if (writtenSomething) { array.WriteByte((byte)ASCIIBytes.BraceCurlyRight); } return(writtenSomething); }
/// <summary> /// Convert to a postgresql binary int8. /// </summary> internal static byte[] Int64ToInt8Binary(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, NativeToBackendTypeConverterOptions options) { return(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Convert.ToInt64(NativeData)))); }
private bool WriteArray(NpgsqlNativeTypeInfo TypeInfo, Array ar, StringBuilder sb, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { bool writtenSomething = false; //we need to know the size of each dimension. int c = ar.Rank; List <int> lengths = new List <int>(c); do { lengths.Add(ar.GetLength(--c)); }while (c != 0); //c is now zero. Might as well reuse it! foreach (object item in ar) { // As this prcedure handles both prepared and plain query representations, in order to not keep if's inside the loops // we simply set a placeholder here for both openElement ( '{' or '[' ) and closeElement ( '}', or ']' ) Char openElement = forExtendedQuery ? '{' : '['; Char closeElement = forExtendedQuery ? '}' : ']'; //to work out how many [ characters we need we need to work where we are compared to the dimensions. //Say we are at position 24 in a 3 * 4 * 5 array. //We're at the end of a row as 24 % 3 == 0 so write one [ for that. //We're at the end of a square as 24 % (3 * 4) == 24 % (12) == 0 so write one [ for that. //We're not at the end of a cube as 24 % (3 * 4 * 5) == 24 % (30) != 0, so we're finished for that pass. int curlength = 1; foreach (int lengthTest in lengths) { if (c % (curlength *= lengthTest) == 0) { //sb.Append('['); sb.Append(openElement); } else { break; } } //Write whatever the element is. writtenSomething |= WriteItem(TypeInfo, item, sb, forExtendedQuery, options); ++c; //up our counter for knowing when to write [ and ] //same logic as above for writing [ this time writing ] curlength = 1; foreach (int lengthTest in lengths) { if (c % (curlength *= lengthTest) == 0) { //sb.Append(']'); sb.Append(closeElement); } else { break; } } //comma between each item. sb.Append(','); } if (writtenSomething) { //last comma was one too many. sb.Remove(sb.Length - 1, 1); } return(writtenSomething); }
private bool WriteArray(NpgsqlNativeTypeInfo TypeInfo, Array ar, StringBuilder sb, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { bool writtenSomething = false; //we need to know the size of each dimension. int c = ar.Rank; List<int> lengths = new List<int>(c); do { lengths.Add(ar.GetLength(--c)); } while (c != 0); //c is now zero. Might as well reuse it! foreach (object item in ar) { // As this prcedure handles both prepared and plain query representations, in order to not keep if's inside the loops // we simply set a placeholder here for both openElement ( '{' or '[' ) and closeElement ( '}', or ']' ) Char openElement = forExtendedQuery ? '{' : '['; Char closeElement = forExtendedQuery ? '}' : ']'; //to work out how many [ characters we need we need to work where we are compared to the dimensions. //Say we are at position 24 in a 3 * 4 * 5 array. //We're at the end of a row as 24 % 3 == 0 so write one [ for that. //We're at the end of a square as 24 % (3 * 4) == 24 % (12) == 0 so write one [ for that. //We're not at the end of a cube as 24 % (3 * 4 * 5) == 24 % (30) != 0, so we're finished for that pass. int curlength = 1; foreach (int lengthTest in lengths) { if (c%(curlength *= lengthTest) == 0) { //sb.Append('['); sb.Append(openElement); } else { break; } } //Write whatever the element is. writtenSomething |= WriteItem(TypeInfo, item, sb, forExtendedQuery, options); ++c; //up our counter for knowing when to write [ and ] //same logic as above for writing [ this time writing ] curlength = 1; foreach (int lengthTest in lengths) { if (c%(curlength *= lengthTest) == 0) { //sb.Append(']'); sb.Append(closeElement); } else { break; } } //comma between each item. sb.Append(','); } if (writtenSomething) { //last comma was one too many. sb.Remove(sb.Length - 1, 1); } return writtenSomething; }
private bool WriteArrayText(NpgsqlNativeTypeInfo TypeInfo, Array ar, MemoryStream array, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { bool writtenSomething = false; //we need to know the size of each dimension. int c = ar.Rank; List<int> lengths = new List<int>(c); bool firstItem = true; do { lengths.Add(ar.GetLength(--c)); } while (c != 0); //c is now zero. Might as well reuse it! foreach (object item in ar) { if (firstItem) { firstItem = false; } else { array.WriteByte((byte)ASCIIBytes.Comma); } //to work out how many [ characters we need we need to work where we are compared to the dimensions. //Say we are at position 24 in a 3 * 4 * 5 array. //We're at the end of a row as 24 % 3 == 0 so write one [ for that. //We're at the end of a square as 24 % (3 * 4) == 24 % (12) == 0 so write one [ for that. //We're not at the end of a cube as 24 % (3 * 4 * 5) == 24 % (30) != 0, so we're finished for that pass. int curlength = 1; foreach (int lengthTest in lengths) { if (c%(curlength *= lengthTest) == 0) { array.WriteByte((byte)ASCIIBytes.BraceCurlyLeft); } else { break; } } //Write whatever the element is. writtenSomething |= WriteItemText(TypeInfo, item, array, forExtendedQuery, options); ++c; //up our counter for knowing when to write [ and ] //same logic as above for writing [ this time writing ] curlength = 1; foreach (int lengthTest in lengths) { if (c%(curlength *= lengthTest) == 0) { array.WriteByte((byte)ASCIIBytes.BraceCurlyRight); } else { break; } } } return writtenSomething; }
internal static byte[] ToTimeStamp(NpgsqlNativeTypeInfo typeInfo, object nativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (nativeData is DateTime) { return(BasicNativeToBackendTypeConverter.ToDateTime(typeInfo, nativeData, forExtendedQuery, options, arrayElement)); } else { return(BackendEncoding.UTF8Encoding.GetBytes(nativeData.ToString())); } }
/// <summary> /// Convert to a postgresql bit. /// </summary> internal static byte[] ToBit(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (NativeData is bool) { return(((bool)NativeData) ? ASCIIByteArrays.AsciiDigit_1 : ASCIIByteArrays.AsciiDigit_0); } // It may seem more sensible to just convert an integer to a BitString here and pass it on. // However behaviour varies in terms of how this is interpretted if being passed to a bitstring // value smaller than the int. // Prior to Postgres 8.0, the behaviour would be the same either way. E.g. if 10 were passed to // a bit(1) then the bits (1010) would be extracted from the left, so resulting in the bitstring B'1'. // From 8.0 onwards though, if we cast 10 straight to a bit(1) then the right-most bit is taken, // resulting in B'0'. If we cast it to the "natural" bitstring for it's size first (which is what would // happen if we did that work here) then it would become B'1010' which would then be cast to bit(1) by // taking the left-most bit resulting in B'1' (the behaviour one would expect from Postgres 7.x). // // Since we don't know what implicit casts (say by inserting into a table with a bitstring field of // set size) may happen, we don't know how to ensure expected behaviour. While passing a bitstring // literal would work as expected with Postgres before 8.0, it can fail with 8.0 and later. else if (NativeData is int) { return(BackendEncoding.UTF8Encoding.GetBytes(NativeData.ToString())); } else { return(BackendEncoding.UTF8Encoding.GetBytes(((BitString)NativeData).ToString("E"))); } }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, StringBuilder sb, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { // As this prcedure handles both prepared and plain query representations, in order to not keep if's inside the loops // we simply set a placeholder here for both openElement ( '{' or '[' ) and closeElement ( '}', or ']' ) Char openElement = forExtendedQuery ? '{' : '['; Char closeElement = forExtendedQuery ? '}' : ']'; bool writtenSomething = false; //sb.Append('['); sb.Append(openElement); //write each item with a comma between them. foreach (object item in col) { writtenSomething |= WriteItem(TypeInfo, item, sb, forExtendedQuery, options); sb.Append(','); } if (writtenSomething) { //last comma was one too many. Replace it with the final } //sb[sb.Length - 1] = ']'; sb[sb.Length - 1] = closeElement; } return writtenSomething; }
internal static byte[] ToTimeTZ(NpgsqlNativeTypeInfo typeInfo, object nativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (nativeData is DateTime) { return(BasicNativeToBackendTypeConverter.ToTime(typeInfo, nativeData, forExtendedQuery, options, arrayElement)); } NpgsqlTimeTZ time; if (nativeData is TimeSpan) { time = (NpgsqlTimeTZ)(TimeSpan)nativeData; } else { time = (NpgsqlTimeTZ)nativeData; } return(BackendEncoding.UTF8Encoding.GetBytes(time.ToString())); }
/// <summary> /// Convert to a postgresql timestamp. /// </summary> internal static byte[] ToDateTime(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (!(NativeData is DateTime)) { return(ExtendedNativeToBackendTypeConverter.ToTimeStamp(TypeInfo, NativeData, forExtendedQuery, options, arrayElement)); } if (DateTime.MaxValue.Equals(NativeData)) { return(ASCIIByteArrays.INFINITY); } if (DateTime.MinValue.Equals(NativeData)) { return(ASCIIByteArrays.NEG_INFINITY); } return(BackendEncoding.UTF8Encoding.GetBytes((((DateTime)NativeData).ToString("yyyy-MM-dd HH:mm:ss.ffffff", DateTimeFormatInfo.InvariantInfo)))); }
static NativeToBackendTypeConverterOptions() { _default = new NativeToBackendTypeConverterOptions(true, false, true, false, null); }
/// <summary> /// Convert to a postgresql time. /// </summary> internal static byte[] ToTime(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (!(NativeData is DateTime)) { return(ExtendedNativeToBackendTypeConverter.ToTime(TypeInfo, NativeData, forExtendedQuery, options, arrayElement)); } else { return(BackendEncoding.UTF8Encoding.GetBytes(((DateTime)NativeData).ToString("HH:mm:ss.ffffff", DateTimeFormatInfo.InvariantInfo))); } }
internal static byte[] ToBasicType <T>(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { // This double cast is needed in order to get the enum type handled correctly (IConvertible) // and the decimal separator always as "." regardless of culture (IFormattable) return(BackendEncoding.UTF8Encoding.GetBytes((((IFormattable)((IConvertible)NativeData).ToType(typeof(T), null)).ToString(null, CultureInfo.InvariantCulture.NumberFormat)))); }
/// <summary> /// Convert to a postgres double with maximum precision. /// </summary> internal static byte[] SingleDoubleToFloat4Float8Text(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { //Formats accepted vary according to locale, but it always accepts a plain number (no currency or //grouping symbols) passed as a string (with the appropriate cast appended, as UseCast will cause //to happen. return(BackendEncoding.UTF8Encoding.GetBytes(((IFormattable)NativeData).ToString("R", CultureInfo.InvariantCulture.NumberFormat))); }
/// <summary> /// Constructor. /// </summary> /// <param name="ConnectionString">Connection string.</param> /// <param name="Pooled">Pooled</param> /// <param name="Shared">Controls whether the connector can be shared.</param> public NpgsqlConnector(NpgsqlConnectionStringBuilder ConnectionString, bool Pooled, bool Shared) { this.settings = ConnectionString; _connection_state = ConnectionState.Closed; _pooled = Pooled; _shared = Shared; _isInitialized = false; _state = NpgsqlClosedState.Instance; _mediator = new NpgsqlMediator(); _NativeToBackendTypeConverterOptions = NativeToBackendTypeConverterOptions.Default.Clone(new NpgsqlBackendTypeMapping()); _planIndex = 0; _portalIndex = 0; _notificationThreadStopCount = 1; }
/// <summary> /// Convert a System.Double to a postgres float8. /// </summary> internal static byte[] DoubleToFloat8Binary(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, NativeToBackendTypeConverterOptions options) { return(PGUtil.HostNetworkByteOrderSwap(BitConverter.GetBytes(Convert.ToDouble(NativeData)))); }
private bool WriteArrayText(NpgsqlNativeTypeInfo TypeInfo, Array ar, MemoryStream array, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { bool writtenSomething = false; //we need to know the size of each dimension. int c = ar.Rank; List <int> lengths = new List <int>(c); bool firstItem = true; do { lengths.Add(ar.GetLength(--c)); }while (c != 0); //c is now zero. Might as well reuse it! foreach (object item in ar) { if (firstItem) { firstItem = false; } else { array.WriteByte((byte)ASCIIBytes.Comma); } //to work out how many [ characters we need we need to work where we are compared to the dimensions. //Say we are at position 24 in a 3 * 4 * 5 array. //We're at the end of a row as 24 % 3 == 0 so write one [ for that. //We're at the end of a square as 24 % (3 * 4) == 24 % (12) == 0 so write one [ for that. //We're not at the end of a cube as 24 % (3 * 4 * 5) == 24 % (30) != 0, so we're finished for that pass. int curlength = 1; foreach (int lengthTest in lengths) { if (c % (curlength *= lengthTest) == 0) { array.WriteByte((byte)ASCIIBytes.BraceCurlyLeft); } else { break; } } //Write whatever the element is. writtenSomething |= WriteItemText(TypeInfo, item, array, forExtendedQuery, options); ++c; //up our counter for knowing when to write [ and ] //same logic as above for writing [ this time writing ] curlength = 1; foreach (int lengthTest in lengths) { if (c % (curlength *= lengthTest) == 0) { array.WriteByte((byte)ASCIIBytes.BraceCurlyRight); } else { break; } } } return(writtenSomething); }
/// <summary> /// Point. /// </summary> internal static byte[] ToPoint(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (NativeData is NpgsqlPoint) { NpgsqlPoint P = (NpgsqlPoint)NativeData; return(BackendEncoding.UTF8Encoding.GetBytes(String.Format(CultureInfo.InvariantCulture, "({0},{1})", P.X, P.Y))); } else { throw new InvalidCastException("Unable to cast data to NpgsqlPoint type"); } }
/// <summary> /// Append all array data to the binary stream. /// </summary> private void WriteBinaryArrayData(NpgsqlNativeTypeInfo TypeInfo, Array nativeData, NativeToBackendTypeConverterOptions options, MemoryStream dst, int dimensionOffset, int[] dimensionOffsets) { int dimensionLength = nativeData.GetLength(dimensionOffset); int dimensionLBound = nativeData.GetLowerBound(dimensionOffset); if (dimensionOffset < nativeData.Rank - 1) { // Drill down recursively until we hit a single dimension array. for (int i = dimensionLBound; i < dimensionLBound + dimensionLength; i++) { dimensionOffsets[dimensionOffset] = i; WriteBinaryArrayData(TypeInfo, nativeData, options, dst, dimensionOffset + 1, dimensionOffsets); } } else { // Write the individual array elements to the output stream. for (int i = dimensionLBound; i < dimensionLBound + dimensionLength; i++) { object elementNative; dimensionOffsets[dimensionOffset] = i; elementNative = nativeData.GetValue(dimensionOffsets); if (elementNative == null || elementNative == DBNull.Value) { // Write length identifier -1 indicating NULL value. PGUtil.WriteInt32(dst, -1); } else { byte[] elementBinary; elementBinary = (byte[])_elementConverter.ConvertToBackend(elementNative, true, options); // Write lenght identifier. PGUtil.WriteInt32(dst, elementBinary.Length); // Write element data. dst.Write(elementBinary, 0, elementBinary.Length); } } } }
/// <summary> /// Box. /// </summary> internal static byte[] ToBox(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { /*if (NativeData.GetType() == typeof(Rectangle)) { * Rectangle R = (Rectangle)NativeData; * return String.Format(CultureInfo.InvariantCulture, "({0},{1}),({2},{3})", R.Left, R.Top, R.Left + R.Width, R.Top + R.Height); * } else if (NativeData.GetType() == typeof(RectangleF)) { * RectangleF R = (RectangleF)NativeData; * return String.Format(CultureInfo.InvariantCulture, "({0},{1}),({2},{3})", R.Left, R.Top, R.Left + R.Width, R.Top + R.Height);*/ if (NativeData is NpgsqlBox) { NpgsqlBox box = (NpgsqlBox)NativeData; return (BackendEncoding.UTF8Encoding.GetBytes(String.Format(CultureInfo.InvariantCulture, "({0},{1}),({2},{3})", box.LowerLeft.X, box.LowerLeft.Y, box.UpperRight.X, box.UpperRight.Y))); } else { throw new InvalidCastException("Unable to cast data to Rectangle type"); } }
/// <summary> /// Serialise the enumeration or array. /// </summary> public byte[] ArrayToArrayText(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { MemoryStream array = new MemoryStream(); if (!forExtendedQuery) { if (!options.UseConformantStrings && options.Supports_E_StringPrefix) { array.WriteByte((byte)ASCIIBytes.E); } array.WriteByte((byte)ASCIIBytes.SingleQuote); } if (!WriteItemText(TypeInfo, NativeData, array, forExtendedQuery, options)) { array.Write(ASCIIArrayByteArrays.EmptyArray, 0, ASCIIArrayByteArrays.EmptyArray.Length); } if (!forExtendedQuery) { array.WriteByte((byte)ASCIIBytes.SingleQuote); } return(array.ToArray()); }
/// <summary> /// LSeg. /// </summary> internal static byte[] ToLSeg(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { NpgsqlLSeg S = (NpgsqlLSeg)NativeData; return(BackendEncoding.UTF8Encoding.GetBytes(String.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", S.Start.X, S.Start.Y, S.End.X, S.End.Y))); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, StringBuilder sb, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { // As this prcedure handles both prepared and plain query representations, in order to not keep if's inside the loops // we simply set a placeholder here for both openElement ( '{' or '[' ) and closeElement ( '}', or ']' ) Char openElement = forExtendedQuery ? '{' : '['; Char closeElement = forExtendedQuery ? '}' : ']'; bool writtenSomething = false; //sb.Append('['); sb.Append(openElement); //write each item with a comma between them. foreach (object item in col) { writtenSomething |= WriteItem(TypeInfo, item, sb, forExtendedQuery, options); sb.Append(','); } if (writtenSomething) { //last comma was one too many. Replace it with the final } //sb[sb.Length - 1] = ']'; sb[sb.Length - 1] = closeElement; } return(writtenSomething); }
/// <summary> /// Polygon. /// </summary> internal static byte[] ToPolygon(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { StringBuilder B = new StringBuilder(); foreach (NpgsqlPoint P in ((NpgsqlPolygon)NativeData)) { B.AppendFormat(CultureInfo.InvariantCulture, "{0}({1},{2})", (B.Length > 0 ? "," : ""), P.X, P.Y); } return(BackendEncoding.UTF8Encoding.GetBytes(String.Format("({0})", B))); }
private bool WriteItem(NpgsqlNativeTypeInfo TypeInfo, object item, StringBuilder sb, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { //item could be: //an Ienumerable - in which case we call WriteEnumeration //an element - in which case we call the NpgsqlNativeTypeInfo for that type to serialise it. //an array - in which case we call WriteArray, // Even an string being an IEnumerable, it shouldn't be processed. It will be processed on the last else. // See http://pgfoundry.org/tracker/?func=detail&atid=592&aid=1010514&group_id=1000140 for more info. if (item == null || NpgsqlTypesHelper.DefinedType(item)) { sb.Append(_elementConverter.ConvertToBackend(item, forExtendedQuery, options)); return(true); } else if (item is Array) { return(WriteArray(TypeInfo, item as Array, sb, forExtendedQuery, options)); } else if (item is IEnumerable) { return(WriteEnumeration(TypeInfo, item as IEnumerable, sb, forExtendedQuery, options)); } else {//This shouldn't really be reachable. sb.Append(_elementConverter.ConvertToBackend(item, forExtendedQuery, options)); return(true); } }
/// <summary> /// Circle. /// </summary> internal static byte[] ToCircle(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { NpgsqlCircle C = (NpgsqlCircle)NativeData; return(BackendEncoding.UTF8Encoding.GetBytes(String.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", C.Center.X, C.Center.Y, C.Radius))); }
/// <summary> /// Convert a System.Array to PG binary format. /// Write the array header and prepare to write array data to the stream. /// </summary> public byte[] ArrayToArrayBinary(NpgsqlNativeTypeInfo TypeInfo, object oNativeData, NativeToBackendTypeConverterOptions options) { Array NativeData = (Array)oNativeData; MemoryStream dst = new MemoryStream(); // Write the number of dimensions in the array. dst.WriteInt32(NativeData.Rank); // Placeholder for null bitmap flag, which isn't used? dst.WriteInt32(0); // Write the OID of the elements of the array. dst.WriteInt32(options.OidToNameMapping[_elementConverter.Name].OID); // White dimension descriptors. for (int i = 0 ; i < NativeData.Rank ; i++) { // Number of elements in the dimension. dst.WriteInt32(NativeData.GetLength(i)); // Lower bounds of the dimension, 1-based for SQL. dst.WriteInt32(NativeData.GetLowerBound(i) + 1); } int[] dimensionOffsets = new int[NativeData.Rank]; // Write all array data. WriteBinaryArrayData(TypeInfo, NativeData, options, dst, 0, dimensionOffsets); return dst.ToArray(); }
/// <summary> /// Convert to a postgres inet. /// </summary> internal static byte[] ToIPAddress(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { if (NativeData is NpgsqlInet) { return(BackendEncoding.UTF8Encoding.GetBytes(((NpgsqlInet)NativeData).ToString())); } return(BackendEncoding.UTF8Encoding.GetBytes(NativeData.ToString())); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, MemoryStream array, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { bool writtenSomething = false; bool firstItem = true; //write each item with a comma between them. foreach (object item in col) { if (firstItem) { array.WriteByte((byte)ASCIIBytes.BraceCurlyLeft); firstItem = false; } else { array.WriteByte((byte)ASCIIBytes.Comma); } writtenSomething |= WriteItemText(TypeInfo, item, array, forExtendedQuery, options); } if (writtenSomething) { array.WriteByte((byte)ASCIIBytes.BraceCurlyRight); } return writtenSomething; }
/// <summary> /// Convert to a postgres interval /// </summary> internal static byte[] ToInterval(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { return (BackendEncoding.UTF8Encoding.GetBytes(((NativeData is TimeSpan) ? ((NpgsqlInterval)(TimeSpan)NativeData).ToString() : ((NpgsqlInterval)NativeData).ToString()))); }
private bool WriteItemText(NpgsqlNativeTypeInfo TypeInfo, object item, MemoryStream array, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { //item could be: //an Ienumerable - in which case we call WriteEnumeration //an element - in which case we call the NpgsqlNativeTypeInfo for that type to serialise it. //an array - in which case we call WriteArray, // Even an string being an IEnumerable, it shouldn't be processed. It will be processed on the last else. // See http://pgfoundry.org/tracker/?func=detail&atid=592&aid=1010514&group_id=1000140 for more info. if(item == null || (NpgsqlTypesHelper.DefinedType(item) && !(item is Array && TypeInfo.NpgsqlDbType == (NpgsqlDbType.SingleChar | NpgsqlDbType.Array)))) { byte[] element; element = _elementConverter.ConvertToBackend(item, forExtendedQuery, options, true); array.Write(element, 0, element.Length); return true; } else if (item is Array) { return WriteArrayText(TypeInfo, item as Array, array, forExtendedQuery, options); } else if (item is IEnumerable) { return WriteEnumeration(TypeInfo, item as IEnumerable, array, forExtendedQuery, options); } else {//This shouldn't really be reachable. byte[] element; element = _elementConverter.ConvertToBackend(item, forExtendedQuery, options, true); array.Write(element, 0, element.Length); return true; } }
/// <summary> /// Serialise the enumeration or array. /// </summary> public string FromArray(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options) { if (forExtendedQuery) { StringBuilder sb = new StringBuilder(""); if (WriteItem(TypeInfo, NativeData, sb, forExtendedQuery, options)) { return sb.ToString(); } else { return "{}"; } } else { //just prepend "array" and then pass to WriteItem. StringBuilder sb = new StringBuilder("array"); if (WriteItem(TypeInfo, NativeData, sb, forExtendedQuery, options)) { return sb.ToString(); } else { return "'{}'"; } } }