Пример #1
0
        /// <summary>
        /// Attempt to map types by issuing a query against pg_type.
        /// This function takes a list of NpgsqlTypeInfo and attempts to resolve the OID field
        /// of each by querying pg_type.  If the mapping is found, the type info object is
        /// updated (OID) and added to the provided NpgsqlTypeMapping object.
        /// </summary>
        /// <param name="conn">NpgsqlConnector to send query through.</param>
        /// <param name="TypeMappings">Mapping object to add types too.</param>
        /// <param name="TypeInfoList">List of types that need to have OID's mapped.</param>
        public static void LoadTypesMappings(NpgsqlConnector conn, NpgsqlBackendTypeMapping TypeMappings, IList TypeInfoList)
        {
            StringBuilder InList    = new StringBuilder();
            Hashtable     NameIndex = new Hashtable();

            // Build a clause for the SELECT statement.
            // Build a name->typeinfo mapping so we can match the results of the query
            /// with the list of type objects efficiently.
            foreach (NpgsqlBackendTypeInfo TypeInfo in TypeInfoList)
            {
                NameIndex.Add(TypeInfo.Name, TypeInfo);
                InList.AppendFormat("{0}'{1}'", ((InList.Length > 0) ? ", " : ""), TypeInfo.Name);
            }

            if (InList.Length == 0)
            {
                return;
            }

            NpgsqlCommand    command = new NpgsqlCommand("SELECT oid, typname FROM pg_type WHERE typname IN (" + InList.ToString() + ")", conn);
            NpgsqlDataReader dr      = command.ExecuteReader();

            while (dr.Read())
            {
                NpgsqlBackendTypeInfo TypeInfo = (NpgsqlBackendTypeInfo)NameIndex[dr[1].ToString()];

                TypeInfo._OID = Convert.ToInt32(dr[0]);

                TypeMappings.AddType(TypeInfo);
            }
        }
 private NativeToBackendTypeConverterOptions(bool Immutable, bool useConformantStrings, bool supports_E_StringPrefix, bool supportsHexByteFormat, NpgsqlBackendTypeMapping oidToNameMapping)
 {
     this.IsImmutable = Immutable;
     this._UseConformantStrings = useConformantStrings;
     this._Supports_E_StringPrefix = supports_E_StringPrefix;
     this._SupportsHexByteFormat = supportsHexByteFormat;
     this._oidToNameMapping = oidToNameMapping;
 }
Пример #3
0
 private NativeToBackendTypeConverterOptions(bool Immutable, bool useConformantStrings, bool supports_E_StringPrefix, bool supportsHexByteFormat, NpgsqlBackendTypeMapping oidToNameMapping)
 {
     this.IsImmutable              = Immutable;
     this._UseConformantStrings    = useConformantStrings;
     this._Supports_E_StringPrefix = supports_E_StringPrefix;
     this._SupportsHexByteFormat   = supportsHexByteFormat;
     this._oidToNameMapping        = oidToNameMapping;
 }
