coop-schema-compare 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coop_schema_compare-0.1.0/LICENSE +21 -0
- coop_schema_compare-0.1.0/PKG-INFO +178 -0
- coop_schema_compare-0.1.0/README.md +139 -0
- coop_schema_compare-0.1.0/pyproject.toml +29 -0
- coop_schema_compare-0.1.0/setup.cfg +4 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/__init__.py +3 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/catalog.py +331 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/cli.py +238 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/connect.py +125 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/diff.py +107 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/fabric.py +119 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/script.py +199 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare/source.py +328 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare.egg-info/PKG-INFO +178 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare.egg-info/SOURCES.txt +18 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare.egg-info/dependency_links.txt +1 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare.egg-info/entry_points.txt +2 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare.egg-info/requires.txt +1 -0
- coop_schema_compare-0.1.0/src/coop_schema_compare.egg-info/top_level.txt +1 -0
- coop_schema_compare-0.1.0/tests/test_compare.py +513 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cooptimize / Aaron Jennings
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: coop-schema-compare
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deterministic schema compare between SQL environments (Fabric Warehouse, Azure SQL) with an ordered promotion script. Reads only; applies nothing.
|
|
5
|
+
Author: Cooptimize
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Cooptimize / Aaron Jennings
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/kabukisensei/coop-schema-compare
|
|
29
|
+
Keywords: fabric,warehouse,azure-sql,schema,compare,deployment
|
|
30
|
+
Classifier: Programming Language :: Python :: 3
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Operating System :: OS Independent
|
|
33
|
+
Classifier: Topic :: Database
|
|
34
|
+
Requires-Python: >=3.10
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
License-File: LICENSE
|
|
37
|
+
Requires-Dist: pyodbc>=5.0
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# coop-schema-compare
|
|
41
|
+
|
|
42
|
+
Deterministic schema compare between two SQL schemas, live or as code, with an
|
|
43
|
+
ordered promotion script. Built for Microsoft Fabric Warehouse, where the
|
|
44
|
+
built-in deployment pipeline gives you no script to read; it works the same on
|
|
45
|
+
Azure SQL Database, Fabric SQL database and SQL Server. A side is a live
|
|
46
|
+
database (by SQL endpoint or by Fabric workspace and warehouse name), a
|
|
47
|
+
committed snapshot, or a repo folder of `.sql` files, in any pairing: repo
|
|
48
|
+
against repo, live against live, repo against live. It **reads only and applies
|
|
49
|
+
nothing**: the output is a report and a script a person reviews and runs through
|
|
50
|
+
their own deployment path.
|
|
51
|
+
|
|
52
|
+
Part of the coop suite (see [coop-agent](https://github.com/kabukisensei/coop-agent)).
|
|
53
|
+
coop calls it as its `schema_compare` tool; you can run it yourself.
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
pipx install coop-schema-compare
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Needs Python 3.10+, the Microsoft ODBC Driver 18 for SQL Server, and either an
|
|
62
|
+
access token in `SQL_ACCESS_TOKEN` or the Azure CLI signed in (`az login`).
|
|
63
|
+
|
|
64
|
+
## Use
|
|
65
|
+
|
|
66
|
+
```powershell
|
|
67
|
+
# dev against prod, live on both sides, named by workspace and warehouse
|
|
68
|
+
coop-schema-compare compare "fabric://Contoso Dev/QE_WH" "fabric://Contoso Prod/QE_WH" --source-environment dev --target-environment prod
|
|
69
|
+
|
|
70
|
+
# the same by SQL endpoint host
|
|
71
|
+
coop-schema-compare compare contoso-dev.datawarehouse.fabric.microsoft.com/QE_WH contoso-prod.datawarehouse.fabric.microsoft.com/QE_WH --source-environment dev --target-environment prod
|
|
72
|
+
|
|
73
|
+
# the repo (schema as code) against the live prod Warehouse
|
|
74
|
+
coop-schema-compare compare .\warehouse\QE_WH.Warehouse "fabric://Contoso Prod/QE_WH" --target-environment prod
|
|
75
|
+
|
|
76
|
+
# two branches of the repo, checked out side by side: no connection
|
|
77
|
+
coop-schema-compare diff ..\QE_WH-main\warehouse ..\QE_WH-feature\warehouse
|
|
78
|
+
|
|
79
|
+
# commit a snapshot of each side, then diff the folders offline (no connection)
|
|
80
|
+
coop-schema-compare snapshot "fabric://Contoso Dev/QE_WH" --out catalog/dev --environment dev
|
|
81
|
+
coop-schema-compare snapshot "fabric://Contoso Prod/QE_WH" --out catalog/prod --environment prod
|
|
82
|
+
coop-schema-compare diff catalog/dev catalog/prod
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
A side is one of:
|
|
86
|
+
|
|
87
|
+
| Form | Reads |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| `server/database` | the live catalog over an encrypted, token-authenticated connection |
|
|
90
|
+
| `fabric://<workspace>/<warehouse>` | the same, with the SQL endpoint looked up through the Fabric REST API; workspace and warehouse by id or display name |
|
|
91
|
+
| a snapshot folder | the folder `snapshot` or coop's `coop catalog snapshot` wrote (it holds `manifest.json`); no connection |
|
|
92
|
+
| any other folder | the repo: every `.sql` file under it, read as code; no connection |
|
|
93
|
+
|
|
94
|
+
The snapshot layout is the one coop's `coop catalog snapshot` writes, so either
|
|
95
|
+
tool's folder is a valid side for the other.
|
|
96
|
+
|
|
97
|
+
### The repo side
|
|
98
|
+
|
|
99
|
+
A repo side is a folder of T-SQL source: a Fabric Warehouse Git export or SQL
|
|
100
|
+
database project (one file per object under folders such as `dbo/Tables/`), or
|
|
101
|
+
a hand-kept `sql/` folder. Files are read in path order and split on `GO`; a
|
|
102
|
+
batch counts when its first statement is `CREATE SCHEMA`, `CREATE TABLE`, or
|
|
103
|
+
`CREATE [OR ALTER] VIEW | PROCEDURE | FUNCTION`. Everything else (post-deployment
|
|
104
|
+
scripts, `ALTER`, `INSERT`, `.sqlproj`, the `bin/` and `obj/` folders) is
|
|
105
|
+
ignored, and the report notes how many files held no object, so a mis-pointed
|
|
106
|
+
folder is visible. Table columns are read from the column list with the type
|
|
107
|
+
rendered as the live catalog renders it (`decimal(18, 2)`, `varchar(max)`; a
|
|
108
|
+
length or precision the source leaves out gets the engine default, `varchar(1)`
|
|
109
|
+
or `datetime2(7)`, as the engine itself would store it; write them out for an
|
|
110
|
+
exact compare). Constraints, defaults, identity and computed-column expressions
|
|
111
|
+
are out of scope, as on the live side. A view, procedure or function compares by
|
|
112
|
+
its text with a leading comment banner, `OR ALTER` and a trailing `;` ignored,
|
|
113
|
+
so a file and the catalog's copy of the same object match.
|
|
114
|
+
|
|
115
|
+
`compare` and `diff` write two files under `--out` (default
|
|
116
|
+
`./schema-compare/<source>-to-<target>/`):
|
|
117
|
+
|
|
118
|
+
- `report.md`: both sides' object counts and a sorted table of every difference
|
|
119
|
+
(kind, object, change, detail), destructive ones marked.
|
|
120
|
+
- `deploy.sql`: the promotion script in run order: new schemas, new tables,
|
|
121
|
+
in-place column additions, then functions, views and procedures as
|
|
122
|
+
`CREATE OR ALTER` in dependency order. Every DROP and every change that can
|
|
123
|
+
lose data (a dropped or retyped column, a `NOT NULL` column added to an
|
|
124
|
+
existing table, a name whose kind differs between the sides) is at the end,
|
|
125
|
+
commented out under a DESTRUCTIVE banner. On a Fabric Warehouse or Lakehouse
|
|
126
|
+
a column change is a rebuild note with the source shape, because those
|
|
127
|
+
targets do not alter columns in place.
|
|
128
|
+
|
|
129
|
+
Direction is "what the target needs to match the source". A view or procedure
|
|
130
|
+
reformatted by an editor is not a change: definitions are compared with line
|
|
131
|
+
endings and runs of whitespace folded.
|
|
132
|
+
|
|
133
|
+
## What is compared
|
|
134
|
+
|
|
135
|
+
Schemas; tables (each column's name, type, nullability and position); views,
|
|
136
|
+
procedures and functions by definition. Constraints, indexes, permissions and
|
|
137
|
+
row data are out of scope and the report says so.
|
|
138
|
+
|
|
139
|
+
## Exit codes and output
|
|
140
|
+
|
|
141
|
+
`0` the compare ran; `--fail-on-diff` gives `2` on any difference and
|
|
142
|
+
`--fail-on-destructive` gives `3` on a destructive one, for CI gates; `1` on an
|
|
143
|
+
error, printed as a short state (`connection_failed`, `side_invalid`,
|
|
144
|
+
`pyodbc_unavailable`, `odbc_driver_unavailable`, `az_unavailable`,
|
|
145
|
+
`snapshot_missing`, `output_not_snapshot`, `workspace_not_found`,
|
|
146
|
+
`warehouse_not_found`, `fabric_forbidden`). `--json` prints the result as one
|
|
147
|
+
object. No token, credential, server name, driver text or exception text is ever
|
|
148
|
+
printed or written.
|
|
149
|
+
|
|
150
|
+
## Authentication
|
|
151
|
+
|
|
152
|
+
The token for `https://database.windows.net/` is read from `SQL_ACCESS_TOKEN`
|
|
153
|
+
(or the variable `--token-env` names). When it is empty, the Azure CLI mints one
|
|
154
|
+
(`az account get-access-token`, `--tenant` to pin the tenant). The token goes to
|
|
155
|
+
the driver as a connection attribute and nowhere else. A `fabric://` side also
|
|
156
|
+
needs a token for `https://api.fabric.microsoft.com`, from `FABRIC_ACCESS_TOKEN`
|
|
157
|
+
(or `--fabric-token-env`) or the Azure CLI the same way; it is used for two
|
|
158
|
+
read-only GETs (list workspaces, list the workspace's warehouses) and nothing
|
|
159
|
+
else. Folder sides need no token.
|
|
160
|
+
|
|
161
|
+
## Why not SqlPackage or a deployment pipeline
|
|
162
|
+
|
|
163
|
+
Fabric deployment pipelines and Git integration promote a Warehouse through
|
|
164
|
+
DacFx: no script to read or edit, a column change drops and recreates the table,
|
|
165
|
+
permissions do not travel, and both sides must be workspaces in one tenant and
|
|
166
|
+
pipeline. SqlPackage supports the Warehouse but is a separate .NET tool on each
|
|
167
|
+
machine with a publish you cannot review line by line. This tool gives you the
|
|
168
|
+
plain script instead. SqlPackage remains the right tool for a full-fidelity
|
|
169
|
+
dacpac of a large estate.
|
|
170
|
+
|
|
171
|
+
## Develop
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
python -m pip install -e .
|
|
175
|
+
python -m unittest discover -s tests -v
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Tests run offline with fake cursors; no database or network is needed.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# coop-schema-compare
|
|
2
|
+
|
|
3
|
+
Deterministic schema compare between two SQL schemas, live or as code, with an
|
|
4
|
+
ordered promotion script. Built for Microsoft Fabric Warehouse, where the
|
|
5
|
+
built-in deployment pipeline gives you no script to read; it works the same on
|
|
6
|
+
Azure SQL Database, Fabric SQL database and SQL Server. A side is a live
|
|
7
|
+
database (by SQL endpoint or by Fabric workspace and warehouse name), a
|
|
8
|
+
committed snapshot, or a repo folder of `.sql` files, in any pairing: repo
|
|
9
|
+
against repo, live against live, repo against live. It **reads only and applies
|
|
10
|
+
nothing**: the output is a report and a script a person reviews and runs through
|
|
11
|
+
their own deployment path.
|
|
12
|
+
|
|
13
|
+
Part of the coop suite (see [coop-agent](https://github.com/kabukisensei/coop-agent)).
|
|
14
|
+
coop calls it as its `schema_compare` tool; you can run it yourself.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```powershell
|
|
19
|
+
pipx install coop-schema-compare
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Needs Python 3.10+, the Microsoft ODBC Driver 18 for SQL Server, and either an
|
|
23
|
+
access token in `SQL_ACCESS_TOKEN` or the Azure CLI signed in (`az login`).
|
|
24
|
+
|
|
25
|
+
## Use
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
# dev against prod, live on both sides, named by workspace and warehouse
|
|
29
|
+
coop-schema-compare compare "fabric://Contoso Dev/QE_WH" "fabric://Contoso Prod/QE_WH" --source-environment dev --target-environment prod
|
|
30
|
+
|
|
31
|
+
# the same by SQL endpoint host
|
|
32
|
+
coop-schema-compare compare contoso-dev.datawarehouse.fabric.microsoft.com/QE_WH contoso-prod.datawarehouse.fabric.microsoft.com/QE_WH --source-environment dev --target-environment prod
|
|
33
|
+
|
|
34
|
+
# the repo (schema as code) against the live prod Warehouse
|
|
35
|
+
coop-schema-compare compare .\warehouse\QE_WH.Warehouse "fabric://Contoso Prod/QE_WH" --target-environment prod
|
|
36
|
+
|
|
37
|
+
# two branches of the repo, checked out side by side: no connection
|
|
38
|
+
coop-schema-compare diff ..\QE_WH-main\warehouse ..\QE_WH-feature\warehouse
|
|
39
|
+
|
|
40
|
+
# commit a snapshot of each side, then diff the folders offline (no connection)
|
|
41
|
+
coop-schema-compare snapshot "fabric://Contoso Dev/QE_WH" --out catalog/dev --environment dev
|
|
42
|
+
coop-schema-compare snapshot "fabric://Contoso Prod/QE_WH" --out catalog/prod --environment prod
|
|
43
|
+
coop-schema-compare diff catalog/dev catalog/prod
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
A side is one of:
|
|
47
|
+
|
|
48
|
+
| Form | Reads |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `server/database` | the live catalog over an encrypted, token-authenticated connection |
|
|
51
|
+
| `fabric://<workspace>/<warehouse>` | the same, with the SQL endpoint looked up through the Fabric REST API; workspace and warehouse by id or display name |
|
|
52
|
+
| a snapshot folder | the folder `snapshot` or coop's `coop catalog snapshot` wrote (it holds `manifest.json`); no connection |
|
|
53
|
+
| any other folder | the repo: every `.sql` file under it, read as code; no connection |
|
|
54
|
+
|
|
55
|
+
The snapshot layout is the one coop's `coop catalog snapshot` writes, so either
|
|
56
|
+
tool's folder is a valid side for the other.
|
|
57
|
+
|
|
58
|
+
### The repo side
|
|
59
|
+
|
|
60
|
+
A repo side is a folder of T-SQL source: a Fabric Warehouse Git export or SQL
|
|
61
|
+
database project (one file per object under folders such as `dbo/Tables/`), or
|
|
62
|
+
a hand-kept `sql/` folder. Files are read in path order and split on `GO`; a
|
|
63
|
+
batch counts when its first statement is `CREATE SCHEMA`, `CREATE TABLE`, or
|
|
64
|
+
`CREATE [OR ALTER] VIEW | PROCEDURE | FUNCTION`. Everything else (post-deployment
|
|
65
|
+
scripts, `ALTER`, `INSERT`, `.sqlproj`, the `bin/` and `obj/` folders) is
|
|
66
|
+
ignored, and the report notes how many files held no object, so a mis-pointed
|
|
67
|
+
folder is visible. Table columns are read from the column list with the type
|
|
68
|
+
rendered as the live catalog renders it (`decimal(18, 2)`, `varchar(max)`; a
|
|
69
|
+
length or precision the source leaves out gets the engine default, `varchar(1)`
|
|
70
|
+
or `datetime2(7)`, as the engine itself would store it; write them out for an
|
|
71
|
+
exact compare). Constraints, defaults, identity and computed-column expressions
|
|
72
|
+
are out of scope, as on the live side. A view, procedure or function compares by
|
|
73
|
+
its text with a leading comment banner, `OR ALTER` and a trailing `;` ignored,
|
|
74
|
+
so a file and the catalog's copy of the same object match.
|
|
75
|
+
|
|
76
|
+
`compare` and `diff` write two files under `--out` (default
|
|
77
|
+
`./schema-compare/<source>-to-<target>/`):
|
|
78
|
+
|
|
79
|
+
- `report.md`: both sides' object counts and a sorted table of every difference
|
|
80
|
+
(kind, object, change, detail), destructive ones marked.
|
|
81
|
+
- `deploy.sql`: the promotion script in run order: new schemas, new tables,
|
|
82
|
+
in-place column additions, then functions, views and procedures as
|
|
83
|
+
`CREATE OR ALTER` in dependency order. Every DROP and every change that can
|
|
84
|
+
lose data (a dropped or retyped column, a `NOT NULL` column added to an
|
|
85
|
+
existing table, a name whose kind differs between the sides) is at the end,
|
|
86
|
+
commented out under a DESTRUCTIVE banner. On a Fabric Warehouse or Lakehouse
|
|
87
|
+
a column change is a rebuild note with the source shape, because those
|
|
88
|
+
targets do not alter columns in place.
|
|
89
|
+
|
|
90
|
+
Direction is "what the target needs to match the source". A view or procedure
|
|
91
|
+
reformatted by an editor is not a change: definitions are compared with line
|
|
92
|
+
endings and runs of whitespace folded.
|
|
93
|
+
|
|
94
|
+
## What is compared
|
|
95
|
+
|
|
96
|
+
Schemas; tables (each column's name, type, nullability and position); views,
|
|
97
|
+
procedures and functions by definition. Constraints, indexes, permissions and
|
|
98
|
+
row data are out of scope and the report says so.
|
|
99
|
+
|
|
100
|
+
## Exit codes and output
|
|
101
|
+
|
|
102
|
+
`0` the compare ran; `--fail-on-diff` gives `2` on any difference and
|
|
103
|
+
`--fail-on-destructive` gives `3` on a destructive one, for CI gates; `1` on an
|
|
104
|
+
error, printed as a short state (`connection_failed`, `side_invalid`,
|
|
105
|
+
`pyodbc_unavailable`, `odbc_driver_unavailable`, `az_unavailable`,
|
|
106
|
+
`snapshot_missing`, `output_not_snapshot`, `workspace_not_found`,
|
|
107
|
+
`warehouse_not_found`, `fabric_forbidden`). `--json` prints the result as one
|
|
108
|
+
object. No token, credential, server name, driver text or exception text is ever
|
|
109
|
+
printed or written.
|
|
110
|
+
|
|
111
|
+
## Authentication
|
|
112
|
+
|
|
113
|
+
The token for `https://database.windows.net/` is read from `SQL_ACCESS_TOKEN`
|
|
114
|
+
(or the variable `--token-env` names). When it is empty, the Azure CLI mints one
|
|
115
|
+
(`az account get-access-token`, `--tenant` to pin the tenant). The token goes to
|
|
116
|
+
the driver as a connection attribute and nowhere else. A `fabric://` side also
|
|
117
|
+
needs a token for `https://api.fabric.microsoft.com`, from `FABRIC_ACCESS_TOKEN`
|
|
118
|
+
(or `--fabric-token-env`) or the Azure CLI the same way; it is used for two
|
|
119
|
+
read-only GETs (list workspaces, list the workspace's warehouses) and nothing
|
|
120
|
+
else. Folder sides need no token.
|
|
121
|
+
|
|
122
|
+
## Why not SqlPackage or a deployment pipeline
|
|
123
|
+
|
|
124
|
+
Fabric deployment pipelines and Git integration promote a Warehouse through
|
|
125
|
+
DacFx: no script to read or edit, a column change drops and recreates the table,
|
|
126
|
+
permissions do not travel, and both sides must be workspaces in one tenant and
|
|
127
|
+
pipeline. SqlPackage supports the Warehouse but is a separate .NET tool on each
|
|
128
|
+
machine with a publish you cannot review line by line. This tool gives you the
|
|
129
|
+
plain script instead. SqlPackage remains the right tool for a full-fidelity
|
|
130
|
+
dacpac of a large estate.
|
|
131
|
+
|
|
132
|
+
## Develop
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
python -m pip install -e .
|
|
136
|
+
python -m unittest discover -s tests -v
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Tests run offline with fake cursors; no database or network is needed.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "coop-schema-compare"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Deterministic schema compare between SQL environments (Fabric Warehouse, Azure SQL) with an ordered promotion script. Reads only; applies nothing."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Cooptimize" }]
|
|
13
|
+
keywords = ["fabric", "warehouse", "azure-sql", "schema", "compare", "deployment"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Topic :: Database",
|
|
19
|
+
]
|
|
20
|
+
dependencies = ["pyodbc>=5.0"]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
coop-schema-compare = "coop_schema_compare.cli:main"
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/kabukisensei/coop-schema-compare"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
where = ["src"]
|