Skip to content

Commit

Permalink
support multiple resolution paths separated by semicolon
Browse files Browse the repository at this point in the history
  • Loading branch information
Thorium committed Mar 11, 2024
1 parent 7c75b43 commit f48f7dd
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 36 deletions.
8 changes: 7 additions & 1 deletion docs/content/core/parameters.fsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(*** hide ***)
(*** hide ***)
#I @"../../files/sqlite"
(*** hide ***)
#I "../../../bin/netstandard2.0"
Expand Down Expand Up @@ -91,6 +91,12 @@ let resolutionPath =
__SOURCE_DIRECTORY__ + @"..\..\..\files\sqlite"

(**
The resolution path(s) (as can be semicolon separated if many) should point the
database driver files and their reference assemblies) that work on design-time.
So depending on your IDE you probably want there .NET Standard 2.0 (or 2.1) versions
and not the latest .NET runtime, even when you target your final product to latest .NET.
#### Note on .NET 5 PublishSingleFile and ResolutionPath
If you are publishing your app using .NET 5's PublishSingleFile mode, the driver will
Expand Down
4 changes: 2 additions & 2 deletions src/SQLProvider.DesignTime/SqlDesignTime.fs
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ type public SqlTypeProvider(config: TypeProviderConfig) as this =

let customResPath =
"resolutionPath",
"The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types",
"The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types. Types used in desing-time: If no better clue, prefer .NET Standard 2.0 versions. Semicolon to separate multiple.",
typeof<string>