Пример #4
0
        ///<summary>
        /// This method creates (or retrieves from cache) a mapping between type and OID
        /// of all natively supported postgresql data types.
        /// This is needed as from one version to another, this mapping can be changed and
        /// so we avoid hardcoding them.
        /// </summary>
        /// <returns>NpgsqlTypeMapping containing all known data types.  The mapping must be
        /// cloned before it is modified because it is cached; changes made by one connection may
        /// effect another connection.
        /// </returns>
        public static NpgsqlBackendTypeMapping CreateAndLoadInitialTypesMapping(NpgsqlConnector conn)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "LoadTypesMapping");

            MappingKey key = new MappingKey(conn);
            // Check the cache for an initial types map.
            NpgsqlBackendTypeMapping oidToNameMapping = null;

            if (BackendTypeMappingCache.TryGetValue(key, out oidToNameMapping))
            {
                return(oidToNameMapping);
            }

            // Not in cache, create a new one.
            oidToNameMapping = new NpgsqlBackendTypeMapping();

            // Create a list of all natively supported postgresql data types.

            // Attempt to map each type info in the list to an OID on the backend and
            // add each mapped type to the new type mapping object.
            LoadTypesMappings(conn, oidToNameMapping, TypeInfoList(conn.UseExtendedTypes, conn.CompatVersion));

            //We hold the lock for the least time possible on the least scope possible.
            //We must lock on BackendTypeMappingCache because it will be updated by this operation,
            //and we must not just add to it, but also check that another thread hasn't updated it
            //in the meantime. Strictly just doing :
            //return BackendTypeMappingCache[key] = oidToNameMapping;
            //as the only call within the locked section should be safe and correct, but we'll assume
            //there's some subtle problem with temporarily having two copies of the same mapping and
            //ensure only one is called.
            //It is of course wasteful that multiple threads could be creating mappings when only one
            //will be used, but we aim for better overall concurrency at the risk of causing some
            //threads the extra work.
            NpgsqlBackendTypeMapping mappingCheck = null;

            //First check without acquiring the lock; don't lock if we don't have to.
            if (BackendTypeMappingCache.TryGetValue(key, out mappingCheck))//Another thread built the mapping in the meantime.
            {
                return(mappingCheck);
            }
            lock (BackendTypeMappingCache)
            {
                //Final check. We have the lock now so if this fails it'll continue to fail.
                if (BackendTypeMappingCache.TryGetValue(key, out mappingCheck))//Another thread built the mapping in the meantime.
                {
                    return(mappingCheck);
                }
                // Add this mapping to the per-server-version cache so we don't have to
                // do these expensive queries on every connection startup.
                BackendTypeMappingCache.Add(key, oidToNameMapping);
            }
            return(oidToNameMapping);
        }
        public void ReadFromStream(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
        {
            switch (protocol_version)
            {
            case ProtocolVersion.Version2 :
                ReadFromStream_Ver_2(input_stream, encoding, type_mapping);
                break;

            case ProtocolVersion.Version3 :
                ReadFromStream_Ver_3(input_stream, encoding, type_mapping);
                break;

            }
        }
Пример #6
0
        /// <summary>
        /// Attempt to map types by issuing a query against pg_type.
        /// This function takes a list of NpgsqlTypeInfo and attempts to resolve the OID field
        /// of each by querying pg_type.  If the mapping is found, the type info object is
        /// updated (OID) and added to the provided NpgsqlTypeMapping object.
        /// </summary>
        /// <param name="conn">NpgsqlConnector to send query through.</param>
        /// <param name="TypeMappings">Mapping object to add types too.</param>
        /// <param name="TypeInfoList">List of types that need to have OID's mapped.</param>
        public static void LoadTypesMappings(NpgsqlConnector conn, NpgsqlBackendTypeMapping TypeMappings,
                                             IEnumerable <NpgsqlBackendTypeInfo> TypeInfoList)
        {
            StringBuilder InList = new StringBuilder();
            Dictionary <string, NpgsqlBackendTypeInfo> NameIndex = new Dictionary <string, NpgsqlBackendTypeInfo>();

            // Build a clause for the SELECT statement.
            // Build a name->typeinfo mapping so we can match the results of the query
            // with the list of type objects efficiently.
            foreach (NpgsqlBackendTypeInfo TypeInfo in TypeInfoList)
            {
                NameIndex.Add(TypeInfo.Name, TypeInfo);
                InList.AppendFormat("{0}'{1}'", ((InList.Length > 0) ? ", " : ""), TypeInfo.Name);

                //do the same for the equivalent array type.

                NameIndex.Add("_" + TypeInfo.Name, ArrayTypeInfo(TypeInfo));

                InList.Append(", '_").Append(TypeInfo.Name).Append('\'');
            }

            if (InList.Length == 0)
            {
                return;
            }

            using (
                NpgsqlCommand command =
                    new NpgsqlCommand(string.Format("SELECT typname, oid FROM pg_type WHERE typname IN ({0})", InList), conn))
            {
                using (NpgsqlDataReader dr = command.GetReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
                {
                    while (dr.Read())
                    {
                        NpgsqlBackendTypeInfo TypeInfo = NameIndex[dr[0].ToString()];

                        TypeInfo._OID = Convert.ToInt32(dr[1]);

                        TypeMappings.AddType(TypeInfo);
                    }
                }
            }
        }
Пример #7
0
 /// <summary>
 /// Copy constuctor.
 /// </summary>
 private NpgsqlBackendTypeMapping(NpgsqlBackendTypeMapping Other)
 {
     OIDIndex = new Dictionary<int, NpgsqlBackendTypeInfo>(Other.OIDIndex);
     NameIndex = new Dictionary<string, NpgsqlBackendTypeInfo>(Other.NameIndex);
 }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="Shared">Controls whether the connector can be shared.</param>
        public NpgsqlConnector(NpgsqlConnectionString ConnectionString, bool Pooled, bool Shared)
        {
            this.ConnectionString = ConnectionString;
            _connection_state = ConnectionState.Closed;
            _pooled = Pooled;
            _shared = Shared;
            _isInitialized = false;
            _state = NpgsqlClosedState.Instance;
            _mediator = new NpgsqlMediator();
            _oidToNameMapping = new NpgsqlBackendTypeMapping();
            _planIndex = 0;
            _portalIndex = 0;

        }
Пример #9
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <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();
     _oidToNameMapping = new NpgsqlBackendTypeMapping();
     _planIndex = 0;
     _portalIndex = 0;
     _notificationThreadStopCount = 1;
     _notificationAutoResetEvent = new AutoResetEvent(true);
 }
Пример #10
0
        /// <summary>
        /// Attempt to map types by issuing a query against pg_type.
        /// This function takes a list of NpgsqlTypeInfo and attempts to resolve the OID field
        /// of each by querying pg_type.  If the mapping is found, the type info object is
        /// updated (OID) and added to the provided NpgsqlTypeMapping object.
        /// </summary>
        /// <param name="conn">NpgsqlConnector to send query through.</param>
        /// <param name="TypeMappings">Mapping object to add types too.</param>
        /// <param name="TypeInfoList">List of types that need to have OID's mapped.</param>
        public static void LoadTypesMappings(NpgsqlConnector conn, NpgsqlBackendTypeMapping TypeMappings, IList TypeInfoList)
        {
            StringBuilder       InList = new StringBuilder();
            Hashtable           NameIndex = new Hashtable();

            // Build a clause for the SELECT statement.
            // Build a name->typeinfo mapping so we can match the results of the query
            /// with the list of type objects efficiently.
            foreach (NpgsqlBackendTypeInfo TypeInfo in TypeInfoList) {
                NameIndex.Add(TypeInfo.Name, TypeInfo);
                InList.AppendFormat("{0}'{1}'", ((InList.Length > 0) ? ", " : ""), TypeInfo.Name);
            }

            if (InList.Length == 0) {
                return;
            }

            NpgsqlCommand       command = new NpgsqlCommand("SELECT oid, typname FROM pg_type WHERE typname IN (" + InList.ToString() + ")", conn);
            NpgsqlDataReader    dr = command.ExecuteReader();

            while (dr.Read()) {
                NpgsqlBackendTypeInfo TypeInfo = (NpgsqlBackendTypeInfo)NameIndex[dr[1].ToString()];

                TypeInfo._OID = Convert.ToInt32(dr[0]);

                TypeMappings.AddType(TypeInfo);
            }
        }
Пример #11
0
        ///<summary>
        /// This method creates (or retrieves from cache) a mapping between type and OID 
        /// of all natively supported postgresql data types.
        /// This is needed as from one version to another, this mapping can be changed and
        /// so we avoid hardcoding them.
        /// </summary>
        /// <returns>NpgsqlTypeMapping containing all known data types.  The mapping must be
        /// cloned before it is modified because it is cached; changes made by one connection may
        /// effect another connection.</returns>
        public static NpgsqlBackendTypeMapping CreateAndLoadInitialTypesMapping(NpgsqlConnector conn)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "LoadTypesMapping");

            // [TODO] Verify another way to get higher concurrency.
            lock(CLASSNAME)
            {
                // Check the cache for an initial types map.
                NpgsqlBackendTypeMapping oidToNameMapping = (NpgsqlBackendTypeMapping) BackendTypeMappingCache[conn.ServerVersion];

                if (oidToNameMapping != null)
                {
                    return oidToNameMapping;
                }

                // Not in cache, create a new one.
                oidToNameMapping = new NpgsqlBackendTypeMapping();

                // Create a list of all natively supported postgresql data types.
                NpgsqlBackendTypeInfo[] TypeInfoList = new NpgsqlBackendTypeInfo[]
                {
                    new NpgsqlBackendTypeInfo(0, "unknown", NpgsqlDbType.Text, DbType.String, typeof(String),
                        null),

                    new NpgsqlBackendTypeInfo(0, "refcursor", NpgsqlDbType.Refcursor, DbType.String, typeof(String),
                        null),
			
                    new NpgsqlBackendTypeInfo(0, "char", NpgsqlDbType.Char, DbType.String, typeof(String),
                        null),

                    new NpgsqlBackendTypeInfo(0, "bpchar", NpgsqlDbType.Text, DbType.String, typeof(String),
                        null),

                    new NpgsqlBackendTypeInfo(0, "varchar", NpgsqlDbType.Varchar, DbType.String, typeof(String),
                        null),

                    new NpgsqlBackendTypeInfo(0, "text", NpgsqlDbType.Text, DbType.String, typeof(String),
                        null),
                        
                    new NpgsqlBackendTypeInfo(0, "name", NpgsqlDbType.Text, DbType.String, typeof(String),
                        null),

                    new NpgsqlBackendTypeInfo(0, "bytea", NpgsqlDbType.Bytea, DbType.Binary, typeof(Byte[]),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToBinary)),

                    new NpgsqlBackendTypeInfo(0, "bit", NpgsqlDbType.Bit, DbType.Boolean, typeof(Boolean),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToBit)),

                    new NpgsqlBackendTypeInfo(0, "bool", NpgsqlDbType.Boolean, DbType.Boolean, typeof(Boolean),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToBoolean)),


                    new NpgsqlBackendTypeInfo(0, "int2", NpgsqlDbType.Smallint, DbType.Int16, typeof(Int16),
                        null),

                    new NpgsqlBackendTypeInfo(0, "int4", NpgsqlDbType.Integer, DbType.Int32, typeof(Int32),
                        null),

                    new NpgsqlBackendTypeInfo(0, "int8", NpgsqlDbType.Bigint, DbType.Int64, typeof(Int64),
                        null),

                    new NpgsqlBackendTypeInfo(0, "oid", NpgsqlDbType.Bigint, DbType.Int64, typeof(Int64),
                        null),


                    new NpgsqlBackendTypeInfo(0, "float4", NpgsqlDbType.Real, DbType.Single, typeof(Single),
                        null),

                    new NpgsqlBackendTypeInfo(0, "float8", NpgsqlDbType.Double, DbType.Double, typeof(Double),
                        null),

                    new NpgsqlBackendTypeInfo(0, "numeric", NpgsqlDbType.Numeric, DbType.Decimal, typeof(Decimal),
                        null),

                    new NpgsqlBackendTypeInfo(0, "inet", NpgsqlDbType.Inet, DbType.Object, typeof(NpgsqlInet), new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToInet)),

                    new NpgsqlBackendTypeInfo(0, "money", NpgsqlDbType.Money, DbType.Decimal, typeof(Decimal),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToMoney)),


                    new NpgsqlBackendTypeInfo(0, "date", NpgsqlDbType.Date, DbType.Date, typeof(DateTime),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDate)),

                    new NpgsqlBackendTypeInfo(0, "time", NpgsqlDbType.Time, DbType.Time, typeof(DateTime),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToTime)),

                    new NpgsqlBackendTypeInfo(0, "timetz", NpgsqlDbType.Time, DbType.Time, typeof(DateTime),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToTime)),

                    new NpgsqlBackendTypeInfo(0, "timestamp", NpgsqlDbType.Timestamp, DbType.DateTime, typeof(DateTime),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),

                    new NpgsqlBackendTypeInfo(0, "timestamptz", NpgsqlDbType.Timestamp, DbType.DateTime, typeof(DateTime),
                        new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),


                    new NpgsqlBackendTypeInfo(0, "point", NpgsqlDbType.Point, DbType.Object, typeof(NpgsqlPoint),
                        new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToPoint)),

                    new NpgsqlBackendTypeInfo(0, "lseg", NpgsqlDbType.LSeg, DbType.Object, typeof(NpgsqlLSeg),
                        new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToLSeg)),

                    new NpgsqlBackendTypeInfo(0, "path", NpgsqlDbType.Path, DbType.Object, typeof(NpgsqlPath),
                        new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToPath)),

                    new NpgsqlBackendTypeInfo(0, "box", NpgsqlDbType.Box, DbType.Object, typeof(NpgsqlBox),
                        new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToBox)),

                    new NpgsqlBackendTypeInfo(0, "circle", NpgsqlDbType.Circle, DbType.Object, typeof(NpgsqlCircle),
                        new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToCircle)),

                    new NpgsqlBackendTypeInfo(0, "polygon", NpgsqlDbType.Polygon, DbType.Object, typeof(NpgsqlPolygon),
                        new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToPolygon)),
                };

                // Attempt to map each type info in the list to an OID on the backend and
                // add each mapped type to the new type mapping object.
                LoadTypesMappings(conn, oidToNameMapping, TypeInfoList);

                // Add this mapping to the per-server-version cache so we don't have to
                // do these expensive queries on every connection startup.
                BackendTypeMappingCache.Add(conn.ServerVersion, oidToNameMapping);

                return oidToNameMapping;
            }


        }
 /// <summary>
 /// Clone the current object with a different OID/Name mapping.
 /// </summary>
 /// <param name="oidToNameMapping">OID/Name mapping object to use in the new instance.</param>
 /// <returns>A new NativeToBackendTypeConverterOptions object.</returns>
 internal NativeToBackendTypeConverterOptions Clone(NpgsqlBackendTypeMapping oidToNameMapping = null)
 {
     return new NativeToBackendTypeConverterOptions(_UseConformantStrings, _Supports_E_StringPrefix, _SupportsHexByteFormat, oidToNameMapping);
 }
 internal NativeToBackendTypeConverterOptions(bool useConformantStrings, bool supports_E_StringPrefix, bool supportsHexByteFormat, NpgsqlBackendTypeMapping oidToNameMapping)
     : this(false, useConformantStrings, supports_E_StringPrefix, supportsHexByteFormat, oidToNameMapping)
 {
 }
        private void ReadFromStream_Ver_2(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_2");

            Byte[] input_buffer = new Byte[10]; // Max read will be 4 + 2 + 4

            // Read the number of fields.
            input_stream.Read(input_buffer, 0, 2);
            Int16 num_fields = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 0));


            // Temporary FieldData object to get data from stream and put in array.
            NpgsqlRowDescriptionFieldData fd;

            // Now, iterate through each field getting its data.
            for (Int16 i = 0; i < num_fields; i++)
            {
                fd = new NpgsqlRowDescriptionFieldData();

                // Set field name.
                fd.name = PGUtil.ReadString(input_stream, encoding);

                // Read type_oid(Int32), type_size(Int16), type_modifier(Int32)
                input_stream.Read(input_buffer, 0, 4 + 2 + 4);

                fd.type_oid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 0));
                fd.type_info = type_mapping[fd.type_oid];
                fd.type_size = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(input_buffer, 4));
                fd.type_modifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(input_buffer, 6));

                // Add field data to array.
                fields_data.Add(fd);

                fields_index.Add(fd.name);
            }
        }
