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;
 }
Exemple #2
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);
        }
Exemple #3
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);
                    }
                }
            }
        }
Exemple #4
0
 /// <summary>
 /// Copy constuctor.
 /// </summary>
 private NpgsqlBackendTypeMapping(NpgsqlBackendTypeMapping Other)
 {
     OIDIndex  = new Dictionary <int, NpgsqlBackendTypeInfo>(Other.OIDIndex);
     NameIndex = new Dictionary <string, NpgsqlBackendTypeInfo>(Other.NameIndex);
 }
 /// <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)
 {
 }