From 94847380e42d0bb66fd51ffc51faf116bf74d996 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 02:44:27 -0400 Subject: [PATCH 1/9] Implement a script to automatically create odbcad configs. --- odbcad.ps1 | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 odbcad.ps1 diff --git a/odbcad.ps1 b/odbcad.ps1 new file mode 100644 index 0000000..653bc0c --- /dev/null +++ b/odbcad.ps1 @@ -0,0 +1,170 @@ +# If you invoke the script from the terminal, you can specify the server and db name in case you changed it. +# Otherwise just stick to the default values. +param ( + # change server_name if you installed your sql server as a Named Instance. + # If you installed on the Default Instance, then you can leave this as-is. + # If you're still not sure what is your sql server names, you can run the following powershell command: + # (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances + [string][Parameter(Mandatory = $false)] + $server_name = "localhost", + + [string][Parameter(Mandatory = $false)] + $db_name = "kodb", + + # 64 or 32 + [string][Parameter(Mandatory = $false)] + $platform = "32", + + # When testing connection, we can decide whether to use the Odbc or SqlClient module + [switch][Parameter(Mandatory = $false)] + $test_odbc_module, + + [switch][Parameter(Mandatory = $false)] + $quiet +) + +. "$PSScriptRoot\logger.ps1" + +function ValidateArgs { + if ($platform -ne "32" -and $platform -ne "64") { + MessageError "Wrong platform argument [$platform]. Choose either 64 or 32." + exit 1 + } + + # MSSQLSERVER instance name indicates it is a Default Instance, which we can connect via localhost or dot, + # any other name indicates it is a Named Instance. + $sql_instances = @((Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances) + if ($server_name -in "localhost", ".") { + $server_instance_name = "MSSQLSERVER" + } else { + $server_instance_name = $server_name.Split("\")[-1] + } + + if (-not ($sql_instances -contains $server_instance_name)) { + MessageError "Error: Invalid sql server name: [$($server_name)]" + $sql_instances = @($sql_instances | Where-Object { $_ -ne "MSSQLSERVER" }) + if ($sql_instances) { + MessageError "Available sql named instances: [$($sql_instances -join ', ')]" + MessageError "Example: .\odbcad.ps1 -server_name .\$($sql_instances[-1])" + } + exit 1 + } +} + + + +function SelectSqlDriver { + $drivers = Get-OdbcDriver | Where-Object { $_.Name -like "*SQL Server*" -and $_.Platform -eq "$platform-bit" } + if (-not $drivers) { + MessageWarn "Are you sure SQL Server is installed? I couldn't find any drivers." + exit 1 + } + + $selected_driver = $null + + # In quiet mode we'll just return the last driver, assuming it is the most up to date one + if ($quiet) { + $selected_driver = $drivers[-1] + MessageInfo "Selected SQL Driver: {$($selected_driver.Name)}" + return $selected_driver + } + + if ($drivers.Count -eq 1) { + # Select the first one if we only have one driver + $selected_driver = $drivers[0] + } else { + while (-not $selected_driver) { + MessageInfo "Enter a number to select your SQL Driver:" + for ($i = 0; $i -lt $drivers.Count; $i++) { + Message "$($i+1). $($drivers[$i].Name)" + } + + $user_input = -1 + $input_valid = [int]::TryParse((Read-Host "Input"), [ref]$user_input) + if (-not $input_valid -or $user_input -lt 1 -or $user_input -gt $drivers.Count) { + MessageWarn "Invalid selection." + } else { + $selected_driver = $drivers[$user_input - 1] + MessageInfo "Selected SQL Driver: {$($selected_driver.Name)}" + break + } + } + } + + return $selected_driver +} + +function CreateOdbcConnection { + param ([string][Parameter(Mandatory)] $driver_name) + Remove-OdbcDsn -Name $db_name -DsnType "User" -ErrorAction Ignore + Add-OdbcDsn ` + -Name $db_name ` + -DriverName $driver_name ` + -DsnType "User" ` + -SetPropertyValue @( + "Server=$server_name", + "Database=$db_name", + "AutoTranslate=No", + "Trusted_Connection=Yes" + ) +} + +# Refs: +# https://learn.microsoft.com/en-us/dotnet/api/system.data.odbc.odbcconnection.connectionstring +# https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlconnection.connectionstring +# https://github.com/microsoft/referencesource/blob/master/System.Data/System/Data/Odbc/OdbcConnection.cs +# https://github.com/microsoft/referencesource/blob/master/System.Data/System/Data/SqlClient/SqlConnection.cs +function TestOdbcConnection { + param ([string][Parameter(Mandatory)] $driver_name) + $result = $false + + $con_timeout_seconds = 15 + # Note that in later sql servers `Trusted_Connection` replaced `Integrated Security` and changed it to a synonym. Therefore for backwards + # compatibility we're using `Integrated Security` instead. + $con_str = "Server={0};UID={1};PWD={1};Timeout={2};Integrated Security=True" -f $server_name, ($db_name + "_user"), $con_timeout_seconds + $con = $null + $module = "" + if ($test_odbc_module) { + $module = "Odbc" + $con_str += ";DSN=$db_name;Driver={$driver_name}" + $con = New-Object System.Data.Odbc.OdbcConnection($con_str) + } else { + $module = "SqlClient" + $con_str += ";Database=$db_name;Encrypt=False;TrustServerCertificate=True" + $con = New-Object System.Data.SqlClient.SqlConnection($con_str) + } + + MessageInfo "Testing connection string with $module module: [$($con.ConnectionString)]" + try { + $con.Open() + $result = $con.State -eq [System.Data.ConnectionState]::Open + } catch { + MessageError "An error occurred while testing the connection: $_" + } finally { + if ($con.State -ne [System.Data.ConnectionState]::Closed) { + $con.Close() + } + } + + return $result +} + +function Main { + ValidateArgs + + $selected_driver = SelectSqlDriver + CreateOdbcConnection -driver_name $selected_driver.Name + $is_successful = TestOdbcConnection -driver_name $selected_driver.Name + if ($is_successful) { + MessageSuccess "Successfully created odbc connection driver and tested connection!" + } else { + MessageError "Failed to test connection. Check that you first imported the database." + MessageError "If that didn't work, depending on how you installed MSSQL (Default or Named Instance), you may need to change the server above from localhost to yours." + exit 1 + } +} + +Main +if (-not $quiet) { + cmd /c 'pause' +} From 8d3904f3112e1c5caa65250ce6cc1b6422c1bc60 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 02:46:06 -0400 Subject: [PATCH 2/9] Update docs to allow installing ps sqlserver module with -AllowClobber. Should be fine for the most use cases, but if this causes issues, we may need to update the docs again or find another approach. --- README.md | 2 +- import.ps1 | 5 ++--- src/migration/README.md | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 761df1d..cc8a4ff 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Brief explanation of the directory structure under `src`: - Download the latest MSSQL Management Studio: https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms - Note that it can connect to any version of SQL Server, so even if you use 2008, just get the latest Management Studio for better development experience - Powershell `sqlserver` module - - Open Powershell as Admin and run the following command: `Install-Module -Name sqlserver -Force` + - Open Powershell as Admin and run the following command: `Install-Module sqlserver -AllowClobber -Force` - Note that if you're getting errors during the installation, it is likely because because your SQL installation installed its own powershell module which conflicts with the one we intend to use. They're incompatible and behave differently when creating db exports, hence you need to delete it from your System Environment Variable `PSModulePath` and restart powershell to reload without these modules. Basically if you see in your `PSModulePath` environment variable something with `Microsoft SQL Server`, just remove it, since we want to use the module that we intend to use. - Python and installing via pip the following packages (if you get errors, run powershell as admin): - T-SQL code formatter: `pip install sqlfluff` diff --git a/import.ps1 b/import.ps1 index 07dbac6..5566cfa 100644 --- a/import.ps1 +++ b/import.ps1 @@ -29,8 +29,7 @@ param ( . "$PSScriptRoot\logger.ps1" -# Note that the script will fail if you don't have powershell sqlserver module installed. -# To install it, run powershell as admin and execute the following command: `Install-Module sqlserver` + function ConnectToSqlServer { [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") > $null $server = $null @@ -140,7 +139,7 @@ function Main { if (-not (Get-Module -Name sqlserver -ListAvailable)) { MessageError "Error: The 'sqlserver' powershell module is not installed." MessageError "Please open PowerShell as Administrator and execute the following command to install it:" - MessageError "Install-Module -Name sqlserver -Force" + MessageError "Install-Module sqlserver -AllowClobber -Force" exit 1 } diff --git a/src/migration/README.md b/src/migration/README.md index 3c62a47..087e736 100644 --- a/src/migration/README.md +++ b/src/migration/README.md @@ -12,7 +12,7 @@ Couple of rules and notes when writing migration scripts: Below are instructions for the release engineer in order to create a new db release: - Create a new release branch following the db new release version according version semantics (`git checkout -b release/1.0.1`) -- Run the import script skipping the migration scripts (`.\import.ps1 -run_migration_scripts $false`) +- Run the import script skipping the migration scripts (`.\import.ps1 -skip_migration_scripts`) - Run the export script, to be sure that no diff is produced (`.\export.ps1` and then `git status`) - If there are local changes, something is probably off. Repeat the steps above - If you're sure all in order, best is if you create a new separate PR with the changes, in case empty spaces and such were added From 5c453825d019106ad597818a364bce04789f23c7 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 02:47:16 -0400 Subject: [PATCH 3/9] Update docs about using the project and setting odbcad configs. --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cc8a4ff..4d61541 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,11 @@ Brief explanation of the directory structure under `src`: - Note that it can connect to any version of SQL Server, so even if you use 2008, just get the latest Management Studio for better development experience - Powershell `sqlserver` module - Open Powershell as Admin and run the following command: `Install-Module sqlserver -AllowClobber -Force` - - Note that if you're getting errors during the installation, it is likely because because your SQL installation installed its own powershell module which conflicts with the one we intend to use. They're incompatible and behave differently when creating db exports, hence you need to delete it from your System Environment Variable `PSModulePath` and restart powershell to reload without these modules. Basically if you see in your `PSModulePath` environment variable something with `Microsoft SQL Server`, just remove it, since we want to use the module that we intend to use. + - Note that if you're getting errors during the installation, it is likely because because your SQL installation installed its own powershell module which conflicts with the one we intend to use. They're incompatible and behave differently when creating db exports, hence you may want to delete it from your System Environment Variable `PSModulePath` and restart powershell to reload without these modules. Basically if you see in your `PSModulePath` environment variable something with `Microsoft SQL Server`, just remove it, since we want to use the module that we intend to use. - Python and installing via pip the following packages (if you get errors, run powershell as admin): - T-SQL code formatter: `pip install sqlfluff` - MSSQL scripter: `pip install mssql-scripter` + - Note that if you're using [virtualenv](https://docs.python.org/3/library/venv.html) (recommended), you can simply install the requirements.txt. ### Development @@ -29,7 +30,7 @@ Note that the development process is inspired from [different db development env During development we only create migration scripts to alter the current state of the base. The base here refers to the generated scripts in data, procedure and schema. -Every migration script will be prefixed by max 4 leading zeros. For example, `0001_insert_steve_user.sql` will contain an insert statement to `TB_USER` table. +Every migration script will be prefixed with max 4 leading zeros. For example, `0001_insert_steve_user.sql` will contain an insert statement into `TB_USER` table. Apart from the benifit of having the database under version control, this also makes it easy to use any SQL version you want. I use both 2008 and 2022 and it works perfectly fine with both. @@ -47,8 +48,14 @@ Maybe in the future this will change if it makes things difficult and we maintai ### How to use -If you running for the first time the `import.ps1` script, open Powershell as admin and run this command: `Install-Module sqlserver` +Before running the `import.ps1` script, check that the `$server_name` variable matches with your current server name. If you installed SQL Server using the default instance, then the defaults arguments should work, otherwise you can provide to the script an argument with your custom server name. You can run the following command in powershell to know the names of your current SQL Servers: +```powershell +(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances +``` -Before running the `import.ps1` script, check that the `$server_name` variable matches your current server name. If you use the default instance, then defaults should work, otherwise you can provide the script an argument with your custom server name (`.\import.ps1 -server_name "MyServer`). +Assuming you set a custom name to your SQL Server instance, you may invoke the import command as follows: +```powershell +.\import.ps1 -server_name ".\MyCustomInstanceName" +``` -Once you run the script, the database is ready to be used by the server files. +Once the import script finished importing the db, it will also invoke the `odbcad.ps1` script for you to automatically set odbc configurations so that the server files can connect with your db. From 91c9e99e42d4788b39f6a6f2f1ac8e1340f628f8 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 02:53:33 -0400 Subject: [PATCH 4/9] Remove server_name comments from scripts. It is not documented in the How to use readme. --- export.ps1 | 2 -- import.ps1 | 2 -- odbcad.ps1 | 2 -- 3 files changed, 6 deletions(-) diff --git a/export.ps1 b/export.ps1 index 915aea8..8a3d439 100644 --- a/export.ps1 +++ b/export.ps1 @@ -6,8 +6,6 @@ param ( # change server_name if you installed your sql server as a Named Instance. # If you installed on the Default Instance, then you can leave this as-is. - # If you're still not sure what is your sql server names, you can run the following powershell command: - # (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances [string][Parameter(Mandatory = $false)] $server_name = "localhost", diff --git a/import.ps1 b/import.ps1 index 5566cfa..e5e9575 100644 --- a/import.ps1 +++ b/import.ps1 @@ -7,8 +7,6 @@ param ( # change server_name if you installed your sql server as a Named Instance. # If you installed on the Default Instance, then you can leave this as-is. - # If you're still not sure what is your sql server names, you can run the following powershell command: - # (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances [string][Parameter(Mandatory = $false)] $server_name = "localhost", diff --git a/odbcad.ps1 b/odbcad.ps1 index 653bc0c..e2f621c 100644 --- a/odbcad.ps1 +++ b/odbcad.ps1 @@ -3,8 +3,6 @@ param ( # change server_name if you installed your sql server as a Named Instance. # If you installed on the Default Instance, then you can leave this as-is. - # If you're still not sure what is your sql server names, you can run the following powershell command: - # (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances [string][Parameter(Mandatory = $false)] $server_name = "localhost", From 8b55e8e7919d05f38f3b878a70b5d1cae4bfcd4c Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 14:02:09 -0400 Subject: [PATCH 5/9] Update import.ps1 script to automatically create odbc configs. --- export.ps1 | 2 +- import.ps1 | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/export.ps1 b/export.ps1 index 8a3d439..a2bd8de 100644 --- a/export.ps1 +++ b/export.ps1 @@ -104,7 +104,7 @@ function Main { "$PSScriptRoot\src\procedure\" } - MessageSuccess "Successfully exported [$db_name] database from [$server_name] SQL server." + MessageSuccess "Successfully exported [$db_name] database from [$server_name] SQL server!" } Main diff --git a/import.ps1 b/import.ps1 index e5e9575..4ea2628 100644 --- a/import.ps1 +++ b/import.ps1 @@ -16,6 +16,9 @@ param ( [switch][Parameter(Mandatory = $false)] $skip_migration_scripts, + [switch][Parameter(Mandatory = $false)] + $skip_odbc_creation, + # Generate diffs for each migration script that is not archived. # Warning: make sure to commit your changes before running the script with this enabled, or you may lose work [switch][Parameter(Mandatory = $false)] @@ -156,6 +159,13 @@ function Main { } CreateDbCredentials + + if (-not $skip_odbc_creation) { + MessageInfo "Creating odbc configurations..." + .\odbcad.ps1 -server_name $server_name -quiet + } + + MessageSuccess "Successfully imported [$db_name] database into [$server_name] SQL server!" } Main From 65819da05fbf3f1c85699e0ef1ebc2fdff5cb789 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 14:34:55 -0400 Subject: [PATCH 6/9] Rename logger.ps1 to utils.ps1. --- export.ps1 | 2 +- import.ps1 | 2 +- odbcad.ps1 | 2 +- logger.ps1 => utils.ps1 | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename logger.ps1 => utils.ps1 (100%) diff --git a/export.ps1 b/export.ps1 index a2bd8de..5047334 100644 --- a/export.ps1 +++ b/export.ps1 @@ -20,7 +20,7 @@ param ( $quiet ) -. "$PSScriptRoot\logger.ps1" +. "$PSScriptRoot\utils.ps1" function GetFileEncoding($Path) { diff --git a/import.ps1 b/import.ps1 index 4ea2628..f5511b7 100644 --- a/import.ps1 +++ b/import.ps1 @@ -28,7 +28,7 @@ param ( $quiet ) -. "$PSScriptRoot\logger.ps1" +. "$PSScriptRoot\utils.ps1" function ConnectToSqlServer { diff --git a/odbcad.ps1 b/odbcad.ps1 index e2f621c..28904d9 100644 --- a/odbcad.ps1 +++ b/odbcad.ps1 @@ -21,7 +21,7 @@ param ( $quiet ) -. "$PSScriptRoot\logger.ps1" +. "$PSScriptRoot\utils.ps1" function ValidateArgs { if ($platform -ne "32" -and $platform -ne "64") { diff --git a/logger.ps1 b/utils.ps1 similarity index 100% rename from logger.ps1 rename to utils.ps1 From 9b129d5c466a3f237f8c7af314fc2fa956c4b441 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 15:07:21 -0400 Subject: [PATCH 7/9] Allow the scripts to exit gracefully. --- export.ps1 | 6 ++---- import.ps1 | 8 +++----- odbcad.ps1 | 12 +++++------- utils.ps1 | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/export.ps1 b/export.ps1 index 5047334..d408175 100644 --- a/export.ps1 +++ b/export.ps1 @@ -44,7 +44,7 @@ function Main { MessageError "Error: 'mssql-scripter' command is not available." MessageError "Please make sure you have Python installed and then run:" MessageError "pip install mssql-scripter" - exit 1 + exit_script 1 $quiet } mssql-scripter ` @@ -108,6 +108,4 @@ function Main { } Main -if (-not $quiet) { - cmd /c 'pause' -} +exit_script 0 $quiet diff --git a/import.ps1 b/import.ps1 index f5511b7..466f1f1 100644 --- a/import.ps1 +++ b/import.ps1 @@ -40,7 +40,7 @@ function ConnectToSqlServer { $server.ConnectionContext.Connect() } catch { Write-Error $_ - exit 1 + exit_script 1 $quiet } return $server @@ -141,7 +141,7 @@ function Main { MessageError "Error: The 'sqlserver' powershell module is not installed." MessageError "Please open PowerShell as Administrator and execute the following command to install it:" MessageError "Install-Module sqlserver -AllowClobber -Force" - exit 1 + exit_script 1 $quiet } $server = ConnectToSqlServer @@ -169,6 +169,4 @@ function Main { } Main -if (-not $quiet) { - cmd /c 'pause' -} +exit_script 0 $quiet diff --git a/odbcad.ps1 b/odbcad.ps1 index 28904d9..e0d1756 100644 --- a/odbcad.ps1 +++ b/odbcad.ps1 @@ -26,7 +26,7 @@ param ( function ValidateArgs { if ($platform -ne "32" -and $platform -ne "64") { MessageError "Wrong platform argument [$platform]. Choose either 64 or 32." - exit 1 + exit_script 1 $quiet } # MSSQLSERVER instance name indicates it is a Default Instance, which we can connect via localhost or dot, @@ -45,7 +45,7 @@ function ValidateArgs { MessageError "Available sql named instances: [$($sql_instances -join ', ')]" MessageError "Example: .\odbcad.ps1 -server_name .\$($sql_instances[-1])" } - exit 1 + exit_script 1 $quiet } } @@ -55,7 +55,7 @@ function SelectSqlDriver { $drivers = Get-OdbcDriver | Where-Object { $_.Name -like "*SQL Server*" -and $_.Platform -eq "$platform-bit" } if (-not $drivers) { MessageWarn "Are you sure SQL Server is installed? I couldn't find any drivers." - exit 1 + exit_script 1 $quiet } $selected_driver = $null @@ -158,11 +158,9 @@ function Main { } else { MessageError "Failed to test connection. Check that you first imported the database." MessageError "If that didn't work, depending on how you installed MSSQL (Default or Named Instance), you may need to change the server above from localhost to yours." - exit 1 + exit_script 1 $quiet } } Main -if (-not $quiet) { - cmd /c 'pause' -} +exit_script 0 $quiet diff --git a/utils.ps1 b/utils.ps1 index 13162e6..f921174 100644 --- a/utils.ps1 +++ b/utils.ps1 @@ -1,3 +1,19 @@ +# Importable script containing utility helpful functions + +function exit_script { + param ( + [int][Parameter(Mandatory = $false, Position = 0)] + $code = 0, + [bool][Parameter(Mandatory = $false, Position = 1)] + $quiet = $false + ) + + if (-not $quiet) { + cmd /c 'pause' + } + exit $code +} + # Simple and colorful log messages function Message { param ([string][Parameter(Mandatory)] $message) From ff48df0c4fa8a7876b0ee31657369747cfa0c7e4 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 15:27:25 -0400 Subject: [PATCH 8/9] Validate script arguments on all scripts. --- export.ps1 | 8 ++++++++ import.ps1 | 12 ++++++++++++ odbcad.ps1 | 17 +---------------- utils.ps1 | 25 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/export.ps1 b/export.ps1 index d408175..3cc0576 100644 --- a/export.ps1 +++ b/export.ps1 @@ -22,6 +22,12 @@ param ( . "$PSScriptRoot\utils.ps1" +function ValidateArgs { + if (-not (ValidateServerNameInput $server_name)) { + exit_script 1 $quiet + } +} + function GetFileEncoding($Path) { $bytes = [byte[]](Get-Content $Path -Encoding byte -ReadCount 4 -TotalCount 4) @@ -47,6 +53,8 @@ function Main { exit_script 1 $quiet } + ValidateArgs + mssql-scripter ` -S $server_name ` -d $db_name ` diff --git a/import.ps1 b/import.ps1 index 466f1f1..88a4bf8 100644 --- a/import.ps1 +++ b/import.ps1 @@ -30,6 +30,16 @@ param ( . "$PSScriptRoot\utils.ps1" +function ValidateArgs { + if (-not (ValidateServerNameInput $server_name)) { + exit_script 1 $quiet + } + + if ($skip_migration_scripts -and $generate_diffs) { + MessageError "Error: skip_migration_scripts and generate_diffs args are mutually exclusive." + exit_script 1 $quiet + } +} function ConnectToSqlServer { [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") > $null @@ -144,6 +154,8 @@ function Main { exit_script 1 $quiet } + ValidateArgs + $server = ConnectToSqlServer RecreateDb -server_instance $server RunInitialDbScripts diff --git a/odbcad.ps1 b/odbcad.ps1 index e0d1756..b07d5d8 100644 --- a/odbcad.ps1 +++ b/odbcad.ps1 @@ -29,22 +29,7 @@ function ValidateArgs { exit_script 1 $quiet } - # MSSQLSERVER instance name indicates it is a Default Instance, which we can connect via localhost or dot, - # any other name indicates it is a Named Instance. - $sql_instances = @((Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances) - if ($server_name -in "localhost", ".") { - $server_instance_name = "MSSQLSERVER" - } else { - $server_instance_name = $server_name.Split("\")[-1] - } - - if (-not ($sql_instances -contains $server_instance_name)) { - MessageError "Error: Invalid sql server name: [$($server_name)]" - $sql_instances = @($sql_instances | Where-Object { $_ -ne "MSSQLSERVER" }) - if ($sql_instances) { - MessageError "Available sql named instances: [$($sql_instances -join ', ')]" - MessageError "Example: .\odbcad.ps1 -server_name .\$($sql_instances[-1])" - } + if (-not (ValidateServerNameInput $server_name)) { exit_script 1 $quiet } } diff --git a/utils.ps1 b/utils.ps1 index f921174..b0673d0 100644 --- a/utils.ps1 +++ b/utils.ps1 @@ -14,6 +14,31 @@ function exit_script { exit $code } +# MSSQLSERVER instance name indicates it is a Default Instance, which we can connect via localhost or dot, +# any other name indicates it is a Named Instance. +function ValidateServerNameInput { + param ([string][Parameter(Mandatory, Position = 0)] $server_name) + + $sql_instances = @((Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances) + if ($server_name -in "localhost", ".") { + $server_instance_name = "MSSQLSERVER" + } else { + $server_instance_name = $server_name.Split("\")[-1] + } + + if (-not ($sql_instances -contains $server_instance_name)) { + MessageError "Error: Invalid sql server name: [$($server_name)]" + $sql_instances = @($sql_instances | Where-Object { $_ -ne "MSSQLSERVER" }) + if ($sql_instances) { + MessageError "Available sql named instances: [$($sql_instances -join ', ')]" + MessageError "Example: .\odbcad.ps1 -server_name .\$($sql_instances[-1])" + } + return $false + } + + return $true +} + # Simple and colorful log messages function Message { param ([string][Parameter(Mandatory)] $message) From f26ad64cd29805abc7f42cc996236f291fa01871 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Wed, 22 May 2024 15:49:59 -0400 Subject: [PATCH 9/9] Update create_login.sql to be templated based on ko_db argument. --- import.ps1 | 7 +++++-- src/misc/create_login.sql | 16 ++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/import.ps1 b/import.ps1 index 88a4bf8..5985a0f 100644 --- a/import.ps1 +++ b/import.ps1 @@ -141,8 +141,11 @@ function RunMigrationScriptsAndGenerateDiffs { function CreateDbCredentials { MessageInfo "`n`n### Creating login and user for $db_name... ###" - Message "src/misc/create_login.sql" - InvokeSqlScript -script_path "src/misc/create_login.sql" + $login_script_file = "src/misc/create_login.sql" + Message $login_script_file + $output_script_file = Join-Path $env:TEMP "create_login_$(New-Guid).sql" + (Get-Content $login_script_file) -replace "###DB_NAME###", $db_name | Out-File $output_script_file + InvokeSqlScript -script_path "$output_script_file" } function Main { diff --git a/src/misc/create_login.sql b/src/misc/create_login.sql index 70d03d3..e356536 100644 --- a/src/misc/create_login.sql +++ b/src/misc/create_login.sql @@ -1,12 +1,12 @@ USE [master] -IF EXISTS (SELECT * FROM sys.server_principals WHERE name = N'kodb_user') - DROP LOGIN [kodb_user]; -CREATE LOGIN [kodb_user] WITH PASSWORD=N'kodb_user', DEFAULT_DATABASE=[kodb], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON; +IF EXISTS (SELECT * FROM sys.server_principals WHERE name = N'###DB_NAME###_user') + DROP LOGIN [###DB_NAME###_user]; +CREATE LOGIN [###DB_NAME###_user] WITH PASSWORD=N'###DB_NAME###_user', DEFAULT_DATABASE=[###DB_NAME###], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON; GO -USE [kodb] -IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'kodb_user') - DROP USER [kodb_user]; -CREATE USER [kodb_user] FOR LOGIN [kodb_user]; -EXEC sp_addrolemember N'db_owner', N'kodb_user'; +USE [###DB_NAME###] +IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'###DB_NAME###_user') + DROP USER [###DB_NAME###_user]; +CREATE USER [###DB_NAME###_user] FOR LOGIN [###DB_NAME###_user]; +EXEC sp_addrolemember N'db_owner', N'###DB_NAME###_user'; GO