Пример #15
0
 /// <summary>
 /// Copy constuctor.
 /// </summary>
 private NpgsqlBackendTypeMapping(NpgsqlBackendTypeMapping Other)
 {
     OIDIndex  = new Dictionary <int, NpgsqlBackendTypeInfo>(Other.OIDIndex);
     NameIndex = new Dictionary <string, NpgsqlBackendTypeInfo>(Other.NameIndex);
 }
Пример #16
0
        ///<summary>
        /// This method creates (or retrieves from cache) a mapping between type and OID
        /// of all natively supported postgresql data types.
        /// This is needed as from one version to another, this mapping can be changed and
        /// so we avoid hardcoding them.
        /// </summary>
        /// <returns>NpgsqlTypeMapping containing all known data types.  The mapping must be
        /// cloned before it is modified because it is cached; changes made by one connection may
        /// effect another connection.</returns>
        public static NpgsqlBackendTypeMapping CreateAndLoadInitialTypesMapping(NpgsqlConnector conn)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "LoadTypesMapping");

            // [TODO] Verify another way to get higher concurrency.
            lock (CLASSNAME)
            {
                // Check the cache for an initial types map.
                NpgsqlBackendTypeMapping oidToNameMapping = (NpgsqlBackendTypeMapping)BackendTypeMappingCache[conn.ServerVersion];

                if (oidToNameMapping != null)
                {
                    return(oidToNameMapping);
                }

                // Not in cache, create a new one.
                oidToNameMapping = new NpgsqlBackendTypeMapping();

                // Create a list of all natively supported postgresql data types.
                NpgsqlBackendTypeInfo[] TypeInfoList = new NpgsqlBackendTypeInfo[]
                {
                    new NpgsqlBackendTypeInfo(0, "unknown", NpgsqlDbType.Text, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "refcursor", NpgsqlDbType.Refcursor, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "char", NpgsqlDbType.Char, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "bpchar", NpgsqlDbType.Text, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "varchar", NpgsqlDbType.Varchar, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "text", NpgsqlDbType.Text, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "name", NpgsqlDbType.Text, DbType.String, typeof(String),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "bytea", NpgsqlDbType.Bytea, DbType.Binary, typeof(Byte[]),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToBinary)),

                    new NpgsqlBackendTypeInfo(0, "bit", NpgsqlDbType.Bit, DbType.Boolean, typeof(Boolean),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToBit)),

                    new NpgsqlBackendTypeInfo(0, "bool", NpgsqlDbType.Boolean, DbType.Boolean, typeof(Boolean),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToBoolean)),


                    new NpgsqlBackendTypeInfo(0, "int2", NpgsqlDbType.Smallint, DbType.Int16, typeof(Int16),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "int4", NpgsqlDbType.Integer, DbType.Int32, typeof(Int32),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "int8", NpgsqlDbType.Bigint, DbType.Int64, typeof(Int64),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "oid", NpgsqlDbType.Bigint, DbType.Int64, typeof(Int64),
                                              null),


                    new NpgsqlBackendTypeInfo(0, "float4", NpgsqlDbType.Real, DbType.Single, typeof(Single),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "float8", NpgsqlDbType.Double, DbType.Double, typeof(Double),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "numeric", NpgsqlDbType.Numeric, DbType.Decimal, typeof(Decimal),
                                              null),

                    new NpgsqlBackendTypeInfo(0, "inet", NpgsqlDbType.Inet, DbType.Object, typeof(NpgsqlInet), new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToInet)),

                    new NpgsqlBackendTypeInfo(0, "money", NpgsqlDbType.Money, DbType.Decimal, typeof(Decimal),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToMoney)),


                    new NpgsqlBackendTypeInfo(0, "date", NpgsqlDbType.Date, DbType.Date, typeof(DateTime),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDate)),

                    new NpgsqlBackendTypeInfo(0, "time", NpgsqlDbType.Time, DbType.Time, typeof(DateTime),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToTime)),

                    new NpgsqlBackendTypeInfo(0, "timetz", NpgsqlDbType.Time, DbType.Time, typeof(DateTime),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToTime)),

                    new NpgsqlBackendTypeInfo(0, "timestamp", NpgsqlDbType.Timestamp, DbType.DateTime, typeof(DateTime),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),

                    new NpgsqlBackendTypeInfo(0, "timestamptz", NpgsqlDbType.Timestamp, DbType.DateTime, typeof(DateTime),
                                              new ConvertBackendToNativeHandler(BasicBackendToNativeTypeConverter.ToDateTime)),


                    new NpgsqlBackendTypeInfo(0, "point", NpgsqlDbType.Point, DbType.Object, typeof(NpgsqlPoint),
                                              new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToPoint)),

                    new NpgsqlBackendTypeInfo(0, "lseg", NpgsqlDbType.LSeg, DbType.Object, typeof(NpgsqlLSeg),
                                              new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToLSeg)),

                    new NpgsqlBackendTypeInfo(0, "path", NpgsqlDbType.Path, DbType.Object, typeof(NpgsqlPath),
                                              new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToPath)),

                    new NpgsqlBackendTypeInfo(0, "box", NpgsqlDbType.Box, DbType.Object, typeof(NpgsqlBox),
                                              new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToBox)),

                    new NpgsqlBackendTypeInfo(0, "circle", NpgsqlDbType.Circle, DbType.Object, typeof(NpgsqlCircle),
                                              new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToCircle)),

                    new NpgsqlBackendTypeInfo(0, "polygon", NpgsqlDbType.Polygon, DbType.Object, typeof(NpgsqlPolygon),
                                              new ConvertBackendToNativeHandler(ExtendedBackendToNativeTypeConverter.ToPolygon)),
                };

                // Attempt to map each type info in the list to an OID on the backend and
                // add each mapped type to the new type mapping object.
                LoadTypesMappings(conn, oidToNameMapping, TypeInfoList);

                // Add this mapping to the per-server-version cache so we don't have to
                // do these expensive queries on every connection startup.
                BackendTypeMappingCache.Add(conn.ServerVersion, oidToNameMapping);

                return(oidToNameMapping);
            }
        }
