-
-
Notifications
You must be signed in to change notification settings - Fork 33
Local Database
If you are working on issues that require making changes to the database schema or reference data (i.e., data that is considered part of the application, such as lookup lists, or, in the case of TDM, CalculationRules),
then you should work with a copy of the shared development database on your local machine, which we will refer to as a Local Database
.
This is a summary of the instructions. See other sections below for more detailed steps.
-
Install SQL Server Express directly (Windows) or via a Docker container (macOS, Linux, or Windows)
-
For macOS or Linux computers, you should install Docker CE and run the Microsoft SQL Server image.
-
For Windows Pro Edition computers, you can install either:
- Docker CE and run the database in a Docker container and run the Microsoft SQL Server image or
- Microsoft SQL Server Express edition.
- If you are new to SQL Server, Docker is probably easier.
-
For Windows Home Edition computers, you should install Microsoft SQL Server Express edition, since running Docker on a Windows Home machine is very painful.
-
If you are working on Windows and already have any instance of SQL Server installed, you may just use your existing instance for development.
-
-
Create a database called
tdmdev
once you have a local copy of SQL Server on your machine. (You can use a different name if you want, and modify the subsequent instructions accordingly.) -
- Edit the
.env
file with your local database connection string information.
- Edit the
-
Run the database migrations to create the database schema and populate it with seed data by opening a terminal in the root directory of the repo and running:
npm run flyway:migrate
-
Run the application (
npm start
), and it will be using the local database. -
Additional info is provided at the end: Working With Migrations, Debugging Tips
NOTE: If for any reason, you corrupt your local database, you can simply drop the
tdmdev
database from your local SQL Server, re-create it, and run migrations again to start over.
-
Install Docker Desktop from here and follow the provided instructions. This will install Docker client and a local Docker daemon (server) that can host docker containers.
The following command will run if docker is set up and ready to go:
docker version
-
Open the Docker Desktop app and ensure it is running.
-
Download the official Microsoft SQL Server image and create a local container named
tdm_sql_server
by running:docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Dogfood1!' -e 'MSSQL_PID=Express' \ -p 1434:1433 --name tdm_sql_server \ -d mcr.microsoft.com/mssql/server:2019-latest
This may take several minutes to run, as it is installing SQL Server on your Docker server.
-
Validate that the Docker container process named
tdm_sql_server
is currently running:docker ps
-
Install SQL Server Express
- Look for the SQL Server Express 2019 download link
- Download and install the file called
SQL2019-SSEI-Expr.exe
- You can accept all the default installation instructions, but
- Choose
Windows
andSQL Server Authenitication
and useDogfood1!
as thesa
(system administrator) password. - It will be helpful to also choose the option to install the client tools as well (
SQL Server Management Studio
andsqlcmd
, in particular).
- Choose
There are several ways to create a new database on a SQL Server, but the following allow you to do it from the command line for both Mac and Windows.
You can run a single-line command to create the database in a Git Bash shell:
docker exec -it tdm_sql_server /opt/mssql-tools/bin/sqlcmd -U sa -P Dogfood1! -Q "CREATE DATABASE tdmdev"
See
Option 2 > NOTE
under the Creating the Database (Windows) Docker section if you are trying to run in a Windows Bash shell.
If you want use the command line (CLI) to write other SQL scripts, you can use the sqlcmd
utility:
docker exec -it tdm_sql_server /opt/mssql-tools/bin/sqlcmd -U sa -P Dogfood1!
- If successful, you should get to a
sqlcmd
command prompt:1>
. - Try running a SQL command, such as
SELECT name FROM sys.sysdatabases
, then on a separate line runGO
. You should see yourtdmdev
database. - For more tips, see the Docker Debugging Tips below or this Quickstart Guide.
If running SQL Server on Windows,
-
run:
sqlcmd -U sa -S localhost\Sqlexpress -P Dogfood1! -Q "CREATE DATABASE tdmdev;"
(or replace
Sqlexpress
with your own instance name.)
If running SQL Server in Docker, run one of the following options:
-
Option 1 (use
sqlcmd
from Windows):sqlcmd -U sa -S localhost,1434 -P Dogfood1! -Q "CREATE DATABASE tdmdev;"
or
-
Option 2 (run
sqlcmd
in the Docker container):You can run the same set of instructions as the above section, Creating the Database via Docker (Mac, Linux, Windows).
NOTE: Running in Windows Bash shell may cause issues.
If you try running the single-liner Docker command on a Windows Bash shell (as opposed to Git Bash), you will likely get this:
$ docker exec -it tdm_sql_server /opt/mssql-tools/bin/sqlcmd -U sa -P Dogfood1! -Q "CREATE DATABASE tdmdev" OCI runtime exec failed: exec failed: container_linux.go:349: starting container process caused "exec: \"C:/Program Files/Git/opt/mssql-tools/bin/sqlcmd\": stat C:/Program Files/Git/opt/mssql-tools/bin/sqlcmd: no such file or directory": unknown
This is a problem with the heuristics that MinGW / Git Bash uses to map Windows paths to POSIX paths in the target container. This page suggests the following work-around:
MSYS_NO_PATHCONV=1 docker exec -it tdm_sql_server /opt/mssql-tools/bin/sqlcmd -U sa -P Dogfood1! -Q "CREATE DATABASE tdmdev"
However, this page describes the heuristics that Git Bash uses to to map paths from Windows to the bash shell, so you can also just change the path to the sqlcmd to start with two slashes like this:
docker exec -it tdm_sql_server //opt/mssql-tools/bin/sqlcmd -U sa -P Dogfood1! -Q "CREATE DATABASE tdmdev"
This problem also affects Docker volume mapping from a Git Bash shell.
You can connect the application to your local database by configuring your .env
file with the correct local database settings. Connecting to a database with a client tool is optional but highly encouraged, especially if you are new to working with databases as it allows you to easily view the database with a GUI.
If you followed the instructions from the previous sections, you should have the following property values:
- server name =
localhost
- The server name corresponds to a physical machine (or virtual machine or Docker container), but it is common to install two or more SQL Server _instances* on a single server, in which case the different instances are distinguished by an instance name.
- username =
sa
- password =
Dogfood1!
- database =
tdmdev
For experienced developers who may occasionally connect to the shared development server, you may have a few sets of connection parameter settings in your
.env
file, and uncomment only the one you need at that particular time.
On Docker (Mac, Linux, Windows):
-
Edit the
.env
file with your local database connection string information. To run in Docker, we use port number1434
and do not use an instance name:SQL_SERVER_NAME=localhost SQL_SERVER_INSTANCE= SQL_SERVER_PORT=1434 SQL_DATABASE_NAME=tdmdev SQL_USER_NAME=sa SQL_PASSWORD=Dogfood1!
- The container will be running SQL Server without an instance name on port 1433 internally; the previous set of instructions re-mapped this to a different external port, which we arbitrarily chose as
1434
. This alternative port number helps avoid a potential conflict with the default instance of SQL Server for those who are running Windows Pro, and may want to run your local database for the project in Docker.
- The container will be running SQL Server without an instance name on port 1433 internally; the previous set of instructions re-mapped this to a different external port, which we arbitrarily chose as
-
Source the
.env
file in order to specify the updated configurations in your local shell environment by running:source .env
NOTE: You may need to run
source
on the.env
file any time you update your local environment variables.
To validate that you are using the correct local environment variables, run echo $SQL_DATABASE_NAME
or echo $SQL_PASSWORD
and ensure that they match the values indicated in your .env
file.
On Windows:
-
To connect to a local database installed conventionally on Windows with the SQL Express edition, use the instance name
SQLEXPRESS
and no port number:SQL_SERVER_NAME=localhost SQL_SERVER_INSTANCE=SQLEXPRESS SQL_SERVER_PORT= SQL_DATABASE_NAME=tdmdev SQL_USER_NAME=sa SQL_PASSWORD=Dogfood1!
Server Instance:
- If you installed the free SQL Server Express edition for the first time, the instance name will be
SQLEXPRESS
. - If you installed any other edition for the first time, it will have an empty instance name, also called the
default
instance. - If you are using the Windows
default
instance, omit "SQLEXPRESS" or change it to the appropriate instance name for the instance you want to use.
Port Number:
- The
default
instance is accessible on port 1433. - If you have other instances, they are each randomly assigned to a different port to avoid conflict.
- Windows will handle mapping instance names to the corresponding port on the server.
The upshot is that when you install SQL Server on Windows, you should not specify a port number, and only specify an instance name if there is one for the instance you want to use.
- If you installed the free SQL Server Express edition for the first time, the instance name will be
It is generally helpful when working with SQL Server to have a client tool for testing database connections and SQL queries, especially if you are new to working with databases. There are a few good options out there, including:
- You can download Azure Data Studio. Since this is a cross-platform (Windows/macOS/Linux) application, we will be using it in any examples below.
- Microsoft's SQL Server Management Studio is the historical standard tool for working with MS SQL Server, but only runs on Windows machines. It is an installation option when you install any version of MS SQL Server on your machine, and can also be installed separately.
- DBeaver is a great option, for both Mac and Windows users
To connect with Azure Data Studio:
- Start Azure Data Studio
- Select on the "Create a Connection" button
- Enter connection details:
- Server:
locahost,1434
for SQL on docker, orlocalhost\SQLEXPRESS
for SQL on Windows - Authentication Type:
SQL Login
- User Name:
sa
- Password:
Dogfood1!
Leave the other settings at their default, and press "Connect"
- Server:
To connect with SQL Server Management Studio on Windows,
- Note that the servername in the login will be
locahost,1434
(for SQL on docker) orlocalhost\SQLEXPRESS
(for SQL on Windows) use this exact punctuation or the connection will not work.
To connect with DBeaver:
- Start DBeaver
- Select the "Connect to database" button and choose SQL Server
- Enter connection details:
- Host:
localhost
- Database/Schema:
tdmdev
- Port:
1434
for SQL on docker, orSQLEXPRESS
for SQL on Windows - Authentication:
SQL Server Authentication
- User name:
sa
- Password:
Dogfood1!
- Leave the other settings at their default, press "Test Connection" to validate the connection, and press "Finish"
- Host:
-
Install all the npm packages if you haven't done so already by running
npm install
in the root directory -
Create the database schema and populate it with seed data by running the following command from the server directory:
npm run flyway:migrate
This will run the SQL scripts in the
/db/migration
folder to populate the database with an up-to-date TDM schema and data.If the migration is successful, you will see a message that ends with a message saying something like
Successfully applied X migrations for schema [dbo]...
-
If you receive an error that says
ERROR: Validate failed: Migration checksum mismatch for migration version XXXX
, then you may want to run flyway'srepair
orclean
command described below. -
At this point, you should be able to start the application as usual, by running
npm start
, and it will be using the local database. HOORAY!
In order to make changes to the database schema or reference data, you will need to write SQL or Transact-SQL scripts and test them in your local database. When the scripts are ready, you can create a migration file in the /db/migration
directory with those SQL scripts and submit a pull request with your changes. We are using a node wrapper library around the Flyway CLI tool to run our migrations.
NOTE: It's important to never edit pre-existing migration files as it may cause the migrations to fail (due to different checksums)
Most client tools allow you to create a "New Query" where you can directly write and test your SQL or Transact-SQL scripts in your local database. You could also write your SQL scripts in the Docker SQL Server container. (See step-by-step instructions in the Create the Database section for example.)
When you are confident in your SQL or TRANSACT-SQL script, you will need to create a new migration file.
To create a new migration file, run the following in the terminal from the server directory:
./db/create-migration
This is an executable file that will generate a .sql
file in your /db/migration/
folder.
The file uses the following naming convention VYYYYMMDD.HHMM__*.sql
, e.g. V20200812.2148__update_foobar_table.sql
- Version (
VYYYYMMDD.HHMM
): 8-digit date and 4-digit time separated by a period, in sequence order of files already there - Separator (
__
): two consecutive underscores that separate the version from the description - Description (
*
): a snake-cased short description of the changes you are making
Because our node library is simply a wrapper around the Flyway CLI, you can utilize some of the Flyway commands that we've set up:
-
Run the following in the terminal from the server directory:
npm run flyway:migrate
will run your migration file on your local database. (This is the main one you will use.)- It will migrate the schema to the latest version.
- Flyway will also create the metadata table automatically if it doesn't exist.
TIP: Change your database data beforehand (e.g. with your client tool) to something different in order to check that the new migration file works.
-
npm run flyway:info
- Prints the details and status information about all the migrations
-
npm run flyway:validate
- Validates applied migrations against resolved ones (on the filesystem or classpath) to detect accidental changes that may prevent the schema(s) from being recreated exactly.
- Validation fails if:
- Differences in migration names, types or checksums are found
- Versions have been applied that aren't resolved locally anymore
- Versions have been resolved that haven't been applied yet
- Validation fails if:
- Validates applied migrations against resolved ones (on the filesystem or classpath) to detect accidental changes that may prevent the schema(s) from being recreated exactly.
-
npm run flyway:repair
- Repairs the Flyway metadata table. This will perform the following actions:
- Remove any failed migrations on databases without DDL transactions (User objects left behind must still be cleaned up manually)
- Correct wrong checksums
- Repairs the Flyway metadata table. This will perform the following actions:
-
npm run flyway:clean
- Clean is a great help in development and test. It will effectively give you a fresh start, by wiping your configured schemas completely clean. All objects (tables, views, procedures, …) will be dropped.
Needless to say: do not use against the production DB!
- When you submit your PR, the migration file will be included in your PR and get saved to the develop branch in the repo.
- The developer who approves and merges your PR to the develop branch should then be able to run migrations against the shared development database to apply your changes as part of the merge.
- Rolling back a migration?
- Writing a script using DBeaver or MSSMS.
-
To learn more about using SQL Server in Docker, check out this Quickstart Guide.
-
To check if your SQL Server container is running, run:
docker ps
-
If you get an error due to permission level, add
sudo
in front of the docker command. e.g.sudo docker exec -it tdm_sql_server bash
-
To run SQL or TRANSACT-SQL commands inside your docker container:
docker exec -it tdm_sql_server /opt/mssql-tools/bin/sqlcmd -U sa -P Dogfood1!
-
If successful, you should get to a sqlcmd command prompt:
1>
-
To show existing databases in the SQL container
SELECT name from sys.Databases GO
GO
should be on the following line
-
-
Run
exit
to exit the container or shell -
To stop running the SQL Server container, run
docker stop tdm_sql_server
-
To show hidden Docker containers (that may have been stopped, but not yet removed), run
docker ls -a
-
To remove a container, run
docker remove tdm_sql_server
NOTE: The container must be stopped before it can be removed
-
See more Docker examples and basic commands in the Deployment docs
- If you get this error
No Active Connection
when making a SQL query, you will need toSet Active Connection
to your current database under theSQL Editor
setting