Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2e36608
ci(sqlserver): test against the core feature branch
vistart Sep 19, 2026
d9b38ef
feat(sqlserver): add SQLServerColumnDefinition and typed column options
vistart Sep 20, 2026
f20ca09
feat(sqlserver): add SQLServerCreateTableOptions and read typed options
vistart Sep 20, 2026
5909b46
test(sqlserver): migrate memory-optimized tests to SQLServerCreateTab…
vistart Sep 20, 2026
7b3cb3d
refactor(sqlserver): add SQLServerIndexDefinition with typed hash ind…
vistart Sep 20, 2026
674294e
refactor(sqlserver): typed ALTER COLUMN options and graph table expre…
vistart Sep 20, 2026
e11ba8d
refactor(sqlserver): typed MERGE/SELECT INTO/partition scheme
vistart Sep 20, 2026
8211776
fix(sqlserver): explicit signature for SQLServerSelectIntoExpression …
vistart Sep 20, 2026
9170019
chore(sqlserver): import BaseExpression under TYPE_CHECKING for annot…
vistart Sep 20, 2026
cc05c1b
refactor(sqlserver): drop inherited Firebird clause params from creat…
vistart Sep 20, 2026
874c902
refactor(sqlserver): drop reserved dialect_options from partition cla…
vistart Sep 20, 2026
d3144f4
refactor(sqlserver): drop dialect_options from data-type value objects
vistart Sep 20, 2026
ea2501b
fix(sqlserver): gate CREATE VIEW WITH CHECK OPTION on supports_view_c…
vistart Sep 20, 2026
3b3a615
test(sqlserver): pin generated-column capability bits
vistart Sep 20, 2026
75e0cde
refactor(sqlserver): remove dead format_cte method
vistart Sep 20, 2026
ee73581
docs(sqlserver): purge stale dialect_options references
vistart Sep 20, 2026
d396a8b
fix(sqlserver): wire SQLServerDatabaseMixin into the dialect
vistart Sep 20, 2026
d802f1b
docs(sqlserver): drop empty dialect_options from examples
vistart Sep 20, 2026
295fe0e
test(sqlserver): use SQLServerDialect directly (database mixin now wi…
vistart Sep 20, 2026
6382a54
refactor(ddl): drop legacy identity fields from column classes
vistart Sep 21, 2026
3da76a4
feat(ddl): render column attributes; backend identity syntax
vistart Sep 21, 2026
a76d3b4
test(ddl): classify ColumnAttributeSupport; use deriver.creation_plan()
vistart Sep 21, 2026
06e5011
fix(sqlserver): raise on declared table/column comments instead of si…
vistart Sep 23, 2026
9b7c3b0
test(ddl): classify CommentSupport for SQL Server conformance
vistart Sep 23, 2026
5b5e4b5
fix(ddl): stop silently dropping declared DDL options
vistart Sep 23, 2026
53b3c92
feat(sqlserver): add type DDL support
vistart Sep 24, 2026
df6dc7d
fix(ddl): reject unsupported table declarations
vistart Sep 24, 2026
b0dc197
test(ddl): cover table inheritance and tablespace
vistart Sep 24, 2026
aff46e7
test(sqlserver): use supported memory type version
vistart Sep 24, 2026
8e5584e
chore(sqlserver): align pull request template
vistart Sep 24, 2026
712ec08
refactor(sqlserver): use direct DDL expressions
vistart Sep 25, 2026
0045300
docs: document repository search scope
vistart Sep 25, 2026
8ac73c1
test(ddl): cover DDLSource collection
vistart Sep 25, 2026
0fc3cc6
fix(backend): repair unresolvable TYPE_CHECKING imports
vistart Sep 27, 2026
92d8597
chore(test): register the pytest markers the suite already uses
vistart Sep 27, 2026
28351e7
fix(scripts): stop the pre-commit hook from blocking commits on older…
vistart Sep 27, 2026
ff98cf0
ci: install core and testsuite from release branches
vistart Sep 27, 2026
339ea11
chore: add changelog fragment for PR #4
vistart Sep 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions .github/PULL_REQUEST_TEMPLATE/feature_template.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
name: "Feature Pull Request"
about: Propose a new feature for the rhosocial-activerecord ecosystem, targeting a pre-release branch (e.g., release/vX.Y.Z).
about: Propose a new feature for the rhosocial-activerecord SQL Server backend, targeting a pre-release branch (e.g., release/vX.Y.Z).
title: "feat(<scope>): <description>"
labels: "feature"
labels: "enhancement"
assignees: ""
---

Expand Down Expand Up @@ -40,18 +40,22 @@ Does this PR introduce a breaking change?
- If NO, please indicate N/A.
-->

- [ ] Yes
- [ ] No
- [ ] Yes, for end-users (backward-incompatible API changes)
- [ ] Yes, for backend developers (internal architectural changes that may affect custom implementations)
- [ ] No breaking changes
(If Yes, please describe the impact and migration path below):

**Applicable `rhosocial-activerecord` Version Range:**
<!-- Specify the version range of rhosocial-activerecord that this change is compatible with (e.g., ">=1.0.0,<2.0.0"). -->
**Impact on End-Users:**
<!-- Describe backward-incompatible changes for typical end-user applications consuming the public API. If none, state "No backward-incompatible changes are expected for typical end-user applications." -->

**Impact on Backend Developers (Custom Implementations):**
<!-- Describe backward-incompatible changes for developers with custom backend implementations or those directly interacting with internal mechanisms. If none, state "No backward-incompatible changes are expected for backend developers using custom implementations." -->


## Related Repositories/Packages

<!--
If this change affects other repositories in the rhosocial-activerecord ecosystem (e.g., testsuite, mysql, postgres),
If this change affects other repositories in the rhosocial-activerecord ecosystem (e.g., core, testsuite, or another backend),
please list them and describe the coordinated changes needed.
-->

Expand Down Expand Up @@ -79,12 +83,12 @@ Go over all the following points, and put an `x` in all the boxes that apply.
If you're unsure about any of these, don't hesitate to ask. We're here to help!
-->

- [ ] My code follows the project's code style guidelines.
- [ ] My code follows the project's code style guidelines in `.claude/code_style.md`.
- [ ] I have performed a self-review of my own code.
- [ ] I have commented my code, particularly in hard-to-understand areas.
- [ ] I have made corresponding changes to the documentation (Docstrings, `README.md`, etc.).
- [ ] My changes generate no new warnings.
- [ ] I have added a Changelog fragment (`changelog.d/<issue_number>.<type>.md`).
- [ ] I have added a Changelog fragment as described in `.claude/version_control.md` (`changelog.d/<issue_number>.<type>.md`).
- [ ] I have verified that my changes do not introduce SQL injection vulnerabilities.
- [ ] I have checked for potential performance regressions.

Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 63 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTo&open=AaDibnYO8CGZ-BmI6sTo&pullRequest=4

Check warning on line 63 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTp&open=AaDibnYO8CGZ-BmI6sTp&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -150,7 +150,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 153 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTq&open=AaDibnYO8CGZ-BmI6sTq&pullRequest=4

Check warning on line 153 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTr&open=AaDibnYO8CGZ-BmI6sTr&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -240,7 +240,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 243 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTs&open=AaDibnYO8CGZ-BmI6sTs&pullRequest=4

Check warning on line 243 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTt&open=AaDibnYO8CGZ-BmI6sTt&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -330,7 +330,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 333 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTv&open=AaDibnYO8CGZ-BmI6sTv&pullRequest=4

Check warning on line 333 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTu&open=AaDibnYO8CGZ-BmI6sTu&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -420,7 +420,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 423 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTx&open=AaDibnYO8CGZ-BmI6sTx&pullRequest=4

Check warning on line 423 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTw&open=AaDibnYO8CGZ-BmI6sTw&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -510,7 +510,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 513 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTz&open=AaDibnYO8CGZ-BmI6sTz&pullRequest=4

Check warning on line 513 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sTy&open=AaDibnYO8CGZ-BmI6sTy&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -601,7 +601,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 604 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sT1&open=AaDibnYO8CGZ-BmI6sT1&pullRequest=4

Check warning on line 604 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sT0&open=AaDibnYO8CGZ-BmI6sT0&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -691,7 +691,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 694 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sT3&open=AaDibnYO8CGZ-BmI6sT3&pullRequest=4

Check warning on line 694 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sT2&open=AaDibnYO8CGZ-BmI6sT2&pullRequest=4

- name: Create test database
run: |
Expand Down Expand Up @@ -790,7 +790,7 @@
- name: Install activerecord and testsuite from PyPI
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/activerecord-derived-ddl"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

Check warning on line 793 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Using dependencies without locking resolved versions is security-sensitive.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sT5&open=AaDibnYO8CGZ-BmI6sT5&pullRequest=4

Check warning on line 793 in .github/workflows/test.yml

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Omitting "--only-binary :all:" can lead to the execution of setup scripts. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnYO8CGZ-BmI6sT4&open=AaDibnYO8CGZ-BmI6sT4&pullRequest=4

- name: Create test database
run: |
Expand Down
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ This project is in early development. Key features being implemented:
## Version Control and Changelog

This project adheres to the same version control, branching, commit message, and changelog management standards as the main `python-activerecord` project.

## Search Scope

- Use `rg` for repository searches; never use `grep`.
- Limit searches to this `python-activerecord` repository and its related testsuite/backend directories.
- Exclude `.git/`, `.venv*/`, `__pycache__/`, `build/`, `dist/`, and other cache directories.
1 change: 1 addition & 0 deletions changelog.d/4.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adapt the SQL Server backend to derived DDL with typed options: `SQLServerColumnDefinition`, `SQLServerCreateTableOptions`, `SQLServerIndexDefinition` with typed hash-index fields, typed `ALTER COLUMN` options, a graph table expression, and typed `MERGE` / `SELECT INTO` / partition scheme. Add type DDL support, classify `CommentSupport` and `ColumnAttributeSupport` for conformance, and cover `DDLSource` collection, table inheritance, tablespace and inline-index rendering.
1 change: 1 addition & 0 deletions changelog.d/4.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Stop silently discarding declared DDL in the SQL Server backend: a declared table or column comment now raises instead of being dropped, declared DDL options are no longer discarded, unsupported table declarations are rejected rather than omitted, and `CREATE VIEW ... WITH CHECK OPTION` is gated on `supports_view_check_option`.
1 change: 1 addition & 0 deletions changelog.d/4.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Install core and testsuite from release branches in CI instead of the derived-DDL feature branch, repair TYPE_CHECKING imports broken by the expression namespace split, register the pytest markers the suite already uses, and stop the pre-commit hook from blocking commits on revisions that predate `scripts/preflight.sh`.
1 change: 1 addition & 0 deletions changelog.d/4.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove the reserved `dialect_options` bag from data-type value objects and partition clauses, the legacy identity fields on column classes, the Firebird clause parameters inherited by the SQL Server create-table subclass, and the dead `format_cte` method.
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ markers = [
"requires_capability: marks tests requiring specific backend capabilities",
"requires_protocol: marks tests requiring specific backend protocol support",
"requires_inner_join: marks tests requiring INNER JOIN support",
"feature: category label for feature-area tests; changes collection grouping only, not ordering",
"benchmark_relation: marks relation benchmarks; changes collection grouping only, not ordering",

]

[tool.coverage.run]
Expand Down
31 changes: 26 additions & 5 deletions scripts/install-git-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,42 @@
# Installs an optional pre-commit hook that runs scripts/preflight.sh so a
# broken import/lint is caught before the commit (and before a CI round-trip).
# Bypass a single commit with: git commit --no-verify
#
# Re-run this after pulling, and re-run it from the repository root. To remove
# the hook, delete .git/hooks/pre-commit (or the core.hooksPath directory).
set -euo pipefail

cd "$(dirname "$0")/.."

HOOK=".git/hooks/pre-commit"
if [ ! -d .git/hooks ]; then
echo "install-git-hooks: .git/hooks not found (not a git repo?)" >&2
exit 2
# git ignores .git/hooks entirely once core.hooksPath is set, so a hook written
# there would never run while this script still reported success.
HOOKS_PATH="$(git config core.hooksPath || true)"
if [ -n "$HOOKS_PATH" ]; then

Check failure on line 17 in scripts/install-git-hooks.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=rhosocial_python-activerecord-sqlserver&issues=AaDibnZg8CGZ-BmI6sT6&open=AaDibnZg8CGZ-BmI6sT6&pullRequest=4
echo "install-git-hooks: core.hooksPath is set to '$HOOKS_PATH'." >&2
echo "install-git-hooks: .git/hooks is ignored by git; writing the hook to" >&2
echo " '$HOOKS_PATH/pre-commit' instead." >&2
HOOK="$HOOKS_PATH/pre-commit"
mkdir -p "$HOOKS_PATH"
else
HOOK=".git/hooks/pre-commit"
if [ ! -d .git/hooks ]; then
echo "install-git-hooks: .git/hooks not found (not a git repo?)" >&2
exit 2
fi
fi

cat > "$HOOK" <<'HOOK_BODY'
#!/usr/bin/env bash
# Installed by scripts/install-git-hooks.sh — runs the local pre-flight.
# Skip with: git commit --no-verify
exec "$(git rev-parse --show-toplevel)/scripts/preflight.sh"
#
# The guard below matters on older revisions: this hook is a local, untracked
# artifact, so it survives a checkout of a commit that predates
# scripts/preflight.sh. Without the guard, exec fails with a bare
# "No such file or directory" and blocks the commit with nothing to act on.
PREFLIGHT="$(git rev-parse --show-toplevel)/scripts/preflight.sh"
[ -x "$PREFLIGHT" ] || exit 0
exec "$PREFLIGHT"
HOOK_BODY
chmod +x "$HOOK"

Expand Down
16 changes: 16 additions & 0 deletions src/rhosocial/activerecord/backend/impl/sqlserver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
SQLServerTryConvertExpression,
SQLServerContainsPredicate,
SQLServerFreetextPredicate,
SQLServerTypeNullability,
SQLServerAliasTypeDefinition,
SQLServerTableTypeDefinition,
SQLServerClrTypeDefinition,
SQLServerDropTypeExpression,
SQLServerRenameTypeExpression,
)

