pax_global_header 0000666 0000000 0000000 00000000064 15215256560 0014521 g ustar 00root root 0000000 0000000 52 comment=8f2bd9407a562b9c65c0f8108ea02acde0faf5e6
microsoft-mssql-django-8f2bd94/ 0000775 0000000 0000000 00000000000 15215256560 0016547 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.devcontainer/ 0000775 0000000 0000000 00000000000 15215256560 0021306 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.devcontainer/Dockerfile 0000664 0000000 0000000 00000002367 15215256560 0023310 0 ustar 00root root 0000000 0000000 # Use Debian Bookworm explicitly - Microsoft packages are signed for Debian 12
FROM mcr.microsoft.com/devcontainers/python:3.14-bookworm
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies (including libmemcached-dev for Django's pylibmc tests)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
gnupg \
unixodbc-dev \
libmemcached-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install Microsoft ODBC Driver for SQL Server (both 17 and 18)
RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \
&& echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update \
&& ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql17 msodbcsql18 mssql-tools18 \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Add mssql-tools to PATH
ENV PATH="$PATH:/opt/mssql-tools18/bin"
# Pre-install core Python dependencies so post-create is faster
RUN pip install --no-cache-dir \
pyodbc \
pytz \
coverage
WORKDIR /workspaces/mssql-django
microsoft-mssql-django-8f2bd94/.devcontainer/devcontainer.json 0000664 0000000 0000000 00000001667 15215256560 0024674 0 ustar 00root root 0000000 0000000 {
"name": "mssql-django",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/mssql-django",
"postCreateCommand": "bash .devcontainer/scripts/post-create.sh",
"customizations": {
"vscode": {
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": true,
"python.testing.unittestArgs": [
"-v", "-s", "-p", "test_*.py", "-t", "."
],
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true
}
},
"extensions": [
"ms-python.python",
"ms-python.debugpy",
"charliermarsh.ruff",
"ms-mssql.mssql",
"github.copilot"
]
}
},
"forwardPorts": [1433],
"remoteEnv": {
"DJANGO_SETTINGS_MODULE": "testapp.settings"
}
}
microsoft-mssql-django-8f2bd94/.devcontainer/docker-compose.yml 0000664 0000000 0000000 00000001714 15215256560 0024746 0 ustar 00root root 0000000 0000000 services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspaces/mssql-django:cached
command: sleep infinity
environment:
# These env vars are read by testapp/settings.py
- MSSQL_HOST=db
- MSSQL_PORT=1433
- MSSQL_USER=sa
- MSSQL_PASSWORD=MyPassword42
- MSSQL_DRIVER=ODBC Driver 17 for SQL Server
depends_on:
db:
condition: service_healthy
db:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "MyPassword42"
MSSQL_PID: "Developer"
ports:
- "1433:1433"
healthcheck:
test:
- CMD-SHELL
- /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -C -Q "SELECT 1" || exit 1
interval: 5s
timeout: 5s
retries: 20
start_period: 15s
volumes:
- mssql-data:/var/opt/mssql
volumes:
mssql-data:
microsoft-mssql-django-8f2bd94/.devcontainer/scripts/ 0000775 0000000 0000000 00000000000 15215256560 0022775 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.devcontainer/scripts/post-create.sh 0000775 0000000 0000000 00000004437 15215256560 0025572 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# post-create.sh β runs once after the dev container is built
set -euo pipefail
echo "π Setting up mssql-django development environment..."
echo "π¦ Installing mssql-django in editable mode..."
pip install -e .
echo "π¦ Installing dev/test dependencies..."
pip install \
pyodbc \
pytz \
coverage \
unittest-xml-reporting \
tox
# Clone Django source for running Django's own test suite (test.sh)
if [ ! -d "django" ]; then
echo "π₯ Cloning Django source for integration tests..."
DJANGO_VERSION="$(python -m django --version)"
git clone --depth 1 --branch "${DJANGO_VERSION}" \
https://github.com/django/django.git django 2>/dev/null || \
git clone --depth 1 https://github.com/django/django.git django
fi
# Set up useful shell aliases
echo "β‘ Setting up aliases..."
cat > ~/.shell_aliases << 'EOF'
# mssql-django development aliases
alias test='python manage.py test testapp'
alias testall='bash test.sh'
alias migrate='python manage.py migrate'
alias makemigrations='python manage.py makemigrations'
alias shell='python manage.py shell'
alias dbshell='python manage.py dbshell'
alias sqlcmd='sqlcmd -S db -U sa -P "${MSSQL_PASSWORD:-MyPassword42}" -C'
EOF
# Ensure aliases are sourced in both shells
grep -qxF 'source ~/.shell_aliases' ~/.bashrc 2>/dev/null || echo 'source ~/.shell_aliases' >> ~/.bashrc
grep -qxF 'source ~/.shell_aliases' ~/.zshrc 2>/dev/null || echo 'source ~/.shell_aliases' >> ~/.zshrc
# Wait for SQL Server to be ready, then verify connectivity
echo "β³ Waiting for SQL Server..."
bash .devcontainer/scripts/wait-for-sql.sh
echo ""
echo "=============================================="
echo "π mssql-django dev environment is ready!"
echo "=============================================="
echo ""
echo "π¦ What's ready:"
echo " β
mssql-django installed (editable)"
echo " β
SQL Server running (db:1433)"
echo " β
Django source cloned for test suite"
echo ""
echo "π Quick start - just type these commands:"
echo " test β Run testapp tests"
echo " testall β Run full Django test suite"
echo " migrate β Run migrations"
echo " shell β Django shell"
echo " sqlcmd β Connect to SQL Server"
echo ""
echo "=============================================="
microsoft-mssql-django-8f2bd94/.devcontainer/scripts/run-tests.sh 0000775 0000000 0000000 00000004167 15215256560 0025310 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# run-tests.sh β convenience wrapper for running tests
#
# Usage:
# bash .devcontainer/scripts/run-tests.sh # run mssql-django tests
# bash .devcontainer/scripts/run-tests.sh --django # run Django's test suite (test.sh)
# bash .devcontainer/scripts/run-tests.sh --module queries # run a specific Django test module
# bash .devcontainer/scripts/run-tests.sh --coverage # run with coverage report
set -euo pipefail
cd /workspaces/mssql-django
case "${1:-}" in
--django)
echo "==> Running Django's own test suite via test.sh..."
bash test.sh
;;
--module)
shift
MODULE="${1:?'Provide a module name, e.g.: --module queries'}"
echo "==> Running Django test module: ${MODULE}..."
cd django
DJANGO_VERSION="$(python -m django --version)"
# Ensure checkout matches installed Django version
CURRENT_REF="$(git describe --tags --exact-match 2>/dev/null || echo 'unknown')"
if [ "${CURRENT_REF}" != "${DJANGO_VERSION}" ]; then
echo "==> Switching Django checkout from ${CURRENT_REF} to ${DJANGO_VERSION}..."
git fetch --depth=1 origin +refs/tags/*:refs/tags/* 2>/dev/null || true
git checkout "${DJANGO_VERSION}" 2>/dev/null || true
fi
pip install -q -r tests/requirements/py3.txt 2>/dev/null || true
coverage run tests/runtests.py --settings=testapp.settings --noinput "${MODULE}"
coverage report --include='*mssql*' --omit='*virtualenvs*'
coverage xml --include='*mssql*' --omit='*virtualenvs*' -o coverage.xml
echo "Coverage report written to coverage.xml"
;;
--coverage)
echo "==> Running mssql-django tests with coverage..."
coverage run manage.py test testapp --noinput -v2
coverage report --include='*mssql*' --omit='*virtualenvs*'
coverage xml --include='*mssql*' --omit='*virtualenvs*' -o coverage.xml
echo "Coverage report written to coverage.xml"
;;
*)
echo "==> Running mssql-django tests..."
python manage.py test testapp --noinput -v2
;;
esac
microsoft-mssql-django-8f2bd94/.devcontainer/scripts/wait-for-sql.sh 0000775 0000000 0000000 00000001570 15215256560 0025664 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# wait-for-sql.sh β poll SQL Server until it accepts connections
set -euo pipefail
HOST="${MSSQL_HOST:-db}"
PORT="${MSSQL_PORT:-1433}"
USER="${MSSQL_USER:-sa}"
PASSWORD="${MSSQL_PASSWORD:-MyPassword42}"
MAX_RETRIES="${MSSQL_MAX_RETRIES:-30}"
SLEEP_INTERVAL=2
echo "Waiting for SQL Server at ${HOST}:${PORT}..."
for i in $(seq 1 "$MAX_RETRIES"); do
# -C trusts the server certificate (bypasses TLS validation for local dev)
if sqlcmd -S "${HOST},${PORT}" -U "${USER}" -P "${PASSWORD}" -C \
-Q "SELECT 1" -b -o /dev/null 2>/dev/null; then
echo "SQL Server is ready! (attempt ${i}/${MAX_RETRIES})"
exit 0
fi
echo " attempt ${i}/${MAX_RETRIES} β not ready yet, retrying in ${SLEEP_INTERVAL}s..."
sleep "$SLEEP_INTERVAL"
done
echo "ERROR: SQL Server did not become available after ${MAX_RETRIES} attempts."
exit 1
microsoft-mssql-django-8f2bd94/.editorconfig 0000664 0000000 0000000 00000000346 15215256560 0021227 0 ustar 00root root 0000000 0000000 # https://editorconfig.org/
root = true
[*]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
charset = utf-8
max_line_length = 119
[*.{yml,yaml}]
indent_size = 2
microsoft-mssql-django-8f2bd94/.github/ 0000775 0000000 0000000 00000000000 15215256560 0020107 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15215256560 0022272 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/ISSUE_TEMPLATE/bug_report.md 0000664 0000000 0000000 00000001736 15215256560 0024773 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
There are some features which are not supported yet. Please check the [Limitations](https://github.com/microsoft/mssql-django#limitations) first to see if your bug is listed.
**Software versions**
* Django:
* mssql-django:
* python:
* SQL Server:
* OS:
**Table schema and Model**
**Database Connection Settings**
`
// Paste your database settings from Settings.py here.
`
**Problem description and steps to reproduce**
**Expected behavior and actual behavior**
**Error message/stack trace**
**Any other details that can be helpful**
microsoft-mssql-django-8f2bd94/.github/ISSUE_TEMPLATE/feature_request.md 0000664 0000000 0000000 00000001470 15215256560 0026021 0 ustar 00root root 0000000 0000000 ---
name: Feature Request
about: Suggest an idea for this project
title: "[FEATURE REQUEST]"
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? If so, please give a short summary of the problem and how the feature would resolve it**
**Describe the preferred solution**
**Describe alternatives you've considered**
**Additional context**
**Reference Documentations/Specifications**
microsoft-mssql-django-8f2bd94/.github/ISSUE_TEMPLATE/question.md 0000664 0000000 0000000 00000000501 15215256560 0024457 0 ustar 00root root 0000000 0000000 ---
name: Question
about: Ask a question
title: "[QUESTION]"
labels: question
assignees: ''
---
**Question**
**Relevant Issues and Pull Requests**
microsoft-mssql-django-8f2bd94/.github/actions/ 0000775 0000000 0000000 00000000000 15215256560 0021547 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/actions/post-coverage-comment/ 0000775 0000000 0000000 00000000000 15215256560 0025765 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/actions/post-coverage-comment/action.yml 0000664 0000000 0000000 00000005004 15215256560 0027764 0 ustar 00root root 0000000 0000000 name: Post Coverage Comment
description: Posts a standardized code coverage comment on a pull request
inputs:
pr_number:
description: 'Pull request number'
required: true
coverage_percentage:
description: 'Overall coverage percentage'
required: true
covered_lines:
description: 'Number of covered lines'
required: true
total_lines:
description: 'Total number of lines'
required: true
patch_coverage_pct:
description: 'Patch/diff coverage percentage'
required: true
low_coverage_files:
description: 'Files with lowest coverage (multiline)'
required: true
patch_coverage_summary:
description: 'Patch coverage summary markdown (multiline)'
required: true
ado_url:
description: 'Azure DevOps build URL'
required: true
runs:
using: composite
steps:
- name: Post coverage comment
uses: marocchino/sticky-pull-request-comment@v2
with:
header: Code Coverage Report
number: ${{ inputs.pr_number }}
message: |
# π Code Coverage Report
### π₯ Diff Coverage
### **${{ inputs.patch_coverage_pct }}**
|
### π― Overall Coverage
### **${{ inputs.coverage_percentage }}**
|
**π Total Lines Covered:** `${{ inputs.covered_lines }}` out of `${{ inputs.total_lines }}`
**π Project:** `mssql-django`
|
---
${{ inputs.patch_coverage_summary }}
---
### π Files Needing Attention
π Files with overall lowest coverage (click to expand)
```diff
${{ inputs.low_coverage_files }}
```
---
### π Quick Links
|
βοΈ Build Summary
|
π Coverage Details
|
|
[View Azure DevOps Build](${{ inputs.ado_url }})
|
[Browse Full Coverage Report](${{ inputs.ado_url }}&view=codecoverage-tab)
|
microsoft-mssql-django-8f2bd94/.github/copilot-instructions.md 0000664 0000000 0000000 00000020475 15215256560 0024654 0 ustar 00root root 0000000 0000000 # GitHub Copilot Instructions for mssql-django
## Project Overview
mssql-django is a Django database backend for Microsoft SQL Server. It enables Django applications to use SQL Server as their database by translating Django's database abstraction layer to SQL Server's T-SQL dialect.
## Repository Structure
```
mssql/ # Core backend implementation (~4400 lines)
βββ schema.py # Schema modifications, _alter_field (~1585 lines, largest file)
βββ base.py # DatabaseWrapper, connection/cursor handling (~736 lines)
βββ compiler.py # SQL query compilation, pagination, ORDER BY (~697 lines)
βββ operations.py # SQL Server-specific operations (~694 lines)
βββ functions.py # SQL function overrides via as_microsoft pattern (~673 lines)
βββ features.py # SQL Server capability flags
βββ introspection.py # Database introspection
βββ creation.py # Test database creation/destruction
βββ client.py # Command-line client support
βββ management/
βββ commands/
βββ install_regex_clr.py # CLR assembly for REGEXP_LIKE support
testapp/ # Unit tests for the backend
βββ tests/ # 42 unit tests across 11 test files
βββ settings.py # Test configuration with EXCLUDED_TESTS
βββ models.py # Test models
django/ # NOT in repo β cloned at runtime by test.sh for full test suite
```
## Key Technical Context
### SQL Server Limitations
| Limitation | Description | Where handled |
|------------|-------------|---------------|
| No tuple/row comparisons | `WHERE (a, b) IN (...)` not supported | Tests excluded |
| ORDER BY uniqueness | Same column can't appear twice | `compiler.py` deduplication |
| No LIMIT/OFFSET natively | Requires `TOP` or `OFFSET...FETCH` | `compiler.py` emulation |
| No boolean in SELECT | `supports_boolean_expr_in_select_clause = False` | CASE WHEN wrapping |
| No subqueries in GROUP BY | `supports_subqueries_in_group_by = False` | `features.py` flag |
| String concatenation | Uses `+` instead of `\|\|` | `compiler.py` |
| RAND() in ORDER BY | Doesn't randomize | Replaced with `NEWID()` in `compiler.py` |
| Identifier quoting | Uses `[brackets]` not `"quotes"` | `operations.py` `quote_name()` |
| ~2100 parameter limit | SQL Server max parameters per query | Temp table splitting in `functions.py` |
### Critical Files
**mssql/schema.py** (~1585 lines) - The **largest** file. Its `_alter_field()` method (~647 lines) handles cascading constraint drop/recreate logic for schema migrations.
**mssql/compiler.py** (~697 lines) - Handles:
- SQL query generation with SQL Server syntax
- OFFSET/LIMIT pagination emulation
- ORDER BY deduplication for composite primary keys
- ROW_NUMBER() window function for offset queries
**mssql/functions.py** (~673 lines) - Uses the `as_microsoft` monkey-patching pattern (see Coding Patterns below). Also handles parameter limit splitting via temp tables for large IN clauses.
**mssql/features.py** - Declares what SQL Server supports/doesn't support. Check here first when a test fails to see if it's a known limitation.
**testapp/settings.py** - Contains `EXCLUDED_TESTS` list for Django tests that cannot pass due to SQL Server limitations (not bugs). Includes version-gated exclusions (e.g., ~75 tests excluded for Django 6.0).
## Coding Patterns
### The `as_microsoft` Pattern
The primary extension mechanism. Functions in `functions.py` define custom SQL generation and are monkey-patched onto Django expression classes:
```python
def sqlserver_round(self, compiler, connection, **extra_context):
# Custom SQL Server ROUND implementation
return self.as_sql(compiler, connection, template='ROUND(%(expressions)s, %(extra)s)', **extra_context)
# Monkey-patch onto Django's class
Round.as_microsoft = sqlserver_round
```
This pattern is used for: `Cast`, `Ln`, `Log`, `Mod`, `Round`, `Window`, `Now`, `MD5`, `SHA*`, `OrderBy`, `Lookup`, `Random`, and more.
### SQL Generation
When modifying SQL generation in compiler.py:
```python
# Always handle both qualified and unqualified column references
col_ref = '[table].[column]' # qualified
col_ref = '[column]' # unqualified
# Handle multi-column ORDER BY from composite PKs
# Django 5.2+ can emit: "[t].[a] DESC, [t].[b] DESC" as single item
parts = [p.strip() for p in o_sql.split(',')]
```
### Test Exclusions
When a test fails due to SQL Server limitations (not bugs), add to `EXCLUDED_TESTS` in testapp/settings.py:
```python
EXCLUDED_TESTS = [
'app.test_module.TestClass.test_method', # Brief reason
]
```
### Regex Support
`python manage.py install_regex_clr ` installs a CLR assembly enabling `REGEXP_LIKE` support for regex-based Django tests.
## Testing
### Run mssql-django unit tests (42 tests)
```bash
python manage.py test testapp.tests
```
### Run specific Django test module
```bash
cd django && python tests/runtests.py --settings=testapp.settings
```
### Common test modules for validation
- `composite_pk` - Composite primary key support (Django 5.2+)
- `ordering` - ORDER BY functionality
- `queries` - General query tests
- `aggregation` - Aggregate functions
- `schema` - Schema migration tests
## Version Compatibility
- **Django**: 3.2, 4.0, 4.1, 4.2, 5.0, 5.1, 5.2, 6.0
- **Python**: 3.8 β 3.14
- **SQL Server**: 2017, 2019, 2022, 2025; Azure SQL DB / Managed Instance
- **ODBC Driver**: 17 or 18 for SQL Server
## Common Issues
### "Column specified more than once in ORDER BY"
SQL Server error 169. Check for duplicate columns in ORDER BY, especially with composite primary keys. Fix in `compiler.py` ORDER BY deduplication logic.
### "Tuple lookups not supported"
Add test to `EXCLUDED_TESTS` - this is a SQL Server limitation, not a bug.
### Tests hanging on database creation
The test database may already exist. Answer "yes" to drop it, or use:
```bash
echo "yes" | python tests/runtests.py --settings=testapp.settings
```
## Pull Request Guidelines
1. Run affected Django test modules, not just unit tests
2. Check if failures are bugs or SQL Server limitations
3. Add appropriate test exclusions with comments explaining why
4. Keep compiler.py and schema.py changes focused - they are complex and sensitive
5. When adding SQL Server function overrides, use the `as_microsoft` pattern in `functions.py`
## Development Workflow Rules
### Git Hygiene
- **Only commit files you intentionally changed.** Untracked files (e.g. `result.xml`, build artifacts) may exist in the workspace but not be in `.gitignore` β do not stage or commit them. Review `git diff` and `git status` before committing.
- Do not modify `testapp/settings.py` database connection settings (ODBC driver version, passwords) as part of a PR β those are local dev environment changes.
### Fix Quality
- **Find the root cause, not a workaround.** Don't parse or manipulate compiled SQL strings when Django provides a structured expression API to solve the problem at the right level. Work at the expression/node level (e.g. override `get_order_by()`, use `as_microsoft` pattern) rather than post-hoc string surgery on generated SQL.
- Follow existing codebase patterns: the `as_microsoft` monkey-patching pattern in `functions.py`, the `_as_microsoft()` dispatch in `compiler.py`, and compiler method overrides are the standard extension points.
### Test Discipline
- **All tests must be green before submitting.** If a test fails due to a SQL Server limitation (not a bug you introduced), add it to `EXCLUDED_TESTS` in `testapp/settings.py` with a comment explaining why.
- If a failure is outside the scope of your PR, ask whether to fix it or exclude it β don't leave it failing silently.
- Always run the specific Django test modules affected by your change (e.g. `ordering`, `db_functions`, `composite_pk`) in addition to the unit tests (`python manage.py test testapp.tests`).
## Prompt References
Use prompt files via slash-style workspace paths:
- `/.github/prompts/mssql-django-pr-self-check-gate.prompt.md` - Gated PR self-check workflow and merge gate criteria.
- `/.github/prompts/mssql-django-dev-environment-setup.prompt.md` - Development environment setup.
- `/.github/prompts/mssql-django-run-unit-tests.prompt.md` - mssql-django unit test workflow.
- `/.github/prompts/mssql-django-run-django-test-suite.prompt.md` - Upstream Django suite workflow.
microsoft-mssql-django-8f2bd94/.github/prompts/ 0000775 0000000 0000000 00000000000 15215256560 0021613 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/prompts/mssql-django-dev-environment-setup.prompt.md 0000664 0000000 0000000 00000012572 15215256560 0032337 0 ustar 00root root 0000000 0000000 # mssql-django Development Environment Setup
This guide covers setting up a development environment for mssql-django, a Django database backend for Microsoft SQL Server.
## Quick Start
```bash
# 1. Install mssql-django in development mode
pip install -e ".[test]"
# 2. Start SQL Server (Docker)
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyPassword42" \
-p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest
# 3. Run mssql-django tests
python manage.py test --noinput
```
## Test Options
| Test Type | Tests | Time | Guide |
|-----------|-------|------|-------|
| mssql-django unit tests | ~42 | ~22s | [mssql-django-run-unit-tests.prompt.md](mssql-django-run-unit-tests.prompt.md) |
| Django full test suite | ~6200 | ~45min | [mssql-django-run-django-test-suite.prompt.md](mssql-django-run-django-test-suite.prompt.md) |
## Project Structure
```
mssql-django/
βββ mssql/ # Main backend code
β βββ base.py # DatabaseWrapper, connection management
β βββ compiler.py # Query compiler, SQL generation
β βββ schema.py # Schema editor, migrations
β βββ operations.py # Database operations, SQL functions
β βββ features.py # Backend feature flags
β βββ introspection.py # Database introspection
β βββ creation.py # Test database creation
βββ testapp/ # Test application
β βββ settings.py # Django settings, test exclusions
β βββ runners.py # Custom test runner
β βββ models.py # Test models
β βββ tests/ # mssql-django unit tests
βββ django/ # NOT in repo β cloned at runtime by test.sh
βββ test.sh # Script to run Django's full test suite
βββ tox.ini # Test matrix configuration
βββ azure-pipelines.yml # CI configuration
```
## Requirements
### System Requirements
- Python 3.8+ (3.12+ recommended; supports up to 3.14)
- SQL Server 2017, 2019, 2022, 2025 or Azure SQL DB / Managed Instance
- ODBC Driver 17 or 18 for SQL Server
### Python Dependencies
```bash
# Development install with test dependencies
pip install -e ".[test]"
# Core dependencies (installed automatically)
# - Django >= 3.2, < 6.1
# - pyodbc >= 3.0
# - pytz
```
## Configuration
### Database Settings (`testapp/settings.py`)
```python
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "default", # Database name
"USER": "sa", # SQL Server user
"PASSWORD": "MyPassword42", # Password
"HOST": "localhost", # Server host
"PORT": "1433", # Port
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"return_rows_bulk_insert": True,
"extra_params": "TrustServerCertificate=yes" # For self-signed certs
},
},
}
```
### Test Exclusions
Tests known to fail due to SQL Server limitations are excluded in `testapp/settings.py`:
```python
EXCLUDED_TESTS = [
# Tuple lookups - SQL Server doesn't support (col1, col2) IN syntax
'foreign_object.test_tuple_lookups.TupleLookupsTests.test_exact',
# ... see settings.py for full list
]
```
## Common Commands
```bash
# Install in development mode
pip install -e ".[test]"
# Run mssql-django tests only
python manage.py test --noinput
# Run Django's full test suite
bash test.sh
# Run specific Django test module
cd django && python tests/runtests.py --settings=testapp.settings composite_pk
# Check Python syntax
python -m py_compile mssql/compiler.py
# View generated SQL
python -c "
from myapp.models import MyModel
print(MyModel.objects.filter(...).query)
"
```
## SQL Server Limitations
Key limitations that affect the backend implementation:
| Limitation | Description | Workaround |
|------------|-------------|------------|
| No LIMIT clause | Must use TOP or OFFSET-FETCH | compiler.py handles this |
| OFFSET requires ORDER BY | Can't paginate without sorting | compiler.py adds default ORDER BY |
| No tuple IN | `(a, b) IN (...)` not supported | Tests excluded |
| No native boolean | Uses BIT type | Automatic conversion |
| Identifier quoting | Must use `[]` not `""` | operations.py quote_name() |
| ORDER BY duplicates | Same column can't appear twice | compiler.py deduplicates |
| ~2100 parameter limit | SQL Server max params per query | Temp table splitting in functions.py |
| No boolean in SELECT | `supports_boolean_expr_in_select_clause = False` | CASE WHEN wrapping |
## Debugging
### Enable SQL Logging
In `testapp/settings.py`:
```python
DEBUG = True # Enables SQL logging to logs/django_sql.log
```
### View Generated SQL
```python
from django.db import connection
qs = MyModel.objects.filter(...)
print(qs.query) # Shows SQL without parameters
print(connection.queries) # Shows executed queries with timing
```
## CI/CD
- **CI Platform:** Azure DevOps
- **Config:** `azure-pipelines.yml`
- **Test Matrix:** `tox.ini` (Python 3.8-3.14 Γ Django 3.2-6.0)
- **SQL Server:** Windows hosted agents with SQL Server 2019+
## Contributing
1. Create a feature branch
2. Make changes to `mssql/` files
3. Add tests to `testapp/tests/` if needed
4. Run `python manage.py test` to verify
5. For SQL changes, run `bash test.sh` for full validation
6. Submit PR against `dev` branch
microsoft-mssql-django-8f2bd94/.github/prompts/mssql-django-pr-self-check-gate.prompt.md 0000664 0000000 0000000 00000011246 15215256560 0031417 0 ustar 00root root 0000000 0000000 # mssql-django Gated PR Self-Check
Use this prompt before merging any backend/compiler/schema PR.
## Objective
Run a **merge gate** that prevents regressions from:
- contract ambiguity,
- double-escaping/double-transforms,
- fast-path branches bypassing shared safety logic,
- stale test exclusions,
- insufficient integration proof.
The output must be a clear **PASS / FAIL / BLOCKED** decision with evidence.
## Inputs
- PR branch name
- Target branch (usually `dev`)
- Changed files (`git diff --name-only ...HEAD`)
- Related Django test modules for changed areas
## Required Checks (in order)
### 1) Contract change declared
For every behavior-changing helper/symbol, declare one explicit contract:
- who returns raw values,
- who escapes/normalizes,
- where transformation happens,
- and whether call sites must change.
### 2) All call sites audited
Audit all consumers of changed symbols and verify:
- contract applied exactly once,
- no mixed old/new behavior,
- no hidden secondary escaping/transform.
### 3) Fast-path invariants preserved
If a fast-path exists (special-case `continue`/`return`/short-circuit), prove it does not bypass shared safety logic:
- ORDER BY dedupe,
- alias handling,
- parameter ordering,
- escaping rules,
- pagination/order requirements.
If it does bypass shared logic, fix by integrating with shared path, not by adding ad-hoc string post-processing.
### 4) Integration test proof
Provide end-to-end proof for each behavior change:
- Add local regression tests under `testapp/tests/` when applicable.
- Run upstream Django tests that exercise the same path.
- Include at least one regression that targets the **risky edge** (duplicate/equivalent path, alias path, mixed type path, etc.).
### 5) Doc/comments synced
Ensure comments and PR description match current behavior:
- remove stale βstill failingβ language if test now passes,
- add concise reasons for any remaining exclusions.
### 6) Exclusion hygiene (strict)
For any exclusion touched in `testapp/settings.py`:
- Verify candidate removals under **normal settings** (`testapp.settings`), not only fast profile.
- If using `settings_fast`, treat as exploratory only; confirm final decision with `testapp.settings`.
- Keep only exclusions that are proven failing due to true SQL Server limitation or out-of-scope known issue.
### 7) Version matrix evidence
Run targeted tests plus HOT guard matrix and report:
- PASS lanes,
- FAIL lanes,
- BLOCKED lanes with concrete environment reason.
## Merge Gate (must all be true)
- No unresolved contract ambiguity.
- No double-escaping / double-transform pattern in call sites.
- No fast-path branch bypassing shared invariants without explicit handling.
- Integration regression proof exists for each behavior change.
- Exclusion changes are validated under `testapp.settings`.
- Targeted tests green + HOT guard green (or BLOCKED with environment reason).
- PR description includes root cause, fix scope, and exclusions touched.
## Recommended Evidence Commands
```bash
# Diff scope
git --no-pager diff --name-status origin/dev...HEAD
git --no-pager diff --stat origin/dev...HEAD
# Local backend tests
python manage.py test testapp.tests --verbosity 2
# Targeted local module
python manage.py test testapp.tests.test_jsonfield --verbosity 2
# Upstream targeted test(s)
cd django
PYTHONPATH=/workspaces/mssql-django/django python tests/runtests.py --settings=testapp.settings
# HOT matrix / CI guard
# Run or verify the HOT matrix / CI guard workflow for this branch in your CI system
# and record its status (PASS / FAIL / BLOCKED) in the gate summary.
```
## Required Output Format
### Gate Summary
- Overall: PASS / FAIL / BLOCKED
- Scope: changed files + behavior areas
### Checklist Results
- Contract change declared: PASS/FAIL (+ evidence)
- Call-site audit: PASS/FAIL (+ evidence)
- Fast-path invariants: PASS/FAIL (+ evidence)
- Integration test proof: PASS/FAIL (+ tests run)
- Doc/comments sync: PASS/FAIL (+ note)
- Exclusion hygiene: PASS/FAIL (+ list kept/removed)
- Version matrix evidence: PASS/FAIL/BLOCKED (+ lanes)
### Exclusions Decision Table
For each touched exclusion:
- test id
- decision (keep/remove)
- reason
- proof command
- result
### Merge Recommendation
- Merge now / Needs fixes
- If fixes needed, list minimal required changes.
## Notes specific to mssql-django
- `testapp/runners.py` marks excluded tests as expected-failure (`x`) under normal settings. Do not treat `x` alone as proof of backend failure for exclusion decisions.
- For exclusion removal decisions, always re-run candidate tests directly under `testapp.settings` and inspect actual pass/fail outcomes.
- Prefer expression-level/compiler-level fixes over SQL string surgery.
microsoft-mssql-django-8f2bd94/.github/prompts/mssql-django-run-django-test-suite.prompt.md 0000664 0000000 0000000 00000014576 15215256560 0032237 0 ustar 00root root 0000000 0000000 # Running Django's Full Test Suite Against SQL Server
This guide covers running Django's comprehensive test suite (~6000+ tests) against SQL Server using mssql-django. This is what CI runs and takes 30-45 minutes.
## Prerequisites
### 1. SQL Server Database (Required)
```bash
# Start SQL Server 2022 in Docker
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyPassword42" \
-p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest
# Wait for SQL Server to fully initialize
sleep 25
# Verify it's running
docker logs sqlserver 2>&1 | tail -3
# Should show: "Recovery is complete" and "tempdb database has X data file(s)"
```
### 2. ODBC Driver (Required)
```bash
# Ubuntu 24.04 - Install ODBC Driver 18
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
echo "deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/ubuntu/24.04/prod noble main" | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev
```
### 3. System Dependencies (Required for Django test dependencies)
```bash
# libmemcached is needed for pylibmc (Django test dependency)
sudo apt-get install -y libmemcached-dev
```
### 4. Python Dependencies
```bash
# Install mssql-django in development mode
pip install -e .
# Install coverage (used by test.sh)
pip install coverage
```
### 5. Update Settings for ODBC Driver 18
If using ODBC Driver 18 (Ubuntu 24.04), update `testapp/settings.py`:
```python
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "default",
"USER": "sa",
"PASSWORD": "MyPassword42",
"HOST": "localhost",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"return_rows_bulk_insert": True,
"extra_params": "TrustServerCertificate=yes"
},
},
'other': {
"ENGINE": "mssql",
"NAME": "other",
"USER": "sa",
"PASSWORD": "MyPassword42",
"HOST": "localhost",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"return_rows_bulk_insert": True,
"extra_params": "TrustServerCertificate=yes"
},
},
}
```
### 6. Django Repository
The `test.sh` script expects a pre-existing Django clone in the `django/` directory. It uses `git fetch`, not `git clone`:
```bash
cd /workspaces/mssql-django
git clone --depth=1 https://github.com/django/django.git django
```
## Running the Full Test Suite
### Using test.sh (Recommended)
```bash
cd /workspaces/mssql-django
bash test.sh 2>&1 | tee test_output.log
```
This will:
1. Fetch tags and checkout the Django version matching your installed Django
2. Install Django's test requirements
3. Run ~100+ test modules against SQL Server
4. Generate coverage report
**Expected runtime:** 30-45 minutes
### Manual Execution
```bash
cd /workspaces/mssql-django/django
# Fetch Django tags and checkout matching version
DJANGO_VERSION="$(python -m django --version)"
git fetch --depth=1 origin +refs/tags/*:refs/tags/*
git checkout $DJANGO_VERSION
# Install Django test requirements
pip install -r tests/requirements/py3.txt
# Run tests
coverage run tests/runtests.py --settings=testapp.settings --noinput \
aggregation \
annotations \
basic \
composite_pk \
queries \
# ... add more test modules as needed
```
### Run Specific Test Modules
```bash
cd /workspaces/mssql-django/django
python tests/runtests.py --settings=testapp.settings --noinput composite_pk
```
### Run Specific Test
```bash
cd /workspaces/mssql-django/django
python tests/runtests.py --settings=testapp.settings --noinput \
composite_pk.test_filter.CompositePKFilterTests.test_explicit_subquery
```
## Understanding Test Output
Test result symbols:
- `.` = passed
- `x` = expected failure (test is known to fail on SQL Server)
- `s` = skipped (test excluded in settings.py)
- `E` = error
- `F` = failure
## Test Exclusions
Tests that are known to fail on SQL Server are excluded in `testapp/settings.py`:
```python
EXCLUDED_TESTS = [
# Tuple lookups - SQL Server doesn't support (col1, col2) IN syntax
'composite_pk.test_filter.CompositePKFilterTests.test_explicit_subquery',
'foreign_object.test_tuple_lookups.TupleLookupsTests.test_exact',
# ... many more
]
```
## Expected Results
From CI (Django 5.2, Python 3.13):
- **Total tests:** ~6200
- **Passed:** ~5400+
- **Skipped:** ~500+
- **Expected failures:** ~200+
- **Errors:** 0 (if code is working correctly)
## Cleanup
```bash
# Stop SQL Server
docker stop sqlserver && docker rm sqlserver
# Restore settings.py
git checkout testapp/settings.py
# Remove Django clone (optional)
rm -rf django/
```
## Troubleshooting
### "coverage: command not found"
```bash
pip install coverage
```
### "pylibmc build failed"
```bash
sudo apt-get install -y libmemcached-dev
```
### Tests hang or timeout
Check SQL Server is running:
```bash
docker ps | grep sqlserver
docker logs sqlserver | tail -10
```
### "An expression of non-boolean type specified in a context where a condition is expected"
This is the tuple lookup limitation. The test should be in `EXCLUDED_TESTS` in settings.py.
### "A column has been specified more than once in the order by list"
This is the ORDER BY duplicate column issue. If you see this, the deduplication fix in `mssql/compiler.py` may need adjustment.
## CI Configuration
The CI uses `tox` with matrix testing. See:
- `azure-pipelines.yml` - CI configuration
- `tox.ini` - Test matrix (Python versions Γ Django versions)
- `test.sh` - Test script that CI runs
## Test Modules Covered
The full list of Django test modules run by `test.sh`:
- aggregation, aggregation_regress
- annotations, backends, basic
- bulk_create, composite_pk, constraints
- custom_columns, custom_lookups, custom_managers
- custom_methods, custom_pk, datatypes
- dates, datetimes, db_functions
- defer, delete, expressions
- fixtures, foreign_object, get_or_create
- indexes, inspectdb, introspection
- lookup, m2m_*, many_to_one, many_to_many
- migrations, migrations2, model_fields
- ordering, pagination, prefetch_related
- queries, raw_query, schema
- select_for_update, select_related
- serializers, timezones, transactions
- update, update_only_fields
- ... and more (see test.sh for complete list)
microsoft-mssql-django-8f2bd94/.github/prompts/mssql-django-run-unit-tests.prompt.md 0000664 0000000 0000000 00000006050 15215256560 0030774 0 ustar 00root root 0000000 0000000 # Running mssql-django Unit Tests
This guide covers running the mssql-django package's own unit tests (42 tests across 11 test files).
## Prerequisites
### 1. SQL Server Database
You need a running SQL Server instance. Options:
#### Option A: Docker (Recommended for local development)
```bash
# Start SQL Server 2022 in Docker
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=MyPassword42" \
-p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest
# Wait for SQL Server to start (about 20 seconds)
sleep 20
# Verify it's running
docker logs sqlserver 2>&1 | tail -5
```
#### Option B: Use existing SQL Server
Update `testapp/settings.py` with your connection details.
### 2. ODBC Driver
Install Microsoft ODBC Driver for SQL Server:
```bash
# Ubuntu 24.04
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
echo "deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/ubuntu/24.04/prod noble main" | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev
```
**Note:** Ubuntu 24.04 only has ODBC Driver 18 available. The default `testapp/settings.py` uses Driver 17. You may need to update:
```python
# In testapp/settings.py, change:
"OPTIONS": {"driver": "ODBC Driver 17 for SQL Server", ...}
# To:
"OPTIONS": {"driver": "ODBC Driver 18 for SQL Server", "extra_params": "TrustServerCertificate=yes", ...}
```
### 3. Python Dependencies
```bash
# Install mssql-django in development mode with test dependencies
pip install -e ".[test]"
```
The `[test]` extra installs `unittest-xml-reporting` which provides the `xmlrunner` module required by the test runner.
**Warning:** Do NOT install the old `xmlrunner` package directly - it's incompatible with Python 3.12+.
## Running Tests
### Run all mssql-django tests
```bash
python manage.py test --noinput
```
Expected output: `Ran 42 tests in ~22s - OK`
### Run specific test module
```bash
python manage.py test testapp.tests.test_base -v 2
```
### Run specific test class
```bash
python manage.py test testapp.tests.test_base.TestEncodeValue -v 2
```
### Run specific test method
```bash
python manage.py test testapp.tests.test_base.TestEncodeValue.test_simple_value -v 2
```
## Test Structure
- Tests are in `testapp/tests/`
- Test runner: `testapp/runners.py` (ExcludedTestSuiteRunner)
- Settings: `testapp/settings.py`
## Cleanup
```bash
# Stop and remove SQL Server container
docker stop sqlserver && docker rm sqlserver
# Restore settings.py if modified
git checkout testapp/settings.py
```
## Troubleshooting
### "Can't open lib 'ODBC Driver 17 for SQL Server'"
Install ODBC Driver 18 and update settings.py (see Prerequisites section).
### "Login failed for user 'sa'"
Wait longer for SQL Server to start, or check the password matches settings.py.
### ModuleNotFoundError: No module named 'xmlrunner'
```bash
pip install unittest-xml-reporting
# Or: pip install -e ".[test]"
```
microsoft-mssql-django-8f2bd94/.github/scripts/ 0000775 0000000 0000000 00000000000 15215256560 0021576 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/scripts/parse_coverage.py 0000664 0000000 0000000 00000002662 15215256560 0025143 0 ustar 00root root 0000000 0000000 """Parse Cobertura coverage.xml and export metrics to GITHUB_ENV."""
import xml.etree.ElementTree as ET
import os
import re
import uuid
root = ET.parse("coverage.xml").getroot()
covered = root.get("lines-covered", "0")
total = root.get("lines-valid", "0")
rate = float(root.get("line-rate", "0"))
pct = f"{rate * 100:.2f}%"
print(f"Overall: {pct} ({covered}/{total} lines)")
env_file = os.environ.get("GITHUB_ENV", "/dev/null")
with open(env_file, "a") as env:
env.write(f"COVERAGE_PERCENTAGE={pct}\n")
env.write(f"COVERED_LINES={covered}\n")
env.write(f"TOTAL_LINES={total}\n")
# Regex to strip ADO agent workspace prefixes
agent_prefix_re = re.compile(
r"^(/mnt/vss/_work/\d+/s/|/home/vsts/work/\d+/s/|[A-Z]:\\\\.*?\\\\s\\\\|\\./)(.*)$"
)
files = []
for cls in root.iter("class"):
fname = cls.get("filename", cls.get("name", "unknown"))
match = agent_prefix_re.match(fname)
if match:
fname = match.group(2)
lr = float(cls.get("line-rate", "0"))
lines_elem = cls.find("lines")
line_count = len(lines_elem.findall("line")) if lines_elem is not None else 0
files.append((fname, lr * 100, line_count))
files.sort(key=lambda x: x[1])
low_cov = "\n".join(
f"- {f}: {p:.1f}% ({l} lines)" for f, p, l in files[:10]
)
print(f"\nLowest coverage files:\n{low_cov}")
delim = f"DELIM_{uuid.uuid4().hex}"
with open(env_file, "a") as env:
env.write(f"LOW_COVERAGE_FILES<<{delim}\n{low_cov}\n{delim}\n")
microsoft-mssql-django-8f2bd94/.github/workflows/ 0000775 0000000 0000000 00000000000 15215256560 0022144 5 ustar 00root root 0000000 0000000 microsoft-mssql-django-8f2bd94/.github/workflows/codeql-analysis.yml 0000664 0000000 0000000 00000004715 15215256560 0025766 0 ustar 00root root 0000000 0000000 # For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
# This workflow is triggered on pushes to the dev branch, pull requests targeting
permissions:
actions: read
contents: read
security-events: write
on:
push:
branches: [ dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ dev ]
schedule:
- cron: '40 13 * * 3'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# βΉοΈ Command-line programs to run using the OS shell.
# π https://git.io/JvXDl
# βοΈ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
microsoft-mssql-django-8f2bd94/.github/workflows/devskim.yml 0000664 0000000 0000000 00000001450 15215256560 0024331 0 ustar 00root root 0000000 0000000 # This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: DevSkim
on:
push:
branches: [ dev, master ]
pull_request:
branches: [ dev ]
schedule:
- cron: '29 14 * * 3'
jobs:
lint:
name: DevSkim
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run DevSkim scanner
uses: microsoft/DevSkim-Action@v1
- name: Upload DevSkim scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: devskim-results.sarif
microsoft-mssql-django-8f2bd94/.github/workflows/forked-pr-coverage.yml 0000664 0000000 0000000 00000007021 15215256560 0026351 0 ustar 00root root 0000000 0000000 name: Post Coverage Comment (Forked PRs)
# This workflow handles posting coverage comments for FORKED PRs.
#
# Why a separate workflow?
# - Forked PRs have restricted GITHUB_TOKEN permissions for security
# - They cannot write comments directly to the base repository's PRs
# - workflow_run triggers run in the BASE repository context with full permissions
# - This allows us to safely post comments on forked PRs
#
# Same-repo PRs post comments directly in pr-code-coverage.yml (faster)
# Forked PRs use this workflow (required for permissions)
on:
workflow_run:
workflows: ["PR Code Coverage"]
types:
- completed
jobs:
post-comment:
runs-on: ubuntu-latest
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Download coverage data
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if ! gh run download ${{ github.event.workflow_run.id }} \
--repo ${{ github.repository }} \
--name coverage-comment-data 2>&1; then
echo "β οΈ No coverage-comment-data artifact found"
echo "This is expected for same-repo PRs (they post comments directly)"
exit 0
fi
if [[ ! -f pr-info.json ]]; then
echo "β οΈ Artifact downloaded but pr-info.json not found"
exit 1
fi
- name: Read coverage data
id: coverage
run: |
if [[ ! -f pr-info.json ]]; then
echo "β pr-info.json not found"
exit 1
fi
cat pr-info.json
PR_NUMBER="$(jq -r '.pr_number' pr-info.json)"
COVERAGE_PCT="$(jq -r '.coverage_percentage' pr-info.json)"
COVERED_LINES="$(jq -r '.covered_lines' pr-info.json)"
TOTAL_LINES="$(jq -r '.total_lines' pr-info.json)"
PATCH_PCT="$(jq -r '.patch_coverage_pct' pr-info.json)"
LOW_COV_FILES="$(jq -r '.low_coverage_files' pr-info.json)"
PATCH_SUMMARY="$(jq -r '.patch_coverage_summary' pr-info.json)"
ADO_URL="$(jq -r '.ado_url' pr-info.json)"
echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_ENV
echo "COVERAGE_PERCENTAGE=${COVERAGE_PCT}" >> $GITHUB_ENV
echo "COVERED_LINES=${COVERED_LINES}" >> $GITHUB_ENV
echo "TOTAL_LINES=${TOTAL_LINES}" >> $GITHUB_ENV
echo "PATCH_COVERAGE_PCT=${PATCH_PCT}" >> $GITHUB_ENV
echo "ADO_URL=${ADO_URL}" >> $GITHUB_ENV
DELIM1="DELIM_$(uuidgen | tr -d '-')"
DELIM2="DELIM_$(uuidgen | tr -d '-')"
{
echo "LOW_COVERAGE_FILES<<${DELIM1}"
echo "$LOW_COV_FILES"
echo "${DELIM1}"
} >> $GITHUB_ENV
{
echo "PATCH_COVERAGE_SUMMARY<<${DELIM2}"
echo "$PATCH_SUMMARY"
echo "${DELIM2}"
} >> $GITHUB_ENV
- name: Comment coverage summary on PR
uses: ./.github/actions/post-coverage-comment
with:
pr_number: ${{ env.PR_NUMBER }}
coverage_percentage: ${{ env.COVERAGE_PERCENTAGE }}
covered_lines: ${{ env.COVERED_LINES }}
total_lines: ${{ env.TOTAL_LINES }}
patch_coverage_pct: ${{ env.PATCH_COVERAGE_PCT }}
low_coverage_files: ${{ env.LOW_COVERAGE_FILES }}
patch_coverage_summary: ${{ env.PATCH_COVERAGE_SUMMARY }}
ado_url: ${{ env.ADO_URL }}
microsoft-mssql-django-8f2bd94/.github/workflows/pr-code-coverage.yml 0000664 0000000 0000000 00000023313 15215256560 0026013 0 ustar 00root root 0000000 0000000 name: PR Code Coverage
on:
pull_request:
branches:
- dev
jobs:
coverage-report:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup git for diff-cover
run: |
git fetch origin dev:dev
echo "Available branches:"
git branch -a
git show-ref --verify refs/heads/dev || echo "Warning: dev branch not found"
- name: Wait for ADO build to start
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
PR_SHA=${{ github.event.pull_request.head.sha }}
API_URL="https://dev.azure.com/sqlclientdrivers/public/_apis/build/builds?definitions=2195&queryOrder=queueTimeDescending&%24top=30&api-version=7.1-preview.7"
echo "Waiting for Azure DevOps build to start for PR #$PR_NUMBER (SHA: $PR_SHA)..."
for i in {1..30}; do
echo "Attempt $i/30: Checking if build has started..."
API_RESPONSE=$(curl --fail --silent --show-error "$API_URL")
if ! echo "$API_RESPONSE" | jq . >/dev/null 2>&1; then
echo "β Invalid JSON response from Azure DevOps API"
echo "Response received: $API_RESPONSE"
exit 1
fi
# Match on both PR number and source SHA for accuracy
BUILD_INFO=$(echo "$API_RESPONSE" | jq -c --arg PR "$PR_NUMBER" --arg SHA "$PR_SHA" \
'[.value[]? | select(.triggerInfo["pr.number"]?==$PR and (.triggerInfo["pr.sourceSha"]?==$SHA or .sourceVersion?==$SHA))] | .[0] // empty' 2>/dev/null)
# Fall back to PR number only if SHA match fails (e.g. ADO hasn't updated triggerInfo yet)
if [[ -z "$BUILD_INFO" || "$BUILD_INFO" == "null" || "$BUILD_INFO" == "empty" ]]; then
BUILD_INFO=$(echo "$API_RESPONSE" | jq -c --arg PR "$PR_NUMBER" \
'[.value[]? | select(.triggerInfo["pr.number"]?==$PR)] | sort_by(.id) | reverse | .[0] // empty' 2>/dev/null)
fi
if [[ -n "$BUILD_INFO" && "$BUILD_INFO" != "null" && "$BUILD_INFO" != "empty" ]]; then
STATUS=$(echo "$BUILD_INFO" | jq -r '.status // "unknown"')
RESULT=$(echo "$BUILD_INFO" | jq -r '.result // "unknown"')
BUILD_ID=$(echo "$BUILD_INFO" | jq -r '.id // "unknown"')
WEB_URL=$(echo "$BUILD_INFO" | jq -r '._links.web.href // "unknown"')
echo "β
Found build: ID=$BUILD_ID, Status=$STATUS, Result=$RESULT"
echo "π Build URL: $WEB_URL"
echo "ADO_URL=$WEB_URL" >> $GITHUB_ENV
echo "BUILD_ID=$BUILD_ID" >> $GITHUB_ENV
if [[ "$STATUS" == "completed" && "$RESULT" == "failed" ]]; then
echo "β Azure DevOps build $BUILD_ID failed early"
exit 1
fi
echo "π Build has started, proceeding to poll for coverage artifacts..."
break
else
echo "β³ No build found for PR #$PR_NUMBER yet... (attempt $i/30)"
fi
if [[ $i -eq 30 ]]; then
echo "β Timeout: No build found for PR #$PR_NUMBER after 30 attempts"
exit 1
fi
sleep 10
done
- name: Download and parse coverage report
run: |
BUILD_ID=${{ env.BUILD_ID }}
ARTIFACTS_URL="https://dev.azure.com/sqlclientdrivers/public/_apis/build/builds/$BUILD_ID/artifacts?api-version=7.1-preview.5"
echo "π₯ Polling for coverage artifacts for build $BUILD_ID..."
COVERAGE_ARTIFACT=""
for i in {1..60}; do
echo "Attempt $i/60: Checking for coverage artifacts..."
ARTIFACTS_RESPONSE=$(curl --fail --silent --show-error "$ARTIFACTS_URL")
if ! echo "$ARTIFACTS_RESPONSE" | jq . >/dev/null 2>&1; then
echo "β οΈ Invalid JSON response from artifacts API (attempt $i/60)"
if [[ $i -eq 60 ]]; then
echo "β Persistent API issues after 60 attempts"
exit 1
fi
sleep 30
continue
fi
echo "π Available artifacts:"
echo "$ARTIFACTS_RESPONSE" | jq -r '.value[]?.name // "No artifacts found"'
COVERAGE_ARTIFACT=$(echo "$ARTIFACTS_RESPONSE" | jq -r '.value[]? | select(.name | test("Code Coverage Report")) | .resource.downloadUrl // empty' 2>/dev/null)
if [[ -n "$COVERAGE_ARTIFACT" && "$COVERAGE_ARTIFACT" != "null" && "$COVERAGE_ARTIFACT" != "empty" ]]; then
echo "β
Found coverage artifact on attempt $i!"
break
else
echo "β³ Coverage report not ready yet (attempt $i/60)..."
if [[ $i -eq 60 ]]; then
echo "β Timeout: Coverage report artifact not found after 60 attempts"
exit 1
fi
sleep 30
fi
done
echo "π Downloading coverage report..."
if ! curl -L "$COVERAGE_ARTIFACT" -o coverage-report.zip --fail --silent; then
echo "β Failed to download coverage report from Azure DevOps"
exit 1
fi
if ! unzip -o -q coverage-report.zip; then
echo "β Failed to extract coverage artifacts"
exit 1
fi
# Find coverage.xml (Cobertura format from coverage.py)
COVERAGE_FILE=$(find . -name "coverage.xml" -path "*/Code Coverage Report*" | head -1)
if [[ -z "$COVERAGE_FILE" ]]; then
COVERAGE_FILE=$(find . -name "*coverage*.xml" -type f | head -1)
fi
if [[ -z "$COVERAGE_FILE" ]]; then
echo "β No coverage XML file found in artifacts"
find . -type f | head -20
exit 1
fi
echo "β
Found coverage file: $COVERAGE_FILE"
cp "$COVERAGE_FILE" ./coverage.xml
# Parse Cobertura XML directly (much simpler than HTML parsing)
python3 .github/scripts/parse_coverage.py
echo "β
Coverage data extracted successfully"
- name: Generate patch coverage report
run: |
pip install diff-cover
if [[ ! -f coverage.xml ]]; then
echo "β coverage.xml not found"
exit 1
fi
echo "β
coverage.xml found, size: $(wc -c < coverage.xml) bytes"
# Generate diff coverage against dev branch
diff-cover coverage.xml \
--compare-branch=dev \
--json-report patch-coverage.json \
--markdown-report patch-coverage.md || {
echo "β οΈ diff-cover failed, continuing with empty patch coverage"
}
if [[ -f patch-coverage.json ]]; then
PATCH_COVERAGE=$(jq -r '.total_percent_covered // "N/A"' patch-coverage.json)
echo "β
Patch coverage: ${PATCH_COVERAGE}%"
echo "PATCH_COVERAGE_PCT=${PATCH_COVERAGE}%" >> $GITHUB_ENV
else
echo "PATCH_COVERAGE_PCT=N/A" >> $GITHUB_ENV
fi
if [[ -f patch-coverage.md ]]; then
DELIM="DELIM_$(uuidgen | tr -d '-')"
{
echo "PATCH_COVERAGE_SUMMARY<<${DELIM}"
cat patch-coverage.md
echo "${DELIM}"
} >> $GITHUB_ENV
else
echo "PATCH_COVERAGE_SUMMARY=Patch coverage report could not be generated." >> $GITHUB_ENV
fi
- name: Save coverage data for comment
run: |
mkdir -p coverage-comment-data
jq -n \
--arg pr_number "${{ github.event.pull_request.number }}" \
--arg coverage_percentage "${{ env.COVERAGE_PERCENTAGE }}" \
--arg covered_lines "${{ env.COVERED_LINES }}" \
--arg total_lines "${{ env.TOTAL_LINES }}" \
--arg patch_coverage_pct "${{ env.PATCH_COVERAGE_PCT }}" \
--arg low_coverage_files "$LOW_COVERAGE_FILES" \
--arg patch_coverage_summary "$PATCH_COVERAGE_SUMMARY" \
--arg ado_url "${{ env.ADO_URL }}" \
'{
pr_number: $pr_number,
coverage_percentage: $coverage_percentage,
covered_lines: $covered_lines,
total_lines: $total_lines,
patch_coverage_pct: $patch_coverage_pct,
low_coverage_files: $low_coverage_files,
patch_coverage_summary: $patch_coverage_summary,
ado_url: $ado_url
}' > coverage-comment-data/pr-info.json
echo "β
JSON validation:"
jq . coverage-comment-data/pr-info.json > /dev/null || {
echo "β Invalid JSON generated"
cat coverage-comment-data/pr-info.json
exit 1
}
cat coverage-comment-data/pr-info.json
- name: Upload coverage comment data
if: github.event.pull_request.head.repo.full_name != github.repository
uses: actions/upload-artifact@v4
with:
name: coverage-comment-data
path: coverage-comment-data/
retention-days: 7
- name: Comment coverage summary on PR
if: github.event.pull_request.head.repo.full_name == github.repository
uses: ./.github/actions/post-coverage-comment
with:
pr_number: ${{ github.event.pull_request.number }}
coverage_percentage: ${{ env.COVERAGE_PERCENTAGE }}
covered_lines: ${{ env.COVERED_LINES }}
total_lines: ${{ env.TOTAL_LINES }}
patch_coverage_pct: ${{ env.PATCH_COVERAGE_PCT }}
low_coverage_files: ${{ env.LOW_COVERAGE_FILES }}
patch_coverage_summary: ${{ env.PATCH_COVERAGE_SUMMARY }}
ado_url: ${{ env.ADO_URL }}
microsoft-mssql-django-8f2bd94/.gitignore 0000664 0000000 0000000 00000000211 15215256560 0020531 0 ustar 00root root 0000000 0000000 *.py[co]
*.sw[a-z]
*.orig
*~
.DS_Store
Thumbs.db
*.egg-info
*.dll
tests/local_settings.py
# Virtual Env
/venv/
.idea/
logs/
result.xml
microsoft-mssql-django-8f2bd94/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000000673 15215256560 0021354 0 ustar 00root root 0000000 0000000 # Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns microsoft-mssql-django-8f2bd94/CONTRIBUTING.md 0000664 0000000 0000000 00000003725 15215256560 0021007 0 ustar 00root root 0000000 0000000 # Contributing
## How to contribute
### Run unit tests
After changes made to the project, it's a good idea to run the unit tests before making a pull request.
1. **Run SQL Server**
Make sure you have SQL Server running in your local machine.
Download and install SQL Server [here](https://www.microsoft.com/en-us/sql-server/sql-server-downloads), or you could use docker. Change `testapp/settings.py` to match your SQL Server login username and password.
```
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Placeholder' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest
```
2. **Clone Django**
In `mssql-django` folder.
```
# Install your local mssql-django
pip install -e .
# The unit test suite are in `Django` folder, so we need to clone it
git clone https://github.com/django/django.git --depth 1
```
3. **Install Tox**
```
# we use `tox` to run tests and install dependencies
pip install tox
```
4. **Run Tox**
```
# eg. run django 3.1 tests with Python 3.7
tox -e py37-django31
```
---
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
microsoft-mssql-django-8f2bd94/CodeQL.yml 0000664 0000000 0000000 00000000053 15215256560 0020377 0 ustar 00root root 0000000 0000000 path_classifiers:
library:
- "django" microsoft-mssql-django-8f2bd94/LICENSE.txt 0000664 0000000 0000000 00000003211 15215256560 0020367 0 ustar 00root root 0000000 0000000 Project Name: mssql-django
BSD 3-Clause License
Copyright (c) 2021, Microsoft Corporation
2019, ES Solutions AB
2018, Michiya Takahashi
2008, 2009 django-pyodbc developers
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
microsoft-mssql-django-8f2bd94/MANIFEST.in 0000664 0000000 0000000 00000000162 15215256560 0020304 0 ustar 00root root 0000000 0000000 include LICENSE.txt
include MANIFEST.in
include README.md
recursive-include mssql *.py
recursive-exclude docker *
microsoft-mssql-django-8f2bd94/NOTICE.md 0000664 0000000 0000000 00000003377 15215256560 0020064 0 ustar 00root root 0000000 0000000 # Notices
This repository incorporates material as listed below or described in the code.
## django-mssql-backend
Please see below for the associated license for the incorporated material from django-mssql-backend (https://github.com/ESSolutions/django-mssql-backend).
### BSD 3-Clause License
Copyright (c) 2019, ES Solutions AB
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
microsoft-mssql-django-8f2bd94/README.md 0000664 0000000 0000000 00000017141 15215256560 0020032 0 ustar 00root root 0000000 0000000 # Django Backend for Microsoft SQL
mssql-django is the official Microsoftβsupported Django database backend for SQL Server, Azure SQL and SQL Database in Microsoft Fabric.
It provides a reliable, enterpriseβgrade database connectivity option for the Django web framework, enabling Python developers to build and run productionβready applications on Microsoftβs data platform.
This project is the continuation and evolution of earlier community efforts, and it builds on the strong foundation established by django-mssql-backend and its predecessors. mssql-django focuses on longβterm stability, performance, security, and compatibility with both Django and SQL Server.
## Supportability
| Component | Supported Versions |
|---|---|
| Django | 3.2, 4.0, 4.1, 4.2, 5.0, 5.1, 5.2, 6.0 |
| Python | 3.8 β 3.14 (Django 6.0 requires 3.12+) |
| SQL Server | 2016, 2017, 2019, 2022, 2025 |
| Azure SQL | Database, Managed Instance, SQL Database in Microsoft Fabric |
| ODBC Driver | Microsoft ODBC Driver 17 or 18 for SQL Server |
| FreeTDS | Supported via FreeTDS ODBC driver |
## Quick Start
1. Install mssql-django (pulls in Django, pyodbc, and pytz automatically):
pip install mssql-django
2. Configure your `settings.py`:
```python
DATABASES = {
'default': {
'ENGINE': 'mssql',
'NAME': 'mydb',
'USER': 'user@myserver',
'PASSWORD': 'password',
'HOST': 'myserver.database.windows.net',
'PORT': '',
'OPTIONS': {
'driver': 'ODBC Driver 18 for SQL Server',
},
},
}
# set this to False if you want to turn off pyodbc's connection pooling
DATABASE_CONNECTION_POOLING = False
```
## Configuration Reference
### Standard Django Settings
| Setting | Type | Description |
|---|---|---|
| `ENGINE` | String | Must be `"mssql"` |
| `NAME` | String | Database name. Required. |
| `HOST` | String | SQL Server instance in `"server\instance"` format |
| `PORT` | String | Server instance port. Empty string means default port. |
| `USER` | String | Database user name. If not given, MS Integrated Security is used. |
| `PASSWORD` | String | Database user password |
| `TOKEN` | String | Access token for Azure AD auth (e.g. via `azure.identity`) |
| `AUTOCOMMIT` | Boolean | Set to `False` to disable Django's transaction management |
| `Trusted_Connection` | String | Default `"yes"`. Set to `"no"` if required. |
### TEST Settings
| Setting | Type | Description |
|---|---|---|
| `NAME` | String | Test database name. Default: `"test_" + NAME` |
| `COLLATION` | String | Collation for test database. Default: instance default. |
| `DEPENDENCIES` | String | Creation-order dependencies of the database |
| `MIRROR` | String | Alias of database to mirror during testing |
### OPTIONS
| Option | Type | Default | Description |
|---|---|---|---|
| `driver` | String | `"ODBC Driver 18 for SQL Server"` | ODBC driver to use. Auto-falls back to Driver 17 if 18 is not installed. |
| `isolation_level` | String | `None` | [Transaction isolation level](https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql): `READ UNCOMMITTED`, `READ COMMITTED`, `REPEATABLE READ`, `SNAPSHOT`, or `SERIALIZABLE` |
| `dsn` | String | β | Named DSN, can be used instead of `HOST` |
| `host_is_server` | Boolean | `False` | Set to `True` to use `HOST`/`PORT` directly with FreeTDS instead of a `freetds.conf` dataserver name. [Details](https://www.freetds.org/userguide/dsnless.html) |
| `unicode_results` | Boolean | `False` | Activate pyodbc's unicode\_results feature |
| `extra_params` | String | β | Additional ODBC params (`"param=value;param=value"`). Use for [Azure AD Authentication](https://github.com/microsoft/mssql-django/wiki/Azure-AD-Authentication). |
| `collation` | String | `None` | Collation for text field lookups (e.g. `"Chinese_PRC_CI_AS"`) |
| `connection_timeout` | Integer | `0` | Connection timeout in seconds (`0` = disabled) |
| `connection_retries` | Integer | `5` | Number of connection retry attempts |
| `connection_retry_backoff_time` | Integer | `5` | Back-off time in seconds between retries |
| `query_timeout` | Integer | `0` | Query timeout in seconds (`0` = disabled) |
| `setencoding` / `setdecoding` | List | β | pyodbc [encoding](https://github.com/mkleehammer/pyodbc/wiki/Connection#setencoding) / [decoding](https://github.com/mkleehammer/pyodbc/wiki/Connection#setdecoding) config |
| `return_rows_bulk_insert` | Boolean | `False` | Allow returning rows from bulk insert. Must be `False` if tables have triggers. |
### Backend-Specific Settings
| Setting | Type | Default | Description |
|---|---|---|---|
| `DATABASE_CONNECTION_POOLING` | Boolean | `True` | Set to `False` to disable pyodbc's connection pooling |
## Known Limitations
The following limitations apply when using SQL Server with Django:
- Altering a model field from or to AutoField at migration
- Floating point arithmetic in some annotate functions
- Annotate/exists function in `order_by`
- Righthand power and arithmetic with datetimes
- Timezones and timedeltas not fully supported
- Rename field/model with foreign key constraint
- Database level constraints and filtered indexes
- Date extract function
- Bulk insert with triggers and returning rows
### Version-Specific Notes
| Version | Notes |
|---|---|
| Django 5.1 | Minor limitations with composite primary key inspection via `inspectdb` |
| Django 5.2 | Tuple lookups require Django 5.2.4+ for full support. Some JSONField bulk/CASE WHEN update edge cases. See [test exclusions](https://github.com/microsoft/mssql-django/blob/dev/testapp/settings.py) for details. |
| Django 6.0 | Requires Python 3.12+. All 5.2 limitations apply. Backend handles all 6.0 API changes transparently. |
JSONField lookups have additional limitations β see the [JSONField wiki page](https://github.com/microsoft/mssql-django/wiki/JSONField).
## Helpful Links
| Resource | Link |
|---|---|
| Wiki & Guides | [mssql-django Wiki](https://github.com/microsoft/mssql-django/wiki) |
| Contributing | [Contributing Guide](https://github.com/microsoft/mssql-django/blob/dev/CONTRIBUTING.md) |
| Code of Conduct | [Microsoft Open Source Code of Conduct](https://github.com/microsoft/mssql-django/blob/dev/CODE_OF_CONDUCT.md) |
## Still have questions?
Check the [FAQ](https://github.com/microsoft/mssql-django/wiki/Frequently-Asked-Questions) or [open an issue](https://github.com/microsoft/mssql-django/issues/new) on GitHub.
## Contributing
We welcome contributions and suggestions! See [CONTRIBUTING.md](https://github.com/microsoft/mssql-django/blob/dev/CONTRIBUTING.md) for details.
All contributors are listed on GitHub: [Contributor Insights](https://github.com/microsoft/mssql-django/graphs/contributors)
Most contributions require a Contributor License Agreement (CLA). For details, visit https://cla.opensource.microsoft.com. A CLA bot will guide you when you submit a pull request.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
## Security
For security reporting instructions please refer to [`SECURITY.md`](https://github.com/microsoft/mssql-django/blob/dev/SECURITY.md).
## Trademarks
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.
microsoft-mssql-django-8f2bd94/SECURITY.md 0000664 0000000 0000000 00000005250 15215256560 0020342 0 ustar 00root root 0000000 0000000 # Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).