let customTransOpts =
Expand Down Expand Up @@ -1064,7 +1064,7 @@ type public SqlTypeProvider(config: TypeProviderConfig) as this =
<param name='DatabaseVendor'> The target database vendor</param>
<param name='IndividualsAmount'>The amount of sample entities to project into the type system for each SQL entity type. Default 50. Note GDPR/PII regulations if using individuals with ContextSchemaPath.</param>
<param name='UseOptionTypes'>If set, F# option types will be used in place of nullable database columns. If not, you will always receive the default value of the column's type even if it is null in the database.</param>
<param name='ResolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types.</param>
<param name='ResolutionPath'>The location to look for dynamically loaded assemblies containing database vendor specific connections and custom types. Types used in desing-time: If no better clue, prefer .NET Standard 2.0 versions. Semicolon to separate multiple.</param>
<param name='Owner'>Oracle: The owner of the schema for this provider to resolve. PostgreSQL: A list of schemas to resolve, separated by spaces, newlines, commas, or semicolons.</param>
<param name='CaseSensitivityChange'>Should we do ToUpper or ToLower when generating table names?</param>
<param name='TableNames'>Comma separated table names list to limit a number of tables in big instances. The names can have '%' sign to handle it as in the 'LIKE' query (Oracle and MSSQL Only)</param>
Expand Down
4 changes: 2 additions & 2 deletions src/SQLProvider.Runtime/Providers.Firebird.fs
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,13 @@ module Firebird =
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as ex when ((not(isNull ex.InnerException)) && ex.InnerException :? DllNotFoundException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.TypeInitializationException as te when (te.InnerException :? System.Reflection.TargetInvocationException) ->
let ex = te.InnerException :?> System.Reflection.TargetInvocationException
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex.InnerException))
| :? System.TypeInitializationException as te when not(isNull te.InnerException) -> raise (te.GetBaseException())
Expand Down
6 changes: 3 additions & 3 deletions src/SQLProvider.Runtime/Providers.MsSqlServer.Dynamic.fs
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,19 @@ module MSSqlServerDynamic =
raise (System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as ex when ((not(isNull ex.InnerException)) && ex.InnerException :? DllNotFoundException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath)+
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath)+
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise (System.Reflection.TargetInvocationException(msg, ex))
| :? System.TypeInitializationException as te when (te.InnerException :? System.Reflection.TargetInvocationException) ->
let ex = te.InnerException :?> System.Reflection.TargetInvocationException
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise (System.Reflection.TargetInvocationException(msg, ex.GetBaseException()))
| :? System.TypeInitializationException as te when not(isNull te.InnerException) -> raise (te.GetBaseException())
| se when not (isNull se.InnerException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = se.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = se.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise (System.Reflection.TargetInvocationException(msg, se.GetBaseException()))

Expand Down
4 changes: 2 additions & 2 deletions src/SQLProvider.Runtime/Providers.MySql.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,13 @@ module MySql =
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as ex when ((not(isNull ex.InnerException)) && ex.InnerException :? DllNotFoundException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.TypeInitializationException as te when (te.InnerException :? System.Reflection.TargetInvocationException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let ex = te.InnerException :?> System.Reflection.TargetInvocationException
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex.InnerException))
| :? System.TypeInitializationException as te when not(isNull te.InnerException) -> raise (te.GetBaseException())
Expand Down
4 changes: 2 additions & 2 deletions src/SQLProvider.Runtime/Providers.Oracle.fs
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,13 @@ module internal Oracle =
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as ex when ((not(isNull ex.InnerException)) && ex.InnerException :? DllNotFoundException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.TypeInitializationException as te when (te.InnerException :? System.Reflection.TargetInvocationException) ->
let ex = te.InnerException :?> System.Reflection.TargetInvocationException
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex.InnerException))
| :? System.TypeInitializationException as te when not(isNull te.InnerException) -> raise (te.GetBaseException())
Expand Down
4 changes: 2 additions & 2 deletions src/SQLProvider.Runtime/Providers.Postgresql.fs
Original file line number Diff line number Diff line change
Expand Up @@ -237,15 +237,15 @@ module PostgreSQL =
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as ex when ((not(isNull ex.InnerException)) && ex.InnerException :? DllNotFoundException) ->
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + " , Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + " , Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as e when not(isNull e.InnerException) ->
failwithf "Could not create the connection, most likely this means that the connectionString is wrong. See error from Npgsql to troubleshoot: %s" e.InnerException.Message
| :? System.TypeInitializationException as te when (te.InnerException :? System.Reflection.TargetInvocationException) ->
let ex = te.InnerException :?> System.Reflection.TargetInvocationException
let platform = Reflection.getPlatform(System.Reflection.Assembly.GetExecutingAssembly())
let msg = ex.GetBaseException().Message + ", Path: " + (System.IO.Path.GetFullPath resolutionPath) +
let msg = ex.GetBaseException().Message + ", Path: " + (Reflection.listResolutionFullPaths resolutionPath) +
(if platform <> "" then Environment.NewLine + "Current execution platform: " + platform else "")
raise(System.Reflection.TargetInvocationException(msg, ex.InnerException))
| :? System.TypeInitializationException as te when not(isNull te.InnerException) -> raise (te.GetBaseException())
Expand Down
14 changes: 9 additions & 5 deletions src/SQLProvider.Runtime/Providers.SQLite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,13 @@ type internal SQLiteProvider(resolutionPath, contextSchemaPath, referencedAssemb
//Forces relative paths to be relative to the Runtime assembly
let basePath =
if String.IsNullOrEmpty(resolutionPath) || resolutionPath = Path.DirectorySeparatorChar.ToString()
then runtimeAssembly
else resolutionPath
|> Path.GetFullPath
then runtimeAssembly |> Path.GetFullPath
else (if resolutionPath.Contains ";" then
resolutionPath.Split ';'
|> Array.map Path.GetFullPath
|> Array.filter System.IO.Directory.Exists
|> Array.tryHead |> Option.defaultValue (runtimeAssembly |> Path.GetFullPath)
else resolutionPath |> Path.GetFullPath)

let connectionString =
connectionString // We don't want to replace /../ and we want to support general unix paths as well as current env paths.
Expand All @@ -387,12 +391,12 @@ type internal SQLiteProvider(resolutionPath, contextSchemaPath, referencedAssemb
let msg = ex.Message + "\r\n" + String.Join("\r\n", errorfiles) + (if Environment.Is64BitProcess then " (You are running on x64.)" else " (You are NOT running on x64.)")
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.Reflection.TargetInvocationException as ex when ((not(isNull ex.InnerException)) && ex.InnerException :? DllNotFoundException) ->
let resp = Path.GetFullPath resolutionPath
let resp = Reflection.listResolutionFullPaths resolutionPath
let msg = ex.GetBaseException().Message + ", Path: " + resp + (if Environment.Is64BitProcess then " (You are running on x64.)" else " (You are NOT running on x64.)")
raise(System.Reflection.TargetInvocationException(msg, ex))
| :? System.TypeInitializationException as te when (te.InnerException :? System.Reflection.TargetInvocationException) ->
let ex = te.InnerException :?> System.Reflection.TargetInvocationException
let resp = Path.GetFullPath resolutionPath
let resp = Reflection.listResolutionFullPaths resolutionPath
let msg = ex.GetBaseException().Message + ", Path: " + resp + (if Environment.Is64BitProcess then " (You are running on x64.)" else " (You are NOT running on x64.)")
raise(System.Reflection.TargetInvocationException(msg, ex.InnerException))
| :? System.Reflection.TargetInvocationException as ex when not(isNull ex.InnerException) ->
Expand Down
67 changes: 50 additions & 17 deletions src/SQLProvider.Runtime/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,14 @@ module internal Reflection =
| itms when itms.Length > 0 -> (itms |> Seq.head :?> System.Runtime.Versioning.TargetFrameworkAttribute).FrameworkName
| _ -> ""

let listResolutionFullPaths (resolutionPathSemicoloned:string) =
if resolutionPathSemicoloned.Contains ";" then
String.Join(";",
(resolutionPathSemicoloned.Split ';'
|> Array.map System.IO.Path.GetFullPath))
else
System.IO.Path.GetFullPath resolutionPathSemicoloned

let tryLoadAssembly path =
try
if not (File.Exists path) || path.StartsWith "System.Runtime.WindowsRuntime" then None
Expand All @@ -433,10 +441,19 @@ module internal Reflection =
with e ->
Some(Choice2Of2 e)

let tryLoadAssemblyFrom (resolutionPath:string) (referencedAssemblies:string[]) assemblyNames =
let resolutionPath =
let p = resolutionPath.Replace('/', System.IO.Path.DirectorySeparatorChar)
if not(File.Exists p) then p else p |> Path.GetDirectoryName
let tryLoadAssemblyFrom (resolutionPathSemicoloned:string) (referencedAssemblies:string[]) assemblyNames =

let resolutionPaths =
if resolutionPathSemicoloned.Contains ";" then
resolutionPathSemicoloned.Split ';' |> Array.toList
else [ resolutionPathSemicoloned ]

let resolutionPaths =
resolutionPaths
|> List.map(fun resolutionPath ->
let p = resolutionPath.Replace('/', System.IO.Path.DirectorySeparatorChar)
if not(File.Exists p) then p else p |> Path.GetDirectoryName
)

let referencedPaths =
referencedAssemblies
Expand All @@ -445,10 +462,16 @@ module internal Reflection =

let resolutionPaths =
assemblyNames
|> List.map (fun asm ->
if String.IsNullOrEmpty resolutionPath
then asm
else Path.Combine(resolutionPath,asm))
|> List.collect (fun asm ->
if List.isEmpty resolutionPaths then
[ asm ]
else
resolutionPaths
|> List.map(fun resolutionPath ->
if String.IsNullOrEmpty resolutionPath
then asm
else Path.Combine(resolutionPath,asm))
)

let ifNotNull (x:Assembly) =
if isNull x then ""
Expand All @@ -470,11 +493,16 @@ module internal Reflection =
#endif
Environment.CurrentDirectory;
System.Reflection.Assembly.GetEntryAssembly() |> ifNotNull;]
let dirs =
if not(System.IO.Path.IsPathRooted resolutionPath) then
dirs @ (dirs |> List.map(fun d -> Path.Combine(d, resolutionPath)))
else
let dirs =
if List.isEmpty resolutionPaths then
dirs
else
resolutionPaths
|> List.collect(fun resolutionPath ->
if not(System.IO.Path.IsPathRooted resolutionPath) then
dirs @ (dirs |> List.map(fun d -> Path.Combine(d, resolutionPath)))
else
dirs)

dirs |> Seq.distinct |> Seq.filter(fun x -> not(String.IsNullOrEmpty x) && Directory.Exists x) |> Seq.toList

Expand Down Expand Up @@ -526,7 +554,7 @@ module internal Reflection =
tryLoad
with
| _ ->
let extraPathDirs = (resolutionPath :: myPaths)
let extraPathDirs = (resolutionPaths @ myPaths)
let loaded =
extraPathDirs |> List.tryPick(fun dllPath ->
let assemblyPath = Path.Combine(dllPath,fileName)
Expand Down Expand Up @@ -608,11 +636,16 @@ module internal Reflection =
) |> List.filter Option.isSome
|> List.map(fun o -> o.Value.GetBaseException().Message)
|> Seq.distinct |> Seq.toList
if not(String.IsNullOrEmpty resolutionPath) && not(System.IO.Directory.Exists(resolutionPath)) then
let x = "" :: errors
Choice2Of2(folders, ("resolutionPath directory doesn't exist:" + resolutionPath::errors))
else
let paths =
resolutionPaths
|> List.filter(fun resolutionPath -> not(String.IsNullOrEmpty resolutionPath) && not(System.IO.Directory.Exists resolutionPath))

if List.isEmpty paths then
Choice2Of2(folders, errors)
else
let x = "" :: errors
let resPaths = String.Join(";", paths)
Choice2Of2(folders, ("resolutionPath directory doesn't exist:" + resPaths::errors))

module Sql =

Expand Down

0 comments on commit f48f7dd

Please sign in to comment.