from .expression.types import (
Expand All @@ -54,7 +60,9 @@
SQLServerBackendMixin,
SQLServerConcurrencyMixin,
SQLServerTypeSupportMixin,
SQLServerTypeDDLMixin,
)
from .protocols import SQLServerUserDefinedTypeSupport

from .schema import SQLServerSchemaDiffer

Expand Down Expand Up @@ -96,6 +104,12 @@
"SQLServerTryConvertExpression",
"SQLServerContainsPredicate",
"SQLServerFreetextPredicate",
"SQLServerTypeNullability",
"SQLServerAliasTypeDefinition",
"SQLServerTableTypeDefinition",
"SQLServerClrTypeDefinition",
"SQLServerDropTypeExpression",
"SQLServerRenameTypeExpression",
# DDL DataType subclasses
"SQLServerNVarCharType",
"SQLServerNCharType",
Expand All @@ -110,6 +124,8 @@
"SQLServerBackendMixin",
"SQLServerConcurrencyMixin",
"SQLServerTypeSupportMixin",
"SQLServerTypeDDLMixin",
"SQLServerUserDefinedTypeSupport",
# Schema differ
"SQLServerSchemaDiffer",
# Type compatibility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def format_alter_column_action(self, action: Any) -> Tuple[str, tuple]:
standard SET/DROP subclauses. The ``operation`` value selects the
variant:

