/// <summary>
        /// This method takes a type and a set of facets and returns the best mapped equivalent type
        /// in Ingres, taking the store version into consideration.
        /// </summary>
        /// <param name="storeType">A TypeUsage encapsulating an EDM type and a set of facets</param>
        /// <returns>A TypeUsage encapsulating a store type and a set of facets</returns>
        public override TypeUsage GetStoreType(TypeUsage edmType)
        {
            if (edmType == null)
            {
                throw new ArgumentNullException("edmType");
            }
            Debug.Assert(edmType.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType);

            var primitiveType = edmType.EdmType as PrimitiveType;

            if (primitiveType == null)
            {
                throw new ArgumentException(String.Format("The underlying provider does not support the type '{0}'.", edmType));
            }

            ReadOnlyMetadataCollection <Facet> facets = edmType.Facets;

            switch (primitiveType.PrimitiveTypeKind)
            {
            case PrimitiveTypeKind.Boolean:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["tinyint"]));

            case PrimitiveTypeKind.SByte:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["tinyint"]));

            case PrimitiveTypeKind.Byte:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["smallint"]));

            case PrimitiveTypeKind.Int16:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["smallint"]));

            case PrimitiveTypeKind.Int32:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["integer"]));

            case PrimitiveTypeKind.Int64:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["bigint"]));

            case PrimitiveTypeKind.Double:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["float"]));

            case PrimitiveTypeKind.Single:
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["real"]));

            case PrimitiveTypeKind.Decimal:     // decimal, money
                return(TypeUsage.CreateDecimalTypeUsage(StoreTypeNameToStorePrimitiveType["decimal"], TypeHelpers.GetPrecision(edmType, 18), TypeHelpers.GetScale(edmType, 0)));

            case PrimitiveTypeKind.Binary:     // byte, byte varying, long byte
            {
                var isFixedLength  = facets["FixedLength"].GetValue <bool>(false);
                var maxLengthFacet = facets["MaxLength"];
                var maxLength      = maxLengthFacet.GetValue <int?>();
                if (maxLengthFacet.IsUnbounded || maxLength == null || maxLength.Value > binaryMaxSize)
                {
                    maxLength = null;
                }

                var storeTypeName = isFixedLength ? "byte" : maxLength == null ? "long byte" : "byte varying";

                return(CreateBinaryTypeUsage(StoreTypeNameToStorePrimitiveType[storeTypeName], isFixedLength, maxLength));
            }

            case PrimitiveTypeKind.String:     // char, nchar, varchar, nvarchar, long varchar, long nvarchar
            {
                var isUnicode      = facets["Unicode"].GetValue <bool>(false);
                var isFixedLength  = facets["FixedLength"].GetValue <bool>(false);
                var maxLengthFacet = facets["MaxLength"];
                var maxLength      = maxLengthFacet.GetValue <int?>();
                if (maxLengthFacet.IsUnbounded || maxLength == null || maxLength.Value > varcharMaxSize)
                {
                    maxLength = null;
                }

                var storeTypeName = isFixedLength ? "char" : "varchar";
                storeTypeName = isUnicode ? "n" + storeTypeName : storeTypeName;
                storeTypeName = (maxLength == null) ? "long " + storeTypeName : storeTypeName;

                return(CreateStringTypeUsage(StoreTypeNameToStorePrimitiveType[storeTypeName], isUnicode, isFixedLength, maxLength));
            }

            case PrimitiveTypeKind.DateTime:     // ingresdate
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["ingresdate"]));

            case PrimitiveTypeKind.Time:     // time
                return(TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["time"]));

            default:
                throw new NotSupportedException(String.Format("There is no store type corresponding to the EDM type '{0}' of primitive type '{1}'.", edmType, primitiveType.PrimitiveTypeKind));
            }
        }
        /// <summary>
        /// This method takes a type and a set of facets and returns the best mapped equivalent type
        /// in EDM.
        /// </summary>
        /// <param name="storeType">A TypeUsage encapsulating a store type and a set of facets</param>
        /// <returns>A TypeUsage encapsulating an EDM type and a set of facets</returns>
        public override TypeUsage GetEdmType(TypeUsage storeType)
        {
            if (storeType == null)
            {
                throw new ArgumentNullException("storeType");
            }

            string storeTypeName = storeType.EdmType.Name.ToLowerInvariant();

            if (!base.StoreTypeNameToEdmPrimitiveType.ContainsKey(storeTypeName))
            {
                throw new ArgumentException(String.Format("The underlying provider does not support the type '{0}'.", storeTypeName));
            }

            PrimitiveType edmPrimitiveType = base.StoreTypeNameToEdmPrimitiveType[storeTypeName];

            switch (storeTypeName)
            {
            // for some types we just go with simple type usage with no facets
            case "tinyint":
            case "smallint":
            case "integer":
            case "bigint":
            case "integer1":
            case "integer2":
            case "integer4":
            case "integer8":
            case "bool":
            case "int1":
            case "int2":
            case "int4":
            case "int8":
            case "float":
            case "float4":
            case "float8":
            case "double":
            case "real":
                return(TypeUsage.CreateDefaultTypeUsage(edmPrimitiveType));

            case "decimal":
                return(CreateDecimalTypeUsage(edmPrimitiveType, TypeHelpers.GetPrecision(storeType), TypeHelpers.GetScale(storeType)));

            case "money":
                return(TypeUsage.CreateDecimalTypeUsage(edmPrimitiveType, 14, 2));

            case "varchar":
                return(CreateStringTypeUsage(edmPrimitiveType, false, false, TypeHelpers.GetMaxLength(storeType)));

            case "char":
                return(CreateStringTypeUsage(edmPrimitiveType, false, true, TypeHelpers.GetMaxLength(storeType)));

            case "nvarchar":
                return(CreateStringTypeUsage(edmPrimitiveType, true, false, TypeHelpers.GetMaxLength(storeType)));

            case "nchar":
                return(CreateStringTypeUsage(edmPrimitiveType, true, true, TypeHelpers.GetMaxLength(storeType)));

            case "long varchar":
                return(CreateStringTypeUsage(edmPrimitiveType, false, false));

            case "byte":
                return(CreateBinaryTypeUsage(edmPrimitiveType, true, TypeHelpers.GetMaxLength(storeType)));

            case "byte varying":
                return(CreateBinaryTypeUsage(edmPrimitiveType, false, TypeHelpers.GetMaxLength(storeType)));

            case "long byte":
                return(CreateBinaryTypeUsage(edmPrimitiveType, false));

            case "timestamp":
            case "rowversion":
                return(TypeUsage.CreateBinaryTypeUsage(edmPrimitiveType, true, 8));

            case "date":
            case "ingresdate":
            case "ansidate":
                return(TypeUsage.CreateDateTimeTypeUsage(edmPrimitiveType, null));

            default:
                throw new NotSupportedException(String.Format("The underlying provider does not support the type '{0}'.", storeTypeName));
            }
        }