Skip to content

Commit d1d2351

Browse files
Merge pull request #391 from smoothdeveloper/issue-345-fix
Issue #345 fix
2 parents 4f76de4 + 8bf8672 commit d1d2351

File tree

8 files changed

+69
-11
lines changed

8 files changed

+69
-11
lines changed

RELEASE_NOTES.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
#### 2.0.7 November 18, 2020
2+
3+
* Issue #345 Decimal values are trimmed when used as part of a TVP
4+
* Contributors: Suou Ryuu (https://github.com/suou-ryuu), Gauthier Segay (https://github.com/smoothdeveloper)
5+
6+
#### 2.0.6 October 10, 2019
7+
8+
* Issue #364 Fix issues in ToTraceString
9+
* Contributors: piaste (https://github.com/piaste)
10+
111
#### 2.0.5 June 11, 2019
212

313
* Issue #339 Allow timeout on data table Update commands

build.fsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Target.create "DeployTestDB" (fun _ ->
159159

160160
do //create extra object to test corner case
161161
let script = File.ReadAllText(testsSourceRoot @@ "extensions.sql")
162-
for batch in script.Split([|"GO"|], StringSplitOptions.RemoveEmptyEntries) do
162+
for batch in script.Split([|"GO";"go"|], StringSplitOptions.RemoveEmptyEntries) do
163163
use cmd = new SqlCommand(batch, conn)
164164
cmd.ExecuteNonQuery() |> ignore
165165
)

src/SqlClient.DesignTime/DesignTime.fs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,16 @@ type DesignTime private() =
543543
let param = ProvidedParameter( name, p.GetProvidedType(), ?optionalValue = if p.Nullable then Some null else None)
544544
let sqlMeta =
545545
let dbType = p.TypeInfo.SqlDbType
546-
if p.TypeInfo.IsFixedLength
547-
then <@@ SqlMetaData(name, dbType) @@>
546+
let precision = byte p.Precision
547+
let scale = byte p.Scale
548+
if p.TypeInfo.IsFixedLength then
549+
if scale = 0uy then
550+
<@@ SqlMetaData(name, dbType) @@>
551+
else
552+
<@@ SqlMetaData(name, dbType, precision, scale) @@>
548553
else
549-
let maxLength = p.MaxLength
550-
<@@ SqlMetaData(name, dbType, int64 maxLength) @@>
551-
554+
let maxLength = int64 p.MaxLength
555+
<@@ SqlMetaData(name, dbType, maxLength) @@>
552556
yield param, sqlMeta
553557
]
554558

src/SqlClient.DesignTime/SqlClientExtensions.fs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,17 +395,20 @@ type SqlConnection with
395395
cmd.ExecuteQuery(fun cursor ->
396396
let user_type_id = cursor.TryGetValue "user_type_id"
397397
let system_type_id = cursor.["system_type_id"] |> unbox<int>
398-
398+
let precisionOrdinal = cursor.GetOrdinal("precision")
399+
let scaleOrdinal = cursor.GetOrdinal("scale")
399400
{
400401
Column.Name = string cursor.["name"]
401402
TypeInfo = findTypeInfoBySqlEngineTypeId (this.ConnectionString, system_type_id, user_type_id)
402403
Nullable = unbox cursor.["is_nullable"]
403404
MaxLength = cursor.["max_length"] |> unbox<int16> |> int
404405
ReadOnly = not( cursor.GetValueOrDefault("is_updateable", true))
405406
Identity = cursor.GetValueOrDefault("is_identity_column", false)
406-
PartOfUniqueKey = cursor.GetValueOrDefault( "is_part_of_unique_key", false)
407+
PartOfUniqueKey = cursor.GetValueOrDefault("is_part_of_unique_key", false)
407408
DefaultConstraint = null
408409
Description = null
410+
Precision = int16 (cursor.GetByte precisionOrdinal)
411+
Scale = int16 (cursor.GetByte scaleOrdinal)
409412
}
410413
)
411414
|> Seq.toList
@@ -434,6 +437,8 @@ type SqlConnection with
434437
PartOfUniqueKey = false
435438
DefaultConstraint = null
436439
Description = null
440+
Precision = unbox row.["NumericPrecision"]
441+
Scale = unbox row.["NumericScale"]
437442
}
438443
]
439444