- ``SET DATA TYPE`` (or ``dialect_options["data_type"]``) renders the
- ``SET DATA TYPE`` (or a typed ``data_type`` field) renders the
T-SQL ``ALTER COLUMN col type [COLLATE ...] [NULL | NOT NULL] [SPARSE]``
form via ``format_alter_column_type_action``.
- ``ADD MASKED`` renders dynamic data masking via
Expand All @@ -81,20 +81,19 @@ def format_alter_column_action(self, action: Any) -> Tuple[str, tuple]:
"""
operation = action.operation
op_str = operation.value if hasattr(operation, "value") else str(operation)
dialect_options = getattr(action, "dialect_options", None) or {}

if op_str == "ADD MASKED" or "masked_function" in dialect_options:
if op_str == "ADD MASKED" or getattr(action, "masked_function", None) is not None:
return self.format_add_masked_action(action)
if op_str == "DROP MASKED" or dialect_options.get("drop_masked"):
if op_str == "DROP MASKED" or getattr(action, "drop_masked", False):
return self.format_drop_masked_action(action)
if op_str == "SET DATA TYPE" or "data_type" in dialect_options:
if op_str == "SET DATA TYPE" or getattr(action, "data_type", None) is not None:
return self.format_alter_column_type_action(action)

raise UnsupportedFeatureError(
self.name,
f"ALTER COLUMN {op_str}",
"SQL Server requires re-specifying the full column. Use "
"operation='SET DATA TYPE' with dialect_options to add "
"operation='SET DATA TYPE' with a SQLServerAlterColumn to add "
"NULL/NOT NULL, COLLATE, SPARSE, or MASKED.",
)

Expand All @@ -105,12 +104,11 @@ def format_alter_column_type_action(self, action: Any) -> Tuple[str, tuple]:
ALTER COLUMN column data_type [COLLATE collation]
[NULL | NOT NULL] [SPARSE]

The data type comes from ``dialect_options["data_type"]`` or the
The data type comes from the typed ``data_type`` field or the
action's ``new_value``. ``not_null``, ``collate``, and ``sparse``
are carried in ``dialect_options``.
are typed fields on ``SQLServerAlterColumn``.
"""
dialect_options = getattr(action, "dialect_options", None) or {}
data_type = dialect_options.get("data_type") or action.new_value
data_type = getattr(action, "data_type", None) or action.new_value
if data_type is None:
raise ValueError("data type is required for ALTER COLUMN")

