# Test Infrastructure: MS SQL 2022 Database ## Overview The test database uses Microsoft SQL Server 2022 Developer Edition running in Docker. It provides two empty databases for ScadaLink — schema creation is handled by EF Core migrations at application startup (dev mode). ## Image & Ports - **Image**: `mcr.microsoft.com/mssql/server:2022-latest` - **Port**: 1433 - **Edition**: Developer (free, full-featured) ## Credentials | Account | Username | Password | Purpose | |---------|----------|----------|---------| | SA | `sa` | `ScadaLink_Dev1#` | Server admin (setup only) | | App | `scadalink_app` | `ScadaLink_Dev1#` | Application login (db_owner on both databases) | ## Databases | Database | Purpose | |----------|---------| | `ScadaLinkConfig` | Configuration Database component — templates, deployments, users, audit log | | `ScadaLinkMachineData` | Machine/operational data storage | Both databases are created by `infra/mssql/setup.sql`. EF Core migrations populate the `ScadaLinkConfig` schema. The `ScadaLinkMachineData` database is seeded with sample tables and stored procedures by `infra/mssql/machinedata_seed.sql`. ## Data Persistence SQL data is stored in the named Docker volume `scadalink-mssql-data`. Data survives container restarts and `docker compose down`. To reset the database completely: ```bash docker compose down -v docker compose up -d # Re-run setup.sql after the container starts ``` ## First-Time Setup After the first `docker compose up -d`, run the setup script: ```bash docker exec -i scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'ScadaLink_Dev1#' -C \ -i /docker-entrypoint-initdb.d/setup.sql ``` This creates the databases and the `scadalink_app` login. Then seed the Machine Data database with sample tables, stored procedures, and data: ```bash docker exec -i scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'ScadaLink_Dev1#' -C \ -i /docker-entrypoint-initdb.d/machinedata_seed.sql ``` You only need to run these once (or again after deleting the volume). ## Connection Strings For `appsettings.Development.json`: ``` Server=localhost,1433;Database=ScadaLinkConfig;User Id=scadalink_app;Password=ScadaLink_Dev1#;TrustServerCertificate=true ``` ``` Server=localhost,1433;Database=ScadaLinkMachineData;User Id=scadalink_app;Password=ScadaLink_Dev1#;TrustServerCertificate=true ``` ## Verification 1. Check the container is running: ```bash docker ps --filter name=scadalink-mssql ``` 2. Query using `sqlcmd` inside the container: ```bash docker exec -it scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U sa -P 'ScadaLink_Dev1#' -C \ -Q "SELECT name FROM sys.databases" ``` 3. Verify the app login: ```bash docker exec -it scadalink-mssql /opt/mssql-tools18/bin/sqlcmd \ -S localhost -U scadalink_app -P 'ScadaLink_Dev1#' -C \ -d ScadaLinkConfig \ -Q "SELECT DB_NAME()" ``` ## CLI Tool The `infra/tools/mssql_tool.py` script provides a convenient CLI for interacting with the SQL Server. **Install dependencies** (one-time): ```bash pip install -r infra/tools/requirements.txt ``` **Commands**: ```bash # Check connectivity and verify expected databases exist python infra/tools/mssql_tool.py check # Run the first-time setup script (uses autocommit mode for CREATE DATABASE) python infra/tools/mssql_tool.py setup --script infra/mssql/setup.sql # List tables in a database python infra/tools/mssql_tool.py tables --database ScadaLinkConfig # Run an ad-hoc query python infra/tools/mssql_tool.py query --database ScadaLinkConfig --sql "SELECT name FROM sys.tables" ``` Use `--host`, `--port`, `--user`, `--password` to override defaults (localhost:1433, sa, ScadaLink_Dev1#). Run with `--help` for full usage. ## Machine Data Tables & Stored Procedures The `machinedata_seed.sql` script creates the following in `ScadaLinkMachineData`: **Tables**: | Table | Description | Sample Data | |-------|-------------|-------------| | `TagHistory` | Time-series tag values from OPC UA / custom protocols | Pressure, flow, level, temperature, speed readings for SiteA/SiteB | | `ProductionCounts` | Shift/line production totals (good, reject, efficiency) | 3 days of 2-shift data across 2 sites | | `EquipmentEvents` | State changes, faults, maintenance, alarm events | Pump faults, belt inspections, batch starts | | `BatchRecords` | Production batch tracking (start, complete, abort) | 5 batches including one in-progress | | `AlarmHistory` | Historical alarm activations, acks, and clears | Active, acknowledged, and cleared alarms | **Stored Procedures**: | Procedure | Description | |-----------|-------------| | `usp_GetTagHistory` | Get tag values for a tag path within a date range | | `usp_GetProductionSummary` | Aggregate production by line over a date range | | `usp_InsertBatchRecord` | Insert a new batch (for `CachedWrite` testing) | | `usp_CompleteBatch` | Complete or abort a batch | | `usp_GetEquipmentEvents` | Get recent equipment events with optional filters | | `usp_GetActiveAlarms` | Get active/acknowledged alarms by severity | ## Relevance to ScadaLink Components - **Configuration Database** — primary consumer; EF Core context targets `ScadaLinkConfig`. - **Deployment Manager** — reads/writes deployment records in `ScadaLinkConfig`. - **Template Engine** — reads/writes template definitions in `ScadaLinkConfig`. - **Security & Auth** — user/role data stored in `ScadaLinkConfig`. - **External System Gateway** — scripts use `Database.Connection("machineDataConnection")` to query `ScadaLinkMachineData` tables and stored procedures. - **Site Runtime** — scripts call stored procedures via `Database.Connection()` and `Database.CachedWrite()` for batch recording and data queries. - **Inbound API** — methods can query machine data via named database connections. ## Notes - The `sa` password must meet SQL Server complexity requirements (uppercase, lowercase, digit, special character, 8+ characters). - If the container fails to start, check Docker has at least 2GB RAM allocated (SQL Server minimum requirement). - The setup script is idempotent — safe to run multiple times.