-
Notifications
You must be signed in to change notification settings - Fork 146
Add user defined data type support for SQL Server SSDT #779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
||
let ssdtTableToTable (tbl: SsdtTable) = | ||
{ Schema = tbl.Schema ; Name = tbl.Name ; Type = if tbl.IsView then "view" else "base table" } | ||
|
||
let ssdtColumnToColumn (tbl: SsdtTable) (col: SsdtColumn) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @Thorium, about this function, I was doubtful if I should remove the Option from it since I am unaware of the consequences it might lead into in the GetColumns
member with the List.choose. In any case, I removed it in favor of the UDDT map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with this, @JordanMarr knows better. Maybe the idea was that totally unknown column types are just skipped by SQLProvider. I would expect that e.g. stored procedures could return something unknown that is then just treated as an obj.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was an arbitrary decision on my part to omit the column instead of adding as a variant / obj
.
Your change to call tryFindMappingOrVariant
seems ok to me.
Nice. 👍 |
I have added a simple test, but I am having problems with running them locally on my machine. If someone can build them I would appreciate. I tested using this script with a database I defined myself: open FSharp.Data.Sql
open FSharp.Data.Sql.Common
let [<Literal>] vendor = DatabaseProviderTypes.MSSQLSERVER_SSDT
type Schema = SqlDataProvider<vendor, SsdtPath="/Users/mmagueta/Projects/FOSS/TestSQLProvider/base.dacpac">
type Config =
{ Host: string
Port: string
Database: string
User: string
Password: string }
[<EntryPoint>]
let main _ =
let config = {Host = "localhost"; Port = "1433"; Database = "msdb"; User = "sa"; Password = "P@ssw0rd"}
let dataCtx =
Schema.GetDataContext($"TrustServerCertificate = true; Server={config.Host},{config.Port}; Initial Catalog={config.Database}; User Id={config.User}; Password={config.Password}")
let entity = dataCtx.Dbo.TestUddTs.Create()
printfn "%A" <| ((entity.A.GetType().FullName) = "System.Int32")
0 |
Anything I would still have to go through? If it's ok, I am done with the scope of this PR @JordanMarr |
| Some tm -> tm | ||
| None -> (typeMappingsByName.TryFind "SQL_VARIANT").Value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you're in there, can you improve this line so that it doesn't call TryFind
and Value
(I was probably rushing):
| None -> typeMappingsByName["SQL_VARIANT"]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing, the map should always have it at this point, so makes sense.
Changed it on this commit: f059201
I have submitted a PR to add my old SSDT unit test project back to the test sln. |
Thanks! |
I'll release new version tomorrow. |
You can do user-defined table type like CREATE TYPE [F#].[Payment] AS TABLE(
[Date] [smalldatetime] NULL,
[Amount] [money] NULL
) Although I'm not sure if SQL is a good tool for this kind of domain modelling as it's not meant to be a general purpose programming language. |
This is somewhat useful for hidden behavior inside procedures (to group a query and insert somewhere from it), triggers (like error handling to persist a rollback), etc; but not so much to expose it via the provider. That's why I parsed a user defined data type only, UDTTs are not even being parsed on the XML from the dacpac. |
Proposed Changes
Currently, SSDTs for SQL Server do not support user defined data types. This means if a simple custom type is defined, such as the one from below, the column does not get translated to F#.
A simple UDDT:
From the lsp:

On the following table, where all the types are also simple overloads on REAL and INT:
With this PR we now have:

A further explanation on the implementation may be found under
Further comments
Types of changes
Changes this PR introduces:
Checklist
Further comments
UDDTName
is the given name to the type, andUDDTInheritedType
is the base type thatUDDTName
inherits fromtryFindMappingOrVariant
where such map is passedtypeMappingsByName
map, if it does not find, attempts once again on the UDDT map, if something was found, searches for the base type intypeMappingsByName
, otherwise defaults toSQL_VARIANT
and consequently toSystem.Object