@@ -480,7 +485,7 @@ type SqlConnection with
480485
then
481486
[|
482487
use cmd = new SqlCommand("
483-
SELECT c.name, c.system_type_id, c.user_type_id, c.is_nullable, c.max_length, c.is_identity, c.is_computed
488+
SELECT c.name, c.system_type_id, c.user_type_id, c.is_nullable, c.max_length, c.is_identity, c.is_computed, c.[precision], c.scale
484489
FROM sys.table_types AS tt
485490
INNER JOIN sys.columns AS c ON tt.type_table_object_id = c.object_id
486491
WHERE tt.user_type_id = @user_type_id
@@ -490,6 +495,8 @@ type SqlConnection with
490495
cmd.Connection <- this
491496
use reader = cmd.ExecuteReader()
492497
while reader.Read() do
498+
let precisionOrdinal = reader.GetOrdinal "precision"
499+
let scaleOrdinal = reader.GetOrdinal "scale"
493500
let user_type_id = reader.TryGetValue "user_type_id"
494501
let stid = reader.["system_type_id"] |> unbox<byte> |> int
495502
yield {
@@ -502,6 +509,8 @@ type SqlConnection with
502509
PartOfUniqueKey = false
503510
DefaultConstraint = null
504511
Description = null
512+
Precision = int16 (reader.GetByte precisionOrdinal)
513+
Scale = int16 (reader.GetByte scaleOrdinal)
505514
}
506515
|]
507516
else

src/SqlClient.DesignTime/SqlClientProvider.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ type SqlProgrammabilityProvider(config : TypeProviderConfig) as this =
259259
,is_part_of_unique_key = CONVERT(BIT, CASE WHEN index_columns.object_id IS NULL THEN 0 ELSE 1 END)
260260
,default_constraint = ISNULL(OBJECT_DEFINITION(default_object_id), '')
261261
,description = ISNULL(XProp.Value, '')
262+
, columns.precision
263+
, columns.scale
262264
FROM
263265
sys.schemas
264266
JOIN sys.tables ON

src/SqlClient/Shared.fs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ type Column = {
5151
PartOfUniqueKey: bool
5252
DefaultConstraint: string
5353
Description: string
54+
Precision: int16
55+
Scale: int16
5456
} with
5557
member this.ErasedToType =
5658
if this.Nullable
@@ -77,7 +79,10 @@ type Column = {
7779
member this.HasDefaultConstraint = this.DefaultConstraint <> ""
7880
member this.NullableParameter = this.Nullable || this.HasDefaultConstraint
7981

80-
static member Parse(cursor: SqlDataReader, typeLookup: int * int option -> TypeInfo, ?defaultValue, ?description) = {
82+
static member Parse(cursor: SqlDataReader, typeLookup: int * int option -> TypeInfo, ?defaultValue, ?description) =
83+
let precisionOrdinal = cursor.GetOrdinal "precision"
84+
let scaleOrdinal = cursor.GetOrdinal "scale"
85+
{
8186
Name = unbox cursor.["name"]
8287
TypeInfo =
8388
let system_type_id = unbox<byte> cursor.["system_type_id"] |> int
@@ -90,7 +95,9 @@ type Column = {
9095
PartOfUniqueKey = unbox cursor.["is_part_of_unique_key"]
9196
DefaultConstraint = defaultArg defaultValue ""
9297
Description = defaultArg description ""
93-
}
98+
Precision = int16 (cursor.GetByte precisionOrdinal)
99+
Scale = int16 (cursor.GetByte scaleOrdinal)
100+
}
94101

95102
override this.ToString() =
96103
sprintf "%s\t%s\t%b\t%i\t%b\t%b\t%b\t%s\t%s"

tests/SqlClient.Tests/TVPTests.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,12 @@ let UsingMappedTVPFixedInQuery() =
185185
|> Seq.toList
186186

187187
Assert.Equal<_ list>(expected, actual)
188+
189+
type AdventureWorks = SqlProgrammabilityProvider<ConnectionStrings.AdventureWorksNamed>
190+
[<Fact>]
191+
let ``issue #345 decimal in TVP gets rounded`` () =
192+
let value = Some 1.2345M
193+
let tvp = [AdventureWorks.dbo.``User-Defined Table Types``.decimal_test_tvp(value)]
194+
use cmd = new AdventureWorks.dbo.decimal_test(ConnectionStrings.AdventureWorksLiteral)
195+
let resultvalue = cmd.Execute(tvp) |> Seq.head
196+
Assert.Equal(value, resultvalue)

tests/SqlClient.Tests/extensions.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,20 @@ GO
352352
CREATE SYNONYM dbo.HRShift FOR HumanResources.Shift
353353
GO
354354

355+
356+
-- issue #345
357+
if object_id('dbo.decimal_test') is not null
358+
drop procedure dbo.decimal_test
359+
go
360+
if type_id('dbo.decimal_test_tvp') is not null
361+
drop type dbo.decimal_test_tvp
362+
go
363+
create type dbo.decimal_test_tvp as table(quantity decimal(22,8) null)
364+
go
365+
create procedure dbo.decimal_test (@tvp dbo.decimal_test_tvp readonly)
366+
as
367+
begin
368+
select quantity from @tvp
369+
end
370+
go
371+

0 commit comments

Comments
 (0)