Skip to content

Commit 61401fa

Browse files
Merge pull request #395 from smoothdeveloper/schema-metadata-2
Infrastructure for serializable schema metadata, rebased with recent changes, passes all the tests.
2 parents 07a4d2a + 31877ce commit 61401fa

File tree

9 files changed

+443
-232
lines changed

9 files changed

+443
-232
lines changed

paket.dependencies

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ group Test
3535
source https://www.nuget.org/api/v2/
3636
framework: net461, netcoreapp2.0
3737

38-
nuget FSharp.Core = 4.5.2
38+
nuget FSharp.Core = 4.5.2 redirects:force
3939
nuget System.Data.SqlClient
4040
nuget System.Configuration.ConfigurationManager
4141

paket.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ GROUP Test
162162
RESTRICTION: || (== net461) (== netcoreapp2.0)
163163
NUGET
164164
remote: https://www.nuget.org/api/v2
165-
FSharp.Core (4.5.2)
165+
FSharp.Core (4.5.2) - redirects: force
166166
Microsoft.CodeCoverage (15.9) - restriction: || (&& (== net461) (>= netcoreapp1.0)) (== netcoreapp2.0)
167167
Microsoft.DotNet.PlatformAbstractions (2.1) - restriction: || (&& (== net461) (>= netcoreapp1.0)) (== netcoreapp2.0)
168168
System.AppContext (>= 4.1) - restriction: || (&& (== net461) (< net45)) (== netcoreapp2.0)

src/SqlClient.DesignTime/DesignTime.fs

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ type DesignTime private() =
140140

141141
m
142142

143-
static member internal GetRecordType(columns: Column list, ?unitsOfMeasurePerSchema) =
143+
static member internal GetRecordType(columns: Column list, unitsOfMeasurePerSchema) =
144144

145145
columns
146146
|> Seq.groupBy (fun x -> x.Name)
@@ -155,7 +155,7 @@ type DesignTime private() =
155155

156156
if propertyName = "" then failwithf "Column #%i doesn't have name. Only columns with names accepted. Use explicit alias." (i + 1)
157157

158-
let propType = col.GetProvidedType(?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema)
158+
let propType = col.GetProvidedType(unitsOfMeasurePerSchema)
159159

160160
let property = ProvidedProperty(propertyName, propType, getterCode = fun args -> <@@ (unbox<DynamicRecord> %%args.[0]).[propertyName] @@>)
161161

@@ -191,14 +191,14 @@ type DesignTime private() =
191191
let setter = QuotationsFactory.GetBody("SetNonNullableValueInDataRow", column.TypeInfo.ClrType, name)
192192
getter, setter
193193

194-
static member internal GetDataRowType (columns: Column list, ?unitsOfMeasurePerSchema) =
194+
static member internal GetDataRowType (columns: Column list, unitsOfMeasurePerSchema) =
195195
let rowType = ProvidedTypeDefinition("Row", Some typeof<DataRow>)
196196

