importing messaging-2008 branch to trunk, going on.
[mono.git] / mcs / class / Npgsql / Npgsql / NpgsqlProviderManifest.cs
1 #if ENTITIES
2 using System;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.Data.Common;
6 using System.Data.Metadata.Edm;
7 using System.Xml;
8 using System.Data;
9
10 namespace Npgsql
11 {
12     internal class NpgsqlProviderManifest : DbXmlEnabledProviderManifest
13         {
14         public NpgsqlProviderManifest(string serverVersion)
15             : base(CreateXmlReaderForResource("Npgsql.NpgsqlProviderManifest.Manifest.xml"))
16         {
17         }
18
19         protected override XmlReader GetDbInformation(string informationType)
20         {
21             XmlReader xmlReader = null;
22
23             if (informationType == StoreSchemaDefinition)
24             {
25                 xmlReader = CreateXmlReaderForResource("Npgsql.NpgsqlSchema.ssdl");
26             }
27             else if (informationType == StoreSchemaMapping)
28             {
29                 xmlReader = CreateXmlReaderForResource("Npgsql.NpgsqlSchema.msl");
30             }
31
32             if (xmlReader == null)
33                 throw new ArgumentOutOfRangeException("informationType");
34
35             return xmlReader;
36         }
37
38         private const string MaxLengthFacet = "MaxLength";
39         private const string ScaleFacet = "Scale";
40         private const string PrecisionFacet = "Precision";
41         private const string FixedLengthFacet = "FixedLength";
42
43         public override TypeUsage GetEdmType(TypeUsage storeType)
44         {
45             if (storeType == null)
46                 throw new ArgumentNullException("storeType");
47
48             string storeTypeName = storeType.EdmType.Name;
49             PrimitiveType primitiveType = StoreTypeNameToEdmPrimitiveType[storeTypeName];
50             // TODO: come up with way to determin if unicode is used
51             bool isUnicode = true;
52             Facet facet;
53
54             switch (storeTypeName)
55             {
56                 case "bool":
57                 case "int2":
58                 case "int4":
59                 case "int8":
60                 case "float4":
61                 case "float8":
62                 case "uuid":
63                     return TypeUsage.CreateDefaultTypeUsage(primitiveType);
64                 case "numeric":
65                     {
66                         byte scale;
67                         byte precision;
68                         if (storeType.Facets.TryGetValue(ScaleFacet, false, out facet) &&
69                             !facet.IsUnbounded && facet.Value != null)
70                         {
71                             scale = (byte)facet.Value;
72                             if (storeType.Facets.TryGetValue(PrecisionFacet, false, out facet) &&
73                                 !facet.IsUnbounded && facet.Value != null)
74                             {
75                                 precision = (byte)facet.Value;
76                                 return TypeUsage.CreateDecimalTypeUsage(primitiveType, precision, scale);
77                             }
78                         }
79                         return TypeUsage.CreateDecimalTypeUsage(primitiveType);
80                     }
81                 case "bpchar":
82                     if (storeType.Facets.TryGetValue(MaxLengthFacet, false, out facet) &&
83                         !facet.IsUnbounded && facet.Value != null)
84                         return TypeUsage.CreateStringTypeUsage(primitiveType, isUnicode, true, (int)facet.Value);
85                     else
86                         return TypeUsage.CreateStringTypeUsage(primitiveType, isUnicode, true);
87                 case "varchar":
88                     if (storeType.Facets.TryGetValue(MaxLengthFacet, false, out facet) &&
89                         !facet.IsUnbounded && facet.Value != null)
90                         return TypeUsage.CreateStringTypeUsage(primitiveType, isUnicode, false, (int)facet.Value);
91                     else
92                         return TypeUsage.CreateStringTypeUsage(primitiveType, isUnicode, false);
93                 case "text":
94                 case "xml":
95                     return TypeUsage.CreateStringTypeUsage(primitiveType, isUnicode, false);
96                 case "timestamp":
97                     // TODO: make sure the arguments are correct here
98                     if (storeType.Facets.TryGetValue(PrecisionFacet, false, out facet) &&
99                         !facet.IsUnbounded && facet.Value != null)
100                     {
101                         return TypeUsage.CreateDateTimeTypeUsage(primitiveType, (byte)facet.Value);
102                     }
103                     else
104                     {
105                         return TypeUsage.CreateDateTimeTypeUsage(primitiveType, null);
106                     }
107                 case "date":
108                     return TypeUsage.CreateDateTimeTypeUsage(primitiveType, 0);
109                 case "bytea":
110                     {
111                         if (storeType.Facets.TryGetValue(MaxLengthFacet, false, out facet) &&
112                             !facet.IsUnbounded && facet.Value != null)
113                         {
114                             return TypeUsage.CreateBinaryTypeUsage(primitiveType, false, (int)facet.Value);
115                         }
116                         return TypeUsage.CreateBinaryTypeUsage(primitiveType, false);
117                     }
118                     //TypeUsage.CreateBinaryTypeUsage
119                     //TypeUsage.CreateDateTimeTypeUsage
120                     //TypeUsage.CreateDecimalTypeUsage
121                     //TypeUsage.CreateStringTypeUsage
122             }
123             throw new NotSupportedException();
124         }
125
126         public override TypeUsage GetStoreType(TypeUsage edmType)
127         {
128             if (edmType == null)
129                 throw new ArgumentNullException("edmType");
130
131             PrimitiveType primitiveType = edmType.EdmType as PrimitiveType;
132             if (primitiveType == null)
133                 throw new ArgumentException("Store does not support specified edm type");
134
135             // TODO: come up with way to determin if unicode is used
136             bool isUnicode = true;
137             Facet facet;
138
139             switch (primitiveType.PrimitiveTypeKind)
140             {
141                 case PrimitiveTypeKind.Boolean:
142                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["bool"]);
143                 case PrimitiveTypeKind.Int16:
144                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["int2"]);
145                 case PrimitiveTypeKind.Int32:
146                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["int4"]);
147                 case PrimitiveTypeKind.Int64:
148                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["int8"]);
149                 case PrimitiveTypeKind.Single:
150                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["float4"]);
151                 case PrimitiveTypeKind.Double:
152                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["float8"]);
153                 case PrimitiveTypeKind.Decimal:
154                     {
155                         byte scale;
156                         byte precision;
157                         if (edmType.Facets.TryGetValue(ScaleFacet, false, out facet) &&
158                             !facet.IsUnbounded && facet.Value != null)
159                         {
160                             scale = (byte)facet.Value;
161                             if (edmType.Facets.TryGetValue(PrecisionFacet, false, out facet) &&
162                                 !facet.IsUnbounded && facet.Value != null)
163                             {
164                                 precision = (byte)facet.Value;
165                                 return TypeUsage.CreateDecimalTypeUsage(StoreTypeNameToStorePrimitiveType["numeric"], precision, scale);
166                             }
167                         }
168                         return TypeUsage.CreateDecimalTypeUsage(StoreTypeNameToStorePrimitiveType["numeric"]);
169                     }
170                 case PrimitiveTypeKind.String:
171                     {
172                         // TODO: could get character, character varying, text
173                         if (edmType.Facets.TryGetValue(FixedLengthFacet, false, out facet) &&
174                             !facet.IsUnbounded && facet.Value != null)
175                         {
176                             PrimitiveType characterPrimitive = StoreTypeNameToStorePrimitiveType["bpchar"];
177                             if (edmType.Facets.TryGetValue(MaxLengthFacet, false, out facet) &&
178                                 !facet.IsUnbounded && facet.Value != null)
179                             {
180                                 return TypeUsage.CreateStringTypeUsage(characterPrimitive, isUnicode, true, (int)facet.Value);
181                             }
182                             // this may not work well
183                             return TypeUsage.CreateStringTypeUsage(characterPrimitive, isUnicode, true);
184                         }
185                         if (edmType.Facets.TryGetValue(MaxLengthFacet, false, out facet) &&
186                             !facet.IsUnbounded && facet.Value != null)
187                         {
188                             return TypeUsage.CreateStringTypeUsage(StoreTypeNameToStorePrimitiveType["varchar"], isUnicode, false, (int)facet.Value);
189                         }
190                         // assume text since it is not fixed length and has no max length
191                         return TypeUsage.CreateStringTypeUsage(StoreTypeNameToStorePrimitiveType["text"], isUnicode, false);
192                     }
193                 case PrimitiveTypeKind.DateTime:
194                     if (edmType.Facets.TryGetValue(PrecisionFacet, false, out facet) &&
195                         !facet.IsUnbounded && facet.Value != null)
196                     {
197                         return TypeUsage.CreateDateTimeTypeUsage(StoreTypeNameToStorePrimitiveType["timestamp"], (byte)facet.Value);
198                     }
199                     else
200                     {
201                         return TypeUsage.CreateDateTimeTypeUsage(StoreTypeNameToStorePrimitiveType["timestamp"], null);
202                     }
203                 case PrimitiveTypeKind.Binary:
204                     {
205                         if (edmType.Facets.TryGetValue(MaxLengthFacet, false, out facet) &&
206                             !facet.IsUnbounded && facet.Value != null)
207                         {
208                             return TypeUsage.CreateBinaryTypeUsage(StoreTypeNameToStorePrimitiveType["bytea"], false, (int)facet.Value);
209                         }
210                         return TypeUsage.CreateBinaryTypeUsage(StoreTypeNameToStorePrimitiveType["bytea"], false);
211                     }
212                 case PrimitiveTypeKind.Guid:
213                     return TypeUsage.CreateDefaultTypeUsage(StoreTypeNameToStorePrimitiveType["uuid"]);
214                 // notably missing
215                 // PrimitiveTypeKind.Byte:
216                 // PrimitiveTypeKind.SByte:
217                 // PrimitiveTypeKind.DateTimeOffset:
218                 // PrimitiveTypeKind.Time:
219             }
220
221             throw new NotSupportedException();
222         }
223
224         private static XmlReader CreateXmlReaderForResource(string resourceName)
225         {
226             return XmlReader.Create(System.Reflection.Assembly.GetAssembly(typeof(NpgsqlProviderManifest)).GetManifestResourceStream(resourceName));
227         }
228     }
229 }
230 #endif