/// <summary> /// Returns an NpgsqlNativeTypeInfo for an array where the elements are of the type /// described by the NpgsqlNativeTypeInfo supplied. /// </summary> public static NpgsqlNativeTypeInfo ArrayOf(NpgsqlNativeTypeInfo elementType) { if (elementType._IsArray) //we've an array of arrays. It's the inner most elements whose type we care about, so the type we have is fine. { return elementType; } NpgsqlNativeTypeInfo copy = null; ArrayNativeToBackendTypeConverter converter = new ArrayNativeToBackendTypeConverter(elementType); if (elementType._ConvertNativeToBackendBinary != null) { copy = new NpgsqlNativeTypeInfo("_" + elementType.Name, NpgsqlDbType.Array | elementType.NpgsqlDbType, elementType.DbType, false, converter.ArrayToArrayText, converter.ArrayToArrayBinary); } else { copy = new NpgsqlNativeTypeInfo("_" + elementType.Name, NpgsqlDbType.Array | elementType.NpgsqlDbType, elementType.DbType, false, converter.ArrayToArrayText); } copy._IsArray = true; return copy; }
/// <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> /// Serialise the enumeration or array. /// </summary> public string FromArray(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean ForExtendedQuery) { if (ForExtendedQuery) { StringBuilder sb = new StringBuilder("{"); //return sb.ToString(); WriteItem(TypeInfo, NativeData, sb, ForExtendedQuery); sb.Append("}"); return sb.ToString(); } else { //just prepend "array" and then pass to WriteItem. StringBuilder sb = new StringBuilder("array"); if (WriteItem(TypeInfo, NativeData, sb, ForExtendedQuery)) { return sb.ToString(); } else { return "'{}'"; } } }
/// <summary> /// Serialise the enumeration or array. /// </summary> public string FromArray(NpgsqlNativeTypeInfo TypeInfo, object NativeData) { //just prepend "array" and then pass to WriteItem. StringBuilder sb = new StringBuilder("array"); if (WriteItem(TypeInfo, NativeData, sb)) { return sb.ToString(); } else { return "'{}'"; } }
/// <summary> /// Serialise the enumeration or array. /// </summary> public string FromArray(NpgsqlNativeTypeInfo TypeInfo, object NativeData) { //just prepend "array" and then pass to WriteItem. StringBuilder sb = new StringBuilder("array"); if (WriteItem(TypeInfo, NativeData, sb)) { return(sb.ToString()); } else { return("'{}'"); } }
/// <summary> /// Box. /// </summary> internal static String ToBox(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean ForExtendedQuery) { if (NativeData is NpgsqlBox) { NpgsqlBox box = (NpgsqlBox)NativeData; return (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> /// 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)))); }
/// <summary> /// Convert to a postgresql timestamp. /// </summary> internal static String ToDateTime(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean ForExtendedQuery) { if (!(NativeData is DateTime)) { return(ExtendedNativeToBackendTypeConverter.ToTimeStamp(TypeInfo, NativeData, ForExtendedQuery)); } if (DateTime.MaxValue.Equals(NativeData)) { return("infinity"); } if (DateTime.MinValue.Equals(NativeData)) { return("-infinity"); } return(((DateTime)NativeData).ToString("yyyy-MM-dd HH:mm:ss.ffffff", DateTimeFormatInfo.InvariantInfo)); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, StringBuilder sb) { bool writtenSomething = false; sb.Append('['); //write each item with a comma between them. foreach (object item in col) { writtenSomething |= WriteItem(TypeInfo, item, sb); sb.Append(','); } if (writtenSomething) { //last comma was one too many. Replace it with the final } sb[sb.Length - 1] = ']'; } 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> /// Binary data. /// </summary> internal static String ToBinary(NpgsqlNativeTypeInfo TypeInfo, Object NativeData) { Byte[] byteArray = (Byte[])NativeData; int len = byteArray.Length; char[] res = new char[len * 5]; for (int i = 0, o = 0; i < len; ++i, o += 5) { byte item = byteArray[i]; res[o] = res[o + 1] = '\\'; res[o + 2] = (char)('0' + (7 & (item >> 6))); res[o + 3] = (char)('0' + (7 & (item >> 3))); res[o + 4] = (char)('0' + (7 & item)); } return(new String(res)); }
internal static string ToTimeTZ(NpgsqlNativeTypeInfo typeInfo, object nativeData, Boolean ForExtendedQuery) { if (nativeData is DateTime) { return(BasicNativeToBackendTypeConverter.ToTime(typeInfo, nativeData, ForExtendedQuery)); } NpgsqlTimeTZ time; if (nativeData is TimeSpan) { time = (NpgsqlTimeTZ)(TimeSpan)nativeData; } else { time = (NpgsqlTimeTZ)nativeData; } return(time.ToString()); }
/// <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 String ToBox(NpgsqlNativeTypeInfo TypeInfo, Object NativeData) { /*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(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> /// Add the given NpgsqlNativeTypeInfo to this mapping. /// </summary> public void AddType(NpgsqlNativeTypeInfo T) { if (NameIndex.ContainsKey(T.Name)) { throw new Exception("Type already mapped"); } NameIndex[T.Name] = T; NpgsqlDbTypeIndex[T.NpgsqlDbType] = T; DbTypeIndex[T.DbType] = T; if (!T.IsArray) { NpgsqlNativeTypeInfo arrayType = NpgsqlNativeTypeInfo.ArrayOf(T); NameIndex[arrayType.Name] = arrayType; NameIndex[arrayType.CastName] = arrayType; NpgsqlDbTypeIndex[arrayType.NpgsqlDbType] = arrayType; } }
/// <summary> /// Serialise the enumeration or array. /// </summary> public string FromArray(NpgsqlNativeTypeInfo TypeInfo, object NativeData, Boolean ForExtendedQuery) { if (ForExtendedQuery) { StringBuilder sb = new StringBuilder("{"); //return sb.ToString(); WriteItem(TypeInfo, NativeData, sb, ForExtendedQuery); sb.Append("}"); return(sb.ToString()); } else { //just prepend "array" and then pass to WriteItem. StringBuilder sb = new StringBuilder("array"); if (WriteItem(TypeInfo, NativeData, sb, ForExtendedQuery)) { return(sb.ToString()); } else { return("'{}'"); } } }
/// <summary> /// Open path. /// </summary> internal static byte[] ToPath(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { StringBuilder B = null; try { B = new StringBuilder(); foreach (NpgsqlPoint P in ((NpgsqlPath)NativeData)) { B.AppendFormat(CultureInfo.InvariantCulture, "{0}({1},{2})", (B.Length > 0 ? "," : ""), P.X, P.Y); } return(BackendEncoding.UTF8Encoding.GetBytes(String.Format("[{0}]", B))); } finally { B = null; } }
/// <summary> /// Open path. /// </summary> internal static String ToPath(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean ForExtendedQuery) { StringBuilder B = null; try { B = new StringBuilder(); foreach (NpgsqlPoint P in ((NpgsqlPath)NativeData)) { B.AppendFormat(CultureInfo.InvariantCulture, "{0}({1},{2})", (B.Length > 0 ? "," : ""), P.X, P.Y); } return(String.Format("[{0}]", B)); } finally { B = null; } }
/// <summary> /// Binary data. /// </summary> internal static String ToBinary(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean ForExtendedQuery) { Byte[] byteArray = (Byte[])NativeData; StringBuilder res = new StringBuilder(byteArray.Length * 5); foreach (byte b in byteArray) { if (b >= 0x20 && b < 0x7F && b != 0x27 && b != 0x5C) { res.Append((char)b); } else { res.Append("\\\\") .Append((char)('0' + (7 & (b >> 6)))) .Append((char)('0' + (7 & (b >> 3)))) .Append((char)('0' + (7 & b))); } } return(res.ToString()); }
/// <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"); } }
private bool WriteItem(NpgsqlNativeTypeInfo TypeInfo, object item, StringBuilder sb) { //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, if (item is IEnumerable) { return(WriteEnumeration(TypeInfo, item as IEnumerable, sb)); } else if (item is Array) { return(WriteArray(TypeInfo, item as Array, sb)); } else { sb.Append(_elementConverter.ConvertToBackend(item, false)); return(true); } }
/// <summary> /// Find a NpgsqlNativeTypeInfo in the default types map that can handle objects /// of the given System.Type. /// </summary> public static bool TryGetNativeTypeInfo(Type type, out NpgsqlNativeTypeInfo typeInfo) { if (NativeTypeMapping.TryGetValue(type, out typeInfo)) { return(true); } // At this point there is no direct mapping, so we see if we have an array or IEnumerable<T>. // Note that we checked for a direct mapping first, so if there is a direct mapping of a class // which implements IEnumerable<T> we will use that (currently this is only string, which // implements IEnumerable<char>. Type elementType = null; NpgsqlNativeTypeInfo elementTypeInfo = null; if (TestTypedEnumerator(type, out elementType) && TryGetNativeTypeInfo(elementType, out elementTypeInfo)) { typeInfo = NpgsqlNativeTypeInfo.ArrayOf(elementTypeInfo); return(true); } return(false); }
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)) { 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); } }
internal static byte[] DoubleToFloat8Text(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. if (!arrayElement) { var asDouble = (double)NativeData; if (double.IsNaN(asDouble)) { return(ASCIIByteArrays.NAN_QUOTED); } if (double.IsPositiveInfinity(asDouble)) { return(ASCIIByteArrays.INFINITY_QUOTED); } if (double.IsNegativeInfinity(asDouble)) { return(ASCIIByteArrays.NEG_INFINITY_QUOTED); } } return(BackendEncoding.UTF8Encoding.GetBytes(((IFormattable)NativeData).ToString("R", CultureInfo.InvariantCulture.NumberFormat))); }
private bool WriteItem(NpgsqlNativeTypeInfo TypeInfo, object item, StringBuilder sb) { //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, if (item is IEnumerable) { return WriteEnumeration(TypeInfo, item as IEnumerable, sb); } else if (item is Array) { return WriteArray(TypeInfo, item as Array, sb); } else { sb.Append(_elementConverter.ConvertToBackend(item, false)); return true; } }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, StringBuilder sb, Boolean ForExtendedQuery) { // 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); 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> /// Convert a Char to something that can be interpreted as a single-byte "char". /// </summary> internal static byte[] ToSingleCharText(NpgsqlNativeTypeInfo TypeInfo, Object oNativeData, bool forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { char c = GetSingleChar(oNativeData); if ((arrayElement || forExtendedQuery) && (c >= 128 || c == 0)) { throw new OverflowException("\"char\" type can only have values between 1 and 127 in array string literals or in extended queries with text encoding. Got " + (int)c); } if (arrayElement) { return(StringToTextText(TypeInfo, c.ToString(), forExtendedQuery, options, arrayElement)); } if (forExtendedQuery) { return(new byte[] { (byte)c }); } else { int i = c >= 128 ? c - 256 : c; return(BackendEncoding.UTF8Encoding.GetBytes(i.ToString())); } }
/// <summary> /// Binary data, escaped and quoted as required. /// </summary> internal static byte[] ByteArrayToByteaText(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, bool forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement) { StringEncodingInfo encodingInfo; // Using a four bit hash key derived from the options at hand, // find the correct string encoding info object. encodingInfo = stringEncodingInfoTable[ StringEncodingInfoHash( forExtendedQuery, options.UseConformantStrings, options.Supports_E_StringPrefix, arrayElement ) ]; if (!options.SupportsHexByteFormat) { return(ByteArrayToByteaTextEscaped((byte[])NativeData, encodingInfo)); } else { return(ByteArrayToByteaTextHexFormat((byte[])NativeData, encodingInfo)); } }
private bool WriteArray(NpgsqlNativeTypeInfo TypeInfo, Array ar, StringBuilder sb, Boolean ForExtendedQuery) { 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); ++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; }
/// <summary> /// Create an ArrayNativeToBackendTypeConverter with the element converter passed /// </summary> /// <param name="elementConverter">The <see cref="NpgsqlNativeTypeInfo"/> that would be used to serialise the element type.</param> public ArrayNativeToBackendTypeConverter(NpgsqlNativeTypeInfo elementConverter) { _elementConverter = elementConverter; }
private bool WriteArray(NpgsqlNativeTypeInfo TypeInfo, Array ar, StringBuilder sb, Boolean ForExtendedQuery) { 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); ++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); }
/// <summary> /// Circle. /// </summary> internal static String ToCircle(NpgsqlNativeTypeInfo TypeInfo, Object NativeData) { NpgsqlCircle C = (NpgsqlCircle)NativeData; return String.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", C.Center.X, C.Center.Y, C.Radius); }
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; }
private bool WriteItem(NpgsqlNativeTypeInfo TypeInfo, object item, StringBuilder sb, Boolean ForExtendedQuery) { //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)); return true; } else if (item is Array) { return WriteArray(TypeInfo, item as Array, sb, ForExtendedQuery); } else if (item is IEnumerable) { return WriteEnumeration(TypeInfo, item as IEnumerable, sb, ForExtendedQuery); } else {//This shouldn't really be reachable. sb.Append(_elementConverter.ConvertToBackend(item, ForExtendedQuery)); return true; } }
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); }
public bool TryGetValue(string name, out NpgsqlNativeTypeInfo typeInfo) { return NameIndex.TryGetValue(name, out typeInfo); }
/// <summary> /// Add the given NpgsqlNativeTypeInfo to this mapping. /// </summary> public void AddType(NpgsqlNativeTypeInfo T) { if (NameIndex.Contains(T.Name)) { throw new Exception("Type already mapped"); } NameIndex[T.Name] = T; NpgsqlDbTypeIndex[T.NpgsqlDbType] = T; DbTypeIndex[T.DbType] = T; }
/// <summary> /// Initializes a new instance of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> /// class with the parameter m_Name, the <see cref="System.Data.DbType">DbType</see>, the size, /// the source column m_Name, a <see cref="System.Data.ParameterDirection">ParameterDirection</see>, /// the precision of the parameter, the scale of the parameter, a /// <see cref="System.Data.DataRowVersion">DataRowVersion</see> to use, and the /// value of the parameter. /// </summary> /// <param m_Name="parameterName">The m_Name of the parameter to map.</param> /// <param m_Name="parameterType">One of the <see cref="System.Data.DbType">DbType</see> values.</param> /// <param m_Name="size">The length of the parameter.</param> /// <param m_Name="sourceColumn">The m_Name of the source column.</param> /// <param m_Name="direction">One of the <see cref="System.Data.ParameterDirection">ParameterDirection</see> values.</param> /// <param m_Name="isNullable"><b>true</b> if the value of the field can be null, otherwise <b>false</b>.</param> /// <param m_Name="precision">The total number of digits to the left and right of the decimal point to which /// <see cref="Npgsql.NpgsqlParameter.Value">Value</see> is resolved.</param> /// <param m_Name="scale">The total number of decimal places to which /// <see cref="Npgsql.NpgsqlParameter.Value">Value</see> is resolved.</param> /// <param m_Name="sourceVersion">One of the <see cref="System.Data.DataRowVersion">DataRowVersion</see> values.</param> /// <param m_Name="value">An <see cref="System.Object">Object</see> that is the value /// of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see>.</param> public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType, Int32 size, String sourceColumn, ParameterDirection direction, bool isNullable, byte precision, byte scale, DataRowVersion sourceVersion, object value) { this.ParameterName = parameterName; this.Size = size; this.SourceColumn = sourceColumn; this.Direction = direction; this.IsNullable = isNullable; this.Precision = precision; this.Scale = scale; this.SourceVersion = sourceVersion; this.Value = value; if (this.value == null) { this.value = DBNull.Value; type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); } else { NpgsqlDbType = parameterType; //allow the setter to catch exceptions if necessary. } }
/// <summary> /// Retrieve the NpgsqlNativeTypeInfo with the given DbType. /// </summary> public bool TryGetValue(DbType dbType, out NpgsqlNativeTypeInfo typeInfo) { return DbTypeIndex.TryGetValue(dbType, out typeInfo); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, StringBuilder sb) { bool writtenSomething = false; sb.Append('['); //write each item with a comma between them. foreach (object item in col) { writtenSomething |= WriteItem(TypeInfo, item, sb); sb.Append(','); } if (writtenSomething) { //last comma was one too many. Replace it with the final } sb[sb.Length - 1] = ']'; } return writtenSomething; }
/// <summary> /// Retrieve the NpgsqlNativeTypeInfo with the given DbType. /// </summary> public bool TryGetValue(DbType dbType, out NpgsqlNativeTypeInfo typeInfo) { return(DbTypeIndex.TryGetValue(dbType, out typeInfo)); }
/// <summary> /// Retrieve the NpgsqlNativeTypeInfo with the given Type. /// </summary> public bool TryGetValue(Type type, out NpgsqlNativeTypeInfo typeInfo) { return(TypeIndex.TryGetValue(type, out typeInfo)); }
/// <summary> /// Convert to a postgres inet. /// </summary> internal static String ToIPAddress(NpgsqlNativeTypeInfo TypeInfo, Object NativeData) { if (NativeData is NpgsqlInet) return ((NpgsqlInet)NativeData).ToString(); else return ((System.Net.IPAddress)NativeData).ToString(); }
/// <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(); }
private bool WriteEnumeration(NpgsqlNativeTypeInfo TypeInfo, IEnumerable col, StringBuilder sb, Boolean ForExtendedQuery) { // 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); 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; }
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> /// Initializes a new instance of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> /// class with the parameter name and a value of the new <b>NpgsqlParameter</b>. /// </summary> /// <param name="parameterName">The name of the parameter to map.</param> /// <param name="value">An <see cref="System.Object">Object</see> that is the value of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see>.</param> /// <remarks> /// <p>When you specify an <see cref="System.Object">Object</see> /// in the value parameter, the <see cref="System.Data.DbType">DbType</see> is /// inferred from the .NET Framework type of the <b>Object</b>.</p> /// <p>When using this constructor, you must be aware of a possible misuse of the constructor which takes a DbType parameter. /// This happens when calling this constructor passing an int 0 and the compiler thinks you are passing a value of DbType. /// Use <code> Convert.ToInt32(value) </code> for example to have compiler calling the correct constructor.</p> /// </remarks> public NpgsqlParameter(String parameterName, object value) { resman = new System.Resources.ResourceManager(this.GetType()); NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, parameterName, value); this.ParameterName = parameterName; this.value = value; if ((this.value == null) || (this.value == DBNull.Value) ) { // don't really know what to do - leave default and do further exploration // Default type for null values is String. this.value = DBNull.Value; type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); return; } else { type_info = NpgsqlTypesHelper.GetNativeTypeInfo(value.GetType()); if (type_info == null) { throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType())); } } }
/// <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); } } } }
/// <summary> /// Initializes a new instance of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> /// class with the parameter name, the <see cref="System.Data.DbType">DbType</see>, the size, /// the source column name, a <see cref="System.Data.ParameterDirection">ParameterDirection</see>, /// the precision of the parameter, the scale of the parameter, a /// <see cref="System.Data.DataRowVersion">DataRowVersion</see> to use, and the /// value of the parameter. /// </summary> /// <param name="parameterName">The name of the parameter to map.</param> /// <param name="parameterType">One of the <see cref="System.Data.DbType">DbType</see> values.</param> /// <param name="size">The length of the parameter.</param> /// <param name="sourceColumn">The name of the source column.</param> /// <param name="direction">One of the <see cref="System.Data.ParameterDirection">ParameterDirection</see> values.</param> /// <param name="isNullable"><b>true</b> if the value of the field can be null, otherwise <b>false</b>.</param> /// <param name="precision">The total number of digits to the left and right of the decimal point to which /// <see cref="Npgsql.NpgsqlParameter.Value">Value</see> is resolved.</param> /// <param name="scale">The total number of decimal places to which /// <see cref="Npgsql.NpgsqlParameter.Value">Value</see> is resolved.</param> /// <param name="sourceVersion">One of the <see cref="System.Data.DataRowVersion">DataRowVersion</see> values.</param> /// <param name="value">An <see cref="System.Object">Object</see> that is the value /// of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see>.</param> public NpgsqlParameter (String parameterName, NpgsqlDbType parameterType, Int32 size, String sourceColumn, ParameterDirection direction, bool isNullable, byte precision, byte scale, DataRowVersion sourceVersion, object value) { resman = new System.Resources.ResourceManager(this.GetType()); this.ParameterName = parameterName; this.Size = size; this.SourceColumn = sourceColumn; this.Direction = direction; this.IsNullable = isNullable; this.Precision = precision; this.Scale = scale; this.SourceVersion = sourceVersion; this.Value = value; if (this.value == null) { this.value = DBNull.Value; type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); } else { type_info = NpgsqlTypesHelper.GetNativeTypeInfo(parameterType); if (type_info == null) throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), parameterType)); } }
public static NpgsqlNativeTypeInfo GetNativeTypeInfo(Type Type) { NpgsqlNativeTypeInfo ret = null; return(TryGetNativeTypeInfo(Type, out ret) ? ret : null); }
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; } }
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; }
/// <summary> /// Initializes a new instance of the <see cref="Npgsql.NpgsqlParameter">NpgsqlParameter</see> /// class with the parameter name, the <see cref="System.Data.DbType">DbType</see>, the size, /// and the source column name. /// </summary> /// <param name="parameterName">The name of the parameter to map.</param> /// <param name="parameterType">One of the <see cref="System.Data.DbType">DbType</see> values.</param> /// <param name="size">The length of the parameter.</param> /// <param name="sourceColumn">The name of the source column.</param> public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType, Int32 size, String sourceColumn) { resman = new System.Resources.ResourceManager(this.GetType()); NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, parameterName, parameterType, size, source_column); this.ParameterName = parameterName; type_info = NpgsqlTypesHelper.GetNativeTypeInfo(parameterType); if (type_info == null) throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), parameterType)); this.size = size; source_column = sourceColumn; }
public bool TryGetValue(string name, out NpgsqlNativeTypeInfo typeInfo) { return(NameIndex.TryGetValue(name, out typeInfo)); }
private bool WriteArray(NpgsqlNativeTypeInfo TypeInfo, Array ar, StringBuilder sb) { 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) { //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('['); } else { break; } } //Write whatever the element is. writtenSomething |= WriteItem(TypeInfo, item, sb); ++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(']'); } else { break; } } //comma between each item. sb.Append(','); } if (writtenSomething) { //last comma was one too many. sb.Remove(sb.Length - 1, 1); } return writtenSomething; }
/// <summary> /// Retrieve the NpgsqlNativeTypeInfo with the given Type. /// </summary> public bool TryGetValue(Type type, out NpgsqlNativeTypeInfo typeInfo) { return TypeIndex.TryGetValue(type, out typeInfo); }
public override void ResetDbType() { //type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); type_info = null; this.Value = Value; }
/// <summary> /// Reset DBType. /// </summary> public override void ResetDbType() { //type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); type_info = null; backendTypeInfo = null; explicitUnknown = false; this.Value = Value; ClearBind(); }