197197
columns |> List.mapi(fun i col ->
198198

199199
if col.Name = "" then failwithf "Column #%i doesn't have name. Only columns with names accepted. Use explicit alias." (i + 1)
200200

201-
let propertyType = col.GetProvidedType(?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema)
201+
let propertyType = col.GetProvidedType(unitsOfMeasurePerSchema)
202202

203203
let getter, setter = DesignTime.GetDataRowPropertyGetterAndSetterCode col
204204
let property = ProvidedProperty(col.Name, propertyType, getterCode = getter, ?setterCode =
@@ -277,13 +277,8 @@ type DesignTime private() =
277277
dataRowType.AddMember tableProperty
278278

279279
let getColumnsSerializedSchema columns =
280-
columns
281-
|> List.map (fun x ->
282-
let nullable = x.Nullable || x.HasDefaultConstraint
283-
sprintf "%s\t%s\t%b\t%i\t%b\t%b\t%b"
284-
x.Name x.TypeInfo.ClrTypeFullName nullable x.MaxLength x.ReadOnly x.Identity x.PartOfUniqueKey
285-
)
286-
|> String.concat "\n"
280+
let columns = List.toArray columns
281+
Encoding.serialize columns
287282

288283
let ctorCode =
289284
fun _ ->
@@ -313,7 +308,7 @@ type DesignTime private() =
313308

314309
tableProvidedType
315310

316-
static member internal GetOutputTypes (outputColumns: Column list, resultType, rank: ResultRank, hasOutputParameters, ?unitsOfMeasurePerSchema) =
311+
static member internal GetOutputTypes (outputColumns: Column list, resultType, rank: ResultRank, hasOutputParameters, unitsOfMeasurePerSchema) =
317312
if resultType = ResultType.DataReader
318313
then
319314
{ Single = typeof<SqlDataReader>; PerRow = None }
@@ -322,7 +317,7 @@ type DesignTime private() =
322317
{ Single = typeof<int>; PerRow = None }
323318
elif resultType = ResultType.DataTable
324319
then
325-
let dataRowType = DesignTime.GetDataRowType(outputColumns, ?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema)
320+
let dataRowType = DesignTime.GetDataRowType(outputColumns, unitsOfMeasurePerSchema)
326321
let dataTableType = DesignTime.GetDataTableType("Table", dataRowType, outputColumns, CommandResultTable)
327322
dataTableType.AddMember dataRowType
328323

@@ -334,14 +329,14 @@ type DesignTime private() =
334329
then
335330
let column0 = outputColumns.Head
336331
let erasedTo = column0.ErasedToType
337-
let provided = column0.GetProvidedType(?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema)
332+
let provided = column0.GetProvidedType(unitsOfMeasurePerSchema)
338333
let values = Var("values", typeof<obj[]>)
339334
let indexGet = Expr.Call(Expr.Var values, typeof<Array>.GetMethod("GetValue",[|typeof<int>|]), [Expr.Value 0])
340335
provided, erasedTo, Expr.Lambda(values, indexGet)
341336

342337
elif resultType = ResultType.Records
343338
then
344-
let provided = DesignTime.GetRecordType(outputColumns, ?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema)
339+
let provided = DesignTime.GetRecordType(outputColumns, unitsOfMeasurePerSchema)
345340
let names = Expr.NewArray(typeof<string>, outputColumns |> List.map (fun x -> Expr.Value(x.Name)))
346341
let mapping =
347342
<@@
@@ -362,8 +357,8 @@ type DesignTime private() =
362357

363358
let providedType =
364359
match outputColumns with
365-
| [ x ] -> x.GetProvidedType()
366-
| xs -> Microsoft.FSharp.Reflection.FSharpType.MakeTupleType [| for x in xs -> x.GetProvidedType(?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema) |]
360+
| [ x ] -> x.GetProvidedType(unitsOfMeasurePerSchema)
361+
| xs -> Microsoft.FSharp.Reflection.FSharpType.MakeTupleType [| for x in xs -> x.GetProvidedType(unitsOfMeasurePerSchema) |]
367362

368363
let clrTypeName = erasedToTupleType.FullName
369364
let mapping = <@@ Microsoft.FSharp.Reflection.FSharpValue.PreComputeTupleConstructor (Type.GetType(clrTypeName, throwOnError = true)) @@>
@@ -532,20 +527,21 @@ type DesignTime private() =
532527
else
533528
None
534529

535-
static member internal CreateUDTT(t: TypeInfo) =
530+
static member internal CreateUDTT(t: TypeInfo, unitsOfMeasurePerSchema) =
536531
assert(t.TableType)
537532
let rowType = ProvidedTypeDefinition(t.UdttName, Some typeof<obj>, hideObjectMethods = true)
538533

539534
let parameters, sqlMetas =
540535
List.unzip [
541-
for p in t.TableTypeColumns.Value do
536+
for p in t.TableTypeColumns do
542537
let name = p.Name
543-
let param = ProvidedParameter( name, p.GetProvidedType(), ?optionalValue = if p.Nullable then Some null else None)
538+
let param = ProvidedParameter( name, p.GetProvidedType(unitsOfMeasurePerSchema), ?optionalValue = if p.Nullable then Some null else None)
544539
let sqlMeta =
545-
let dbType = p.TypeInfo.SqlDbType
540+
let typeInfo = p.GetTypeInfoConsideringUDDT()
541+
let dbType = typeInfo.SqlDbType
546542
let precision = byte p.Precision
547543
let scale = byte p.Scale
548-
if p.TypeInfo.IsFixedLength then
544+
if typeInfo.IsFixedLength then
549545
if scale = 0uy then
550546
<@@ SqlMetaData(name, dbType) @@>
551547
else
@@ -557,7 +553,7 @@ type DesignTime private() =
557553
]
558554

559555
let ctor = ProvidedConstructor( parameters, fun args ->
560-
let optionsToNulls = QuotationsFactory.MapArrayNullableItems(List.ofArray t.TableTypeColumns.Value, "MapArrayOptionItemToObj")
556+
let optionsToNulls = QuotationsFactory.MapArrayNullableItems(List.ofArray t.TableTypeColumns, "MapArrayOptionItemToObj")
561557

562558
<@@
563559
let values: obj[] = %%Expr.NewArray(typeof<obj>, [ for a in args -> Expr.Coerce(a, typeof<obj>) ])
@@ -580,7 +576,7 @@ type DesignTime private() =
580576
rowType
581577

582578

583-
static member internal GetExecuteArgs(cmdProvidedType: ProvidedTypeDefinition, sqlParameters: Parameter list, udttsPerSchema: Dictionary<_, ProvidedTypeDefinition>, ?unitsOfMeasurePerSchema) =
579+
static member internal GetExecuteArgs(cmdProvidedType: ProvidedTypeDefinition, sqlParameters: Parameter list, udttsPerSchema: IDictionary<_, ProvidedTypeDefinition>, unitsOfMeasurePerSchema) =
584580
[
585581
for p in sqlParameters do
586582
assert p.Name.StartsWith("@")
@@ -592,13 +588,13 @@ type DesignTime private() =
592588
if p.Optional
593589
then
594590
assert(p.Direction = ParameterDirection.Input)
595-
ProvidedParameter(parameterName, parameterType = typedefof<_ option>.MakeGenericType( p.TypeInfo.ClrType) , optionalValue = null)
591+
ProvidedParameter(parameterName, parameterType = typedefof<_ option>.MakeGenericType(p.TypeInfo.ClrType) , optionalValue = null)
596592
else
597593
if p.Direction.HasFlag(ParameterDirection.Output)
598594
then
599595
ProvidedParameter(parameterName, parameterType = p.TypeInfo.ClrType.MakeByRefType(), isOut = true)
600596
else
601-
ProvidedParameter(parameterName, parameterType = p.GetProvidedType(?unitsOfMeasurePerSchema = unitsOfMeasurePerSchema), ?optionalValue = p.DefaultValue)
597+
ProvidedParameter(parameterName, parameterType = p.GetProvidedType(unitsOfMeasurePerSchema), ?optionalValue = p.DefaultValue)
602598
else
603599
assert(p.Direction = ParameterDirection.Input)
604600

@@ -607,7 +603,7 @@ type DesignTime private() =
607603
then //SqlCommandProvider case
608604
match cmdProvidedType.GetNestedType(p.TypeInfo.UdttName) with
609605
| null ->
610-
let rowType = DesignTime.CreateUDTT(p.TypeInfo)
606+
let rowType = DesignTime.CreateUDTT(p.TypeInfo, unitsOfMeasurePerSchema)
611607
cmdProvidedType.AddMember rowType
612608
rowType
613609
| x -> downcast x //same type appears more than once
@@ -669,14 +665,14 @@ type DesignTime private() =
669665
yield upcast ProvidedMethod(factoryMethodName.Value, parameters2, returnType = cmdProvidedType, isStatic = true, invokeCode = body2)
670666
]
671667

672-
static member private CreateTempTableRecord(name, cols) =
668+
static member private CreateTempTableRecord(name, cols, unitsOfMeasurePerSchema) =
673669
let rowType = ProvidedTypeDefinition(name, Some typeof<obj>, hideObjectMethods = true)
674670

675671
let parameters =
676672
[
677673
for (p : Column) in cols do
678674
let name = p.Name
679-
let param = ProvidedParameter( name, p.GetProvidedType(), ?optionalValue = if p.Nullable then Some null else None)
675+
let param = ProvidedParameter( name, p.GetProvidedType(unitsOfMeasurePerSchema), ?optionalValue = if p.Nullable then Some null else None)
680676
yield param
681677
]
682678

@@ -693,7 +689,7 @@ type DesignTime private() =
693689
rowType
694690

695691
// Changes any temp tables in to a global temp table (##name) then creates them on the open connection.
696-
static member internal SubstituteTempTables(connection, commandText: string, tempTableDefinitions : string, connectionId) =
692+
static member internal SubstituteTempTables(connection, commandText: string, tempTableDefinitions : string, connectionId, unitsOfMeasurePerSchema) =
697693
// Extract and temp tables
698694
let tempTableRegex = Regex("#([a-z0-9\-_]+)", RegexOptions.IgnoreCase)
699695
let tempTableNames =
@@ -715,7 +711,7 @@ type DesignTime private() =
715711
let cols = DesignTime.GetOutputColumns(connection, "SELECT * FROM #"+name, [], isStoredProcedure = false)
716712
use drop = new SqlCommand("DROP TABLE #"+name, connection)
717713
drop.ExecuteScalar() |> ignore
718-
DesignTime.CreateTempTableRecord(name, cols), cols)
714+
DesignTime.CreateTempTableRecord(name, cols, unitsOfMeasurePerSchema), cols)
719715

720716
let parameters =
721717
tableTypes

src/SqlClient.DesignTime/QuotationsFactory.fs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ type QuotationsFactory private() =
6565
@>
6666

6767
static member internal MapArrayNullableItems(outputColumns : Column list, mapper : string) =
68-
let columnTypes, isNullableColumn = outputColumns |> List.map (fun c -> c.TypeInfo.ClrTypeFullName, c.Nullable) |> List.unzip
69-
QuotationsFactory.MapArrayNullableItems(columnTypes, isNullableColumn, mapper)
70-
71-
static member internal MapArrayNullableItems(columnTypes : string list, isNullableColumn : bool list, mapper : string) =
68+
let columnTypes, isNullableColumn = outputColumns |> List.map (fun c -> c.GetTypeInfoConsideringUDDT().ClrTypeFullName, c.Nullable) |> List.unzip
7269
assert(columnTypes.Length = isNullableColumn.Length)
7370
let arr = Var("_", typeof<obj[]>)
7471
let body =
@@ -79,7 +76,7 @@ type QuotationsFactory private() =
7976
then
8077
typeof<QuotationsFactory>
8178
.GetMethod(mapper, BindingFlags.NonPublic ||| BindingFlags.Static)
82-
.MakeGenericMethod( Type.GetType( typeName, throwOnError = true))
79+
.MakeGenericMethod(Type.GetType(typeName, throwOnError = true))
8380
.Invoke(null, [| box(Expr.Var arr); box index |])
8481
|> unbox
8582
|> Some

src/SqlClient.DesignTime/SqlClient.DesignTime.fsproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
1111
<DisableImplicitSystemValueTupleReference>true</DisableImplicitSystemValueTupleReference>
1212
</PropertyGroup>
13-
1413
<ItemGroup>
1514
<PackageReference Include="FSharp.Core" Version="4.1.18" Condition="'$(TargetFramework)' == 'net40'" />
1615
<PackageReference Include="FSharp.Core" Version="4.3.4" Condition="'$(TargetFramework)' == 'net461'" />
@@ -59,10 +58,11 @@
5958
<Compile Include="DesignTime.fs" />
6059
<Compile Include="SingleFileChangeMonitor.fs" />
6160
<Compile Include="SingleRootTypeProvider.fs" />
62-
<Compile Include="SqlCommandProvider.fs" />
6361
<Compile Include="SqlClientProvider.fs" />
62+
<Compile Include="SqlCommandProvider.fs" />
6463
<Compile Include="SqlEnumProvider.fs" />
6564
<Compile Include="SqlFileProvider.fs" />
65+
<Content Include="paket.references" />
6666
<None Include="Scripts\Scratchpad.fsx" />
6767
<None Include="Scripts\ReverseLineOrderForNotex.fsx" />
6868
<None Include="Scripts\XE.fsx" />

0 commit comments

Comments
 (0)