Пример #17
0
 /// <summary>
 /// Copy constuctor.
 /// </summary>
 private NpgsqlBackendTypeMapping(NpgsqlBackendTypeMapping Other)
 {
     OIDIndex = (Hashtable)Other.OIDIndex.Clone();
     NameIndex = (Hashtable)Other.NameIndex.Clone();
 }
Пример #18
0
 /// <summary>
 /// Copy constuctor.
 /// </summary>
 private NpgsqlBackendTypeMapping(NpgsqlBackendTypeMapping Other)
 {
     OIDIndex  = (Hashtable)Other.OIDIndex.Clone();
     NameIndex = (Hashtable)Other.NameIndex.Clone();
 }
Пример #19
0
 internal NativeToBackendTypeConverterOptions(bool useConformantStrings, bool supports_E_StringPrefix, bool supportsHexByteFormat, NpgsqlBackendTypeMapping oidToNameMapping)
     : this(false, useConformantStrings, supports_E_StringPrefix, supportsHexByteFormat, oidToNameMapping)
 {
 }
Пример #20
0
        /*/// <value>Counts the numbers of Connections that share
        /// this Connector. Used in Release() to decide wether this
        /// connector is to be moved to the PooledConnectors list.</value>
        // internal int mShareCount;*/
        /// <summary>
        /// Opens the physical connection to the server.
        /// </summary>
        /// <remarks>Usually called by the RequestConnector
        /// Method of the connection pool manager.</remarks>
        internal void Open()
        {
            ServerVersion = null;
            // If Connection.ConnectionString specifies a protocol version, we will
            // not try to fall back to version 2 on failure.

            _backendProtocolVersion = (settings.Protocol == ProtocolVersion.Unknown)
                                          ? ProtocolVersion.Version3
                                          : settings.Protocol;

            // Reset state to initialize new connector in pool.
            CurrentState = NpgsqlClosedState.Instance;

            // Get a raw connection, possibly SSL...
            CurrentState.Open(this);
            try
            {
                // Establish protocol communication and handle authentication...
                CurrentState.Startup(this);
            }
            catch (NpgsqlException ne)
            {
                // Check for protocol not supported.  If we have been told what protocol to use,
                // we will not try this step.
                if (settings.Protocol != ProtocolVersion.Unknown)
                {
                    throw;
                }
                // If we attempted protocol version 3, it may be possible to drop back to version 2.
                if (BackendProtocolVersion != ProtocolVersion.Version3)
                {
                    throw;
                }
                NpgsqlError Error0 = (NpgsqlError) ne.Errors[0];

                // If NpgsqlError..ctor() encounters a version 2 error,
                // it will set its own protocol version to version 2.  That way, we can tell
                // easily if the error was a FATAL: protocol error.
                if (Error0.BackendProtocolVersion != ProtocolVersion.Version2)
                {
                    throw;
                }
                // Try using the 2.0 protocol.
                _mediator.ResetResponses();
                BackendProtocolVersion = ProtocolVersion.Version2;
                CurrentState = NpgsqlClosedState.Instance;

                // Get a raw connection, possibly SSL...
                CurrentState.Open(this);
                // Establish protocol communication and handle authentication...
                CurrentState.Startup(this);
            }

            // Change the state of connection to open and ready.
            _connection_state = ConnectionState.Open;
            CurrentState = NpgsqlReadyState.Instance;

            // Fall back to the old way, SELECT VERSION().
            // This should not happen for protocol version 3+.
            if (ServerVersion == null)
            {
                NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this);
                ServerVersion = new Version(PGUtil.ExtractServerVersion((string) command.ExecuteScalar()));
            }

            // Adjust client encoding.

            NpgsqlParameterStatus clientEncodingParam = null;
            if(
                !ServerParameters.TryGetValue("client_encoding", out clientEncodingParam) ||
                (!string.Equals(clientEncodingParam.ParameterValue, "UTF8", StringComparison.OrdinalIgnoreCase) && !string.Equals(clientEncodingParam.ParameterValue, "UNICODE", StringComparison.OrdinalIgnoreCase))
              )
                new NpgsqlCommand("SET CLIENT_ENCODING TO UTF8", this).ExecuteBlind();

            if (!string.IsNullOrEmpty(settings.SearchPath))
            {
                /*NpgsqlParameter p = new NpgsqlParameter("p", DbType.String);
                p.Value = settings.SearchPath;
                NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH TO :p,public", this);
                commandSearchPath.Parameters.Add(p);
                commandSearchPath.ExecuteNonQuery();*/

                /*NpgsqlParameter p = new NpgsqlParameter("p", DbType.String);
                p.Value = settings.SearchPath;
                NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH TO :p,public", this);
                commandSearchPath.Parameters.Add(p);
                commandSearchPath.ExecuteNonQuery();*/

                // TODO: Add proper message when finding a semicolon in search_path.
                // This semicolon could lead to a sql injection security hole as someone could write in connection string:
                // searchpath=public;delete from table; and it would be executed.

                if (settings.SearchPath.Contains(";"))
                {
                    throw new InvalidOperationException();
                }

                // This is using string concatenation because set search_path doesn't allow type casting. ::text
                NpgsqlCommand commandSearchPath = new NpgsqlCommand("SET SEARCH_PATH=" + settings.SearchPath, this);
                commandSearchPath.ExecuteBlind();
            }

            if (!string.IsNullOrEmpty(settings.ApplicationName))
             {
                 if (!SupportsApplicationName)
                 {
                     //TODO
                     //throw new InvalidOperationException(resman.GetString("Exception_ApplicationNameNotSupported"));
                     throw new InvalidOperationException("ApplicationName not supported.");
                 }

                 if (settings.ApplicationName.Contains(";"))
                 {
                     throw new InvalidOperationException();
                 }

                 NpgsqlCommand commandApplicationName = new NpgsqlCommand("SET APPLICATION_NAME='" + settings.ApplicationName + "'", this);
                 commandApplicationName.ExecuteBlind();
             }

            /*
             * Try to set SSL negotiation to 0. As of 2010-03-29, recent problems in SSL library implementations made
             * postgresql to add a parameter to set a value when to do this renegotiation or 0 to disable it.
             * Currently, Npgsql has a problem with renegotiation so, we are trying to disable it here.
             * This only works on postgresql servers where the ssl renegotiation settings is supported of course.
             * See http://lists.pgfoundry.org/pipermail/npgsql-devel/2010-February/001065.html for more information.
             */

            try
            {
                NpgsqlCommand commandSslrenegotiation = new NpgsqlCommand("SET ssl_renegotiation_limit=0", this);
                commandSslrenegotiation.ExecuteBlind();

            }
            catch {}

            /*
             * Set precision digits to maximum value possible. For postgresql before 9 it was 2, after that, it is 3.
             * This way, we set first to 2 and then to 3. If there is an error because of 3, it will have been set to 2 at least.
             * Check bug report #1010992 for more information.
             */

            try
            {
                NpgsqlCommand commandSingleDoublePrecision = new NpgsqlCommand("SET extra_float_digits=2;SET extra_float_digits=3;", this);
                commandSingleDoublePrecision.ExecuteBlind();

            }
            catch {}

            // Make a shallow copy of the type mapping that the connector will own.
            // It is possible that the connector may add types to its private
            // mapping that will not be valid to another connector, even
            // if connected to the same backend version.
            _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone();

            ProcessServerVersion();

            // The connector is now fully initialized. Beyond this point, it is
            // safe to release it back to the pool rather than closing it.
            IsInitialized = true;
        }
