X Tutup
// NpgsqlTypes.NpgsqlTypeInfoNative.cs // // Author: // Francisco Jr. (fxjrlists@yahoo.com.br) // // Copyright (C) 2002 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose, without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph and the following two paragraphs appear in all copies. // // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.Net; using System.Net.NetworkInformation; using System.Reflection; using System.Resources; using System.Text; using System.IO; using Npgsql; namespace NpgsqlTypes { /// /// Delegate called to convert the given native data to its backand representation. /// internal delegate byte[] ConvertNativeToBackendTextHandler(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, Boolean forExtendedQuery, NativeToBackendTypeConverterOptions options, bool arrayElement); internal delegate byte[] ConvertNativeToBackendBinaryHandler(NpgsqlNativeTypeInfo TypeInfo, Object NativeData, NativeToBackendTypeConverterOptions options); internal delegate object ConvertProviderTypeToFrameworkTypeHander(object value); internal delegate object ConvertFrameworkTypeToProviderTypeHander(object value); /// /// Represents a backend data type. /// This class can be called upon to convert a native object to its backend field representation, /// internal class NpgsqlNativeTypeInfo { private static readonly NumberFormatInfo ni; private readonly ConvertNativeToBackendTextHandler _ConvertNativeToBackendText; private readonly ConvertNativeToBackendBinaryHandler _ConvertNativeToBackendBinary; private readonly String _Name; private readonly string _CastName; private readonly NpgsqlDbType _NpgsqlDbType; private readonly DbType _DbType; private readonly Boolean _Quote; private readonly Boolean _UseSize; private Boolean _IsArray = false; /// /// Returns an NpgsqlNativeTypeInfo for an array where the elements are of the type /// described by the NpgsqlNativeTypeInfo supplied. /// 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; } static NpgsqlNativeTypeInfo() { ni = (NumberFormatInfo) CultureInfo.InvariantCulture.NumberFormat.Clone(); ni.NumberDecimalDigits = 15; } internal static NumberFormatInfo NumberFormat { get { return ni; } } /// /// Construct a new NpgsqlTypeInfo with the given attributes and conversion handlers. /// /// Type name provided by the backend server. /// DbType /// Quote /// NpgsqlDbType /// Data conversion handler for text backend encoding. /// Data conversion handler for binary backend encoding (for extended queries). public NpgsqlNativeTypeInfo(String Name, NpgsqlDbType NpgsqlDbType, DbType DbType, Boolean Quote, ConvertNativeToBackendTextHandler ConvertNativeToBackendText = null, ConvertNativeToBackendBinaryHandler ConvertNativeToBackendBinary = null) { _Name = Name; _CastName = Name.StartsWith("_") ? Name.Substring(1) + "[]" : Name; _NpgsqlDbType = NpgsqlDbType; _DbType = DbType; _Quote = Quote; _ConvertNativeToBackendText = ConvertNativeToBackendText; _ConvertNativeToBackendBinary = ConvertNativeToBackendBinary; // The only parameters types which use length currently supported are char and varchar. Check for them. if ((NpgsqlDbType == NpgsqlDbType.Char) || (NpgsqlDbType == NpgsqlDbType.Varchar)) { _UseSize = true; } else { _UseSize = false; } } /// /// Type name provided by the backend server. /// public String Name { get { return _Name; } } public string CastName { get { return _CastName; } } public bool IsArray { get { return _IsArray; } } /// /// NpgsqlDbType. /// public NpgsqlDbType NpgsqlDbType { get { return _NpgsqlDbType; } } /// /// DbType. /// public DbType DbType { get { return _DbType; } } /// /// Apply quoting. /// public Boolean Quote { get { return _Quote; } } /// /// Use parameter size information. /// public Boolean UseSize { get { return _UseSize; } } /// /// 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 /// /// Native .NET object to be converted. /// Specifies that the value should be formatted for the extended query syntax. /// Options to guide serialization. If null, a default options set is used. /// Specifies that the value should be formatted as an extended query array element. 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; } } 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; } } private static byte[] QuoteASCIIString(byte[] src, bool forExtendedQuery, bool arrayElement) { byte[] ret = null; if (arrayElement) { // Array elements always require double-quotes ret = new byte[src.Length + 2]; ret[0] = (byte)ASCIIBytes.DoubleQuote; src.CopyTo(ret, 1); ret[ret.Length - 1] = (byte)ASCIIBytes.DoubleQuote; } else { if (forExtendedQuery) { // Non-array-element values sent via Bind are not quoted ret = src; } else { // Non-array-element values sent via simple query require single-quotes ret = new byte[src.Length + 2]; ret[0] = (byte)ASCIIBytes.SingleQuote; src.CopyTo(ret, 1); ret[ret.Length - 1] = (byte)ASCIIBytes.SingleQuote; } } return ret; } /// /// Reports whether a native to backend binary encoder is available for this type. /// public bool SupportsBinaryBackendData { get { return (! NpgsqlTypesHelper.SuppressBinaryBackendEncoding && _ConvertNativeToBackendBinary != null); } } } }
X Tutup