Expand All @@ -120,15 +118,15 @@ def format_alter_column_type_action(self, action: Any) -> Tuple[str, tuple]:
str(data_type),
]

collate = dialect_options.get("collate")
collate = getattr(action, "collate", None)
if collate:
parts.append(f"COLLATE {collate}")

not_null = dialect_options.get("not_null")
not_null = getattr(action, "not_null", None)
if not_null is not None:
parts.append("NOT NULL" if not_null else "NULL")

if dialect_options.get("sparse"):
if getattr(action, "sparse", False):
if self.version < _SQL_SERVER_SPARSE_COLUMN_VERSION: # type: ignore[attr-defined]
raise UnsupportedFeatureError(
self.name,
Expand All @@ -145,7 +143,7 @@ def format_add_masked_action(self, action: Any) -> Tuple[str, tuple]:
SQL Syntax:
ALTER COLUMN column ADD MASKED WITH (FUNCTION = 'mask_function')

The mask function is carried in ``dialect_options["masked_function"]``
The mask function is carried in the typed ``masked_function`` field
or the action's ``new_value``.
"""
if self.version < _SQL_SERVER_MASKED_COLUMN_VERSION: # type: ignore[attr-defined]
Expand All @@ -155,8 +153,7 @@ def format_add_masked_action(self, action: Any) -> Tuple[str, tuple]:
suggestion="requires SQL Server 2016+.",
)

dialect_options = getattr(action, "dialect_options", None) or {}
function = dialect_options.get("masked_function") or action.new_value
function = getattr(action, "masked_function", None) or action.new_value
if function is None:
raise ValueError("masked_function is required for ADD MASKED")

Expand Down
Loading
Loading