Пример #21
0
 /// <summary>
 /// Clone the current object with a different OID/Name mapping.
 /// </summary>
 /// <param name="oidToNameMapping">OID/Name mapping object to use in the new instance.</param>
 /// <returns>A new NativeToBackendTypeConverterOptions object.</returns>
 internal NativeToBackendTypeConverterOptions Clone(NpgsqlBackendTypeMapping oidToNameMapping = null)
 {
     return(new NativeToBackendTypeConverterOptions(_UseConformantStrings, _Supports_E_StringPrefix, _SupportsHexByteFormat, oidToNameMapping));
 }
        /// <value>Counts the numbers of Connections that share
        /// this Connector. Used in Release() to decide wether this
        /// connector is to be moved to the PooledConnectors list.</value>
        // internal int mShareCount;

        /// <summary>
        /// Opens the physical connection to the server.
        /// </summary>
        /// <remarks>Usually called by the RequestConnector
        /// Method of the connection pool manager.</remarks>
        internal void Open()
        {
            ProtocolVersion      PV;

            // If Connection.ConnectionString specifies a protocol version, we will
            // not try to fall back to version 2 on failure.
            if (ConnectionString.Contains(ConnectionStringKeys.Protocol))
            {
                PV = ConnectionString.ToProtocolVersion(ConnectionStringKeys.Protocol);
            }
            else
            {
                PV = ProtocolVersion.Unknown;
            }

            _backendProtocolVersion = (PV == ProtocolVersion.Unknown) ? ProtocolVersion.Version3 : PV;

            // Reset state to initialize new connector in pool.
            Encoding = Encoding.Default;
            CurrentState = NpgsqlClosedState.Instance;

            // Get a raw connection, possibly SSL...
            CurrentState.Open(this);
            // Establish protocol communication and handle authentication...
            CurrentState.Startup(this);

            // Check for protocol not supported.  If we have been told what protocol to use,
            // we will not try this step.
            if (_mediator.Errors.Count > 0 && PV == ProtocolVersion.Unknown)
            {
                // If we attempted protocol version 3, it may be possible to drop back to version 2.
                if (BackendProtocolVersion == ProtocolVersion.Version3)
                {
                    NpgsqlError       Error0 = (NpgsqlError)_mediator.Errors[0];

                    // If NpgsqlError.ReadFromStream_Ver_3() encounters a version 2 error,
                    // it will set its own protocol version to version 2.  That way, we can tell
                    // easily if the error was a FATAL: protocol error.
                    if (Error0.BackendProtocolVersion == ProtocolVersion.Version2)
                    {
                        // Try using the 2.0 protocol.
                        _mediator.ResetResponses();
                        BackendProtocolVersion = ProtocolVersion.Version2;
                        CurrentState = NpgsqlClosedState.Instance;

                        // Get a raw connection, possibly SSL...
                        CurrentState.Open(this);
                        // Establish protocol communication and handle authentication...
                        CurrentState.Startup(this);
                    }
                }
            }

            // Check for errors and do the Right Thing.
            // FIXME - CheckErrors needs to be moved to Connector
            CheckErrors();

            _backend_keydata = _mediator.BackendKeyData;

            // Change the state of connection to open and ready.
            _connection_state = ConnectionState.Open;
            CurrentState = NpgsqlReadyState.Instance;

            String       ServerVersionString = String.Empty;

            // First try to determine backend server version using the newest method.
            if (((NpgsqlParameterStatus)_mediator.Parameters["__npgsql_server_version"]) != null)
                ServerVersionString = ((NpgsqlParameterStatus)_mediator.Parameters["__npgsql_server_version"]).ParameterValue;


            // Fall back to the old way, SELECT VERSION().
            // This should not happen for protocol version 3+.
            if (ServerVersionString.Length == 0)
            {
                NpgsqlCommand command = new NpgsqlCommand("select version();set DATESTYLE TO ISO;", this);
                ServerVersionString = PGUtil.ExtractServerVersion( (String)command.ExecuteScalar() );
            }

            // Cook version string so we can use it for enabling/disabling things based on
            // backend version.
            ServerVersion = PGUtil.ParseServerVersion(ServerVersionString);

            // Adjust client encoding.

            //NpgsqlCommand commandEncoding1 = new NpgsqlCommand("show client_encoding", _connector);
            //String clientEncoding1 = (String)commandEncoding1.ExecuteScalar();

            if (ConnectionString.ToString(ConnectionStringKeys.Encoding, ConnectionStringDefaults.Encoding).ToUpper() == "UNICODE")
            {
                Encoding = Encoding.UTF8;
                NpgsqlCommand commandEncoding = new NpgsqlCommand("SET CLIENT_ENCODING TO UNICODE", this);
                commandEncoding.ExecuteNonQuery();
            }

            // Make a shallow copy of the type mapping that the connector will own.
            // It is possible that the connector may add types to its private
            // mapping that will not be valid to another connector, even
            // if connected to the same backend version.
            _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone();

            ProcessServerVersion();

            // The connector is now fully initialized. Beyond this point, it is
            // safe to release it back to the pool rather than closing it.
            IsInitialized = true;
        }
        private void ReadFromStream_Ver_3(Stream input_stream, Encoding encoding, NpgsqlBackendTypeMapping type_mapping)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ReadFromStream_Ver_3");

            Byte[] input_buffer = new Byte[4]; // Max read will be 4 + 2 + 4 + 2 + 4 + 2

            // Read the length of message.
            // [TODO] Any use for now?
            PGUtil.ReadInt32(input_stream, input_buffer);
            Int16 num_fields = PGUtil.ReadInt16(input_stream, input_buffer);

            // Temporary FieldData object to get data from stream and put in array.
            NpgsqlRowDescriptionFieldData fd;

            for (Int16 i = 0; i < num_fields; i++)
            {
                fd = new NpgsqlRowDescriptionFieldData();

                fd.name = PGUtil.ReadString(input_stream, encoding);
                fd.table_oid = PGUtil.ReadInt32(input_stream, input_buffer);
                fd.column_attribute_number = PGUtil.ReadInt16(input_stream, input_buffer);
                fd.type_oid = PGUtil.ReadInt32(input_stream, input_buffer);
                fd.type_info = type_mapping[fd.type_oid];
                fd.type_size = PGUtil.ReadInt16(input_stream, input_buffer);
                fd.type_modifier = PGUtil.ReadInt32(input_stream, input_buffer);
                fd.format_code = (FormatCode)PGUtil.ReadInt16(input_stream, input_buffer);

                fields_data.Add(fd);
                fields_index.Add(fd.name);
            }
        }