snowflake-code-unit-registry 0.7.2__tar.gz → 0.7.5__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.
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/Cargo.lock +32 -26
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/Cargo.toml +1 -1
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/PKG-INFO +1 -1
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/examples/code-unit.example.json +2 -2
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/schemas/code-unit.schema.json +4 -4
- snowflake_code_unit_registry-0.7.5/crates/scai-state-core/src/canonical_name.rs +457 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/error.rs +32 -2
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/generated/query_reference.rs +1 -1
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/lib.rs +1 -0
- snowflake_code_unit_registry-0.7.5/crates/scai-state-core/src/migration/mod.rs +626 -0
- snowflake_code_unit_registry-0.7.5/crates/scai-state-core/src/migration/versions/mod.rs +47 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/README.md +15 -2
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/tests.rs +366 -250
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry.rs +304 -123
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_crud.py +2 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_serialization.py +3 -2
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/pyproject.toml +1 -1
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/python/snowflake_code_unit_registry/__init__.py +2 -1
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/python/snowflake_code_unit_registry/types.py +17 -9
- snowflake_code_unit_registry-0.7.2/crates/scai-state-core/src/migration/mod.rs +0 -390
- snowflake_code_unit_registry-0.7.2/crates/scai-state-core/src/migration/versions/mod.rs +0 -32
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/README.md +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-error-derive/Cargo.toml +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-error-derive/src/lib.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-error-derive/tests/derive_integration.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/Cargo.toml +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/build.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/schemas/history/README.md +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/schemas/query-reference.rs.tmpl +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/schemas/query-reference.tmpl +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/checksum.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/error_trace.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/filter.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/generated/file_path_fields.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/generated/mod.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/generated/updated_at_paths.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/identity.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/graph.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/in_memory.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/loader.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/paths.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/query.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/registry/test_helpers.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-core/src/validation.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/Cargo.toml +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/README.md +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/src/lib.rs +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/conftest.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_batch.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_checksum.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_errors.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_migration.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_query.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_refresh.py +0 -0
- {snowflake_code_unit_registry-0.7.2 → snowflake_code_unit_registry-0.7.5}/crates/scai-state-python/tests/test_validation.py +0 -0
|
@@ -161,9 +161,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
|
|
161
161
|
|
|
162
162
|
[[package]]
|
|
163
163
|
name = "cc"
|
|
164
|
-
version = "1.2.
|
|
164
|
+
version = "1.2.60"
|
|
165
165
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
166
|
-
checksum = "
|
|
166
|
+
checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
|
|
167
167
|
dependencies = [
|
|
168
168
|
"find-msvc-tools",
|
|
169
169
|
"jobserver",
|
|
@@ -778,6 +778,12 @@ dependencies = [
|
|
|
778
778
|
"foldhash 0.2.0",
|
|
779
779
|
]
|
|
780
780
|
|
|
781
|
+
[[package]]
|
|
782
|
+
name = "hashbrown"
|
|
783
|
+
version = "0.17.0"
|
|
784
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
785
|
+
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
|
786
|
+
|
|
781
787
|
[[package]]
|
|
782
788
|
name = "heck"
|
|
783
789
|
version = "0.5.0"
|
|
@@ -1069,12 +1075,12 @@ dependencies = [
|
|
|
1069
1075
|
|
|
1070
1076
|
[[package]]
|
|
1071
1077
|
name = "indexmap"
|
|
1072
|
-
version = "2.
|
|
1078
|
+
version = "2.14.0"
|
|
1073
1079
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1074
|
-
checksum = "
|
|
1080
|
+
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
|
1075
1081
|
dependencies = [
|
|
1076
1082
|
"equivalent",
|
|
1077
|
-
"hashbrown 0.
|
|
1083
|
+
"hashbrown 0.17.0",
|
|
1078
1084
|
"serde",
|
|
1079
1085
|
"serde_core",
|
|
1080
1086
|
]
|
|
@@ -1204,9 +1210,9 @@ dependencies = [
|
|
|
1204
1210
|
|
|
1205
1211
|
[[package]]
|
|
1206
1212
|
name = "js-sys"
|
|
1207
|
-
version = "0.3.
|
|
1213
|
+
version = "0.3.95"
|
|
1208
1214
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1209
|
-
checksum = "
|
|
1215
|
+
checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
|
|
1210
1216
|
dependencies = [
|
|
1211
1217
|
"cfg-if",
|
|
1212
1218
|
"futures-util",
|
|
@@ -2068,9 +2074,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
|
|
2068
2074
|
|
|
2069
2075
|
[[package]]
|
|
2070
2076
|
name = "rustls-webpki"
|
|
2071
|
-
version = "0.103.
|
|
2077
|
+
version = "0.103.11"
|
|
2072
2078
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2073
|
-
checksum = "
|
|
2079
|
+
checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4"
|
|
2074
2080
|
dependencies = [
|
|
2075
2081
|
"aws-lc-rs",
|
|
2076
2082
|
"ring",
|
|
@@ -2095,7 +2101,7 @@ dependencies = [
|
|
|
2095
2101
|
|
|
2096
2102
|
[[package]]
|
|
2097
2103
|
name = "scai-error-derive"
|
|
2098
|
-
version = "0.7.
|
|
2104
|
+
version = "0.7.5"
|
|
2099
2105
|
dependencies = [
|
|
2100
2106
|
"err_code",
|
|
2101
2107
|
"heck",
|
|
@@ -2109,7 +2115,7 @@ dependencies = [
|
|
|
2109
2115
|
|
|
2110
2116
|
[[package]]
|
|
2111
2117
|
name = "scai-state-core"
|
|
2112
|
-
version = "0.7.
|
|
2118
|
+
version = "0.7.5"
|
|
2113
2119
|
dependencies = [
|
|
2114
2120
|
"chrono",
|
|
2115
2121
|
"err_code",
|
|
@@ -2134,7 +2140,7 @@ dependencies = [
|
|
|
2134
2140
|
|
|
2135
2141
|
[[package]]
|
|
2136
2142
|
name = "scai-state-csharp"
|
|
2137
|
-
version = "0.7.
|
|
2143
|
+
version = "0.7.5"
|
|
2138
2144
|
dependencies = [
|
|
2139
2145
|
"interoptopus",
|
|
2140
2146
|
"interoptopus_backend_csharp",
|
|
@@ -2145,7 +2151,7 @@ dependencies = [
|
|
|
2145
2151
|
|
|
2146
2152
|
[[package]]
|
|
2147
2153
|
name = "scai-state-node"
|
|
2148
|
-
version = "0.7.
|
|
2154
|
+
version = "0.7.5"
|
|
2149
2155
|
dependencies = [
|
|
2150
2156
|
"napi",
|
|
2151
2157
|
"napi-build",
|
|
@@ -2157,7 +2163,7 @@ dependencies = [
|
|
|
2157
2163
|
|
|
2158
2164
|
[[package]]
|
|
2159
2165
|
name = "scai-state-python"
|
|
2160
|
-
version = "0.7.
|
|
2166
|
+
version = "0.7.5"
|
|
2161
2167
|
dependencies = [
|
|
2162
2168
|
"pyo3",
|
|
2163
2169
|
"pythonize",
|
|
@@ -2868,9 +2874,9 @@ dependencies = [
|
|
|
2868
2874
|
|
|
2869
2875
|
[[package]]
|
|
2870
2876
|
name = "wasm-bindgen"
|
|
2871
|
-
version = "0.2.
|
|
2877
|
+
version = "0.2.118"
|
|
2872
2878
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2873
|
-
checksum = "
|
|
2879
|
+
checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
|
|
2874
2880
|
dependencies = [
|
|
2875
2881
|
"cfg-if",
|
|
2876
2882
|
"once_cell",
|
|
@@ -2881,9 +2887,9 @@ dependencies = [
|
|
|
2881
2887
|
|
|
2882
2888
|
[[package]]
|
|
2883
2889
|
name = "wasm-bindgen-futures"
|
|
2884
|
-
version = "0.4.
|
|
2890
|
+
version = "0.4.68"
|
|
2885
2891
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2886
|
-
checksum = "
|
|
2892
|
+
checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
|
|
2887
2893
|
dependencies = [
|
|
2888
2894
|
"js-sys",
|
|
2889
2895
|
"wasm-bindgen",
|
|
@@ -2891,9 +2897,9 @@ dependencies = [
|
|
|
2891
2897
|
|
|
2892
2898
|
[[package]]
|
|
2893
2899
|
name = "wasm-bindgen-macro"
|
|
2894
|
-
version = "0.2.
|
|
2900
|
+
version = "0.2.118"
|
|
2895
2901
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2896
|
-
checksum = "
|
|
2902
|
+
checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
|
|
2897
2903
|
dependencies = [
|
|
2898
2904
|
"quote",
|
|
2899
2905
|
"wasm-bindgen-macro-support",
|
|
@@ -2901,9 +2907,9 @@ dependencies = [
|
|
|
2901
2907
|
|
|
2902
2908
|
[[package]]
|
|
2903
2909
|
name = "wasm-bindgen-macro-support"
|
|
2904
|
-
version = "0.2.
|
|
2910
|
+
version = "0.2.118"
|
|
2905
2911
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2906
|
-
checksum = "
|
|
2912
|
+
checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
|
|
2907
2913
|
dependencies = [
|
|
2908
2914
|
"bumpalo",
|
|
2909
2915
|
"proc-macro2",
|
|
@@ -2914,9 +2920,9 @@ dependencies = [
|
|
|
2914
2920
|
|
|
2915
2921
|
[[package]]
|
|
2916
2922
|
name = "wasm-bindgen-shared"
|
|
2917
|
-
version = "0.2.
|
|
2923
|
+
version = "0.2.118"
|
|
2918
2924
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2919
|
-
checksum = "
|
|
2925
|
+
checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
|
|
2920
2926
|
dependencies = [
|
|
2921
2927
|
"unicode-ident",
|
|
2922
2928
|
]
|
|
@@ -2957,9 +2963,9 @@ dependencies = [
|
|
|
2957
2963
|
|
|
2958
2964
|
[[package]]
|
|
2959
2965
|
name = "web-sys"
|
|
2960
|
-
version = "0.3.
|
|
2966
|
+
version = "0.3.95"
|
|
2961
2967
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2962
|
-
checksum = "
|
|
2968
|
+
checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
|
|
2963
2969
|
dependencies = [
|
|
2964
2970
|
"js-sys",
|
|
2965
2971
|
"wasm-bindgen",
|
|
@@ -3,7 +3,7 @@ resolver = "2"
|
|
|
3
3
|
members = ["crates/scai-error-derive", "crates/scai-state-core", "crates/scai-state-python"]
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.7.
|
|
6
|
+
version = "0.7.5"
|
|
7
7
|
edition = "2021"
|
|
8
8
|
license = "SEE LICENSE IN LICENSE"
|
|
9
9
|
repository = "https://github.com/snowflake-eng/scai-state"
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"isMissing": false,
|
|
4
4
|
"inScope": true,
|
|
5
|
-
"containsCommit": true,
|
|
6
5
|
"kind": "databaseObject",
|
|
7
6
|
"id": "a3f1b2c4-5d6e-7f89-0a1b-2c3d4e5f6a7b",
|
|
8
7
|
"updatedAt": "2025-01-15T10:30:00Z",
|
|
@@ -53,7 +52,8 @@
|
|
|
53
52
|
"convertedChecksum": "defa8dbc2f2c5915579ade9fdc6aef24"
|
|
54
53
|
},
|
|
55
54
|
"assessment": {
|
|
56
|
-
"status": "completed"
|
|
55
|
+
"status": "completed",
|
|
56
|
+
"containsCommit": true
|
|
57
57
|
},
|
|
58
58
|
"dataQuality": {
|
|
59
59
|
"status": "completed",
|
|
@@ -58,10 +58,6 @@
|
|
|
58
58
|
"description": "true if CodeUnit is in the migration scope",
|
|
59
59
|
"default": true
|
|
60
60
|
},
|
|
61
|
-
"containsCommit": {
|
|
62
|
-
"type": "boolean",
|
|
63
|
-
"description": "True if the stored procedure contains a commit transaction"
|
|
64
|
-
},
|
|
65
61
|
"kind": {
|
|
66
62
|
"type": "string",
|
|
67
63
|
"title": "Kind",
|
|
@@ -208,6 +204,10 @@
|
|
|
208
204
|
"properties": {
|
|
209
205
|
"status": {
|
|
210
206
|
"$ref": "#/definitions/OperationStatus"
|
|
207
|
+
},
|
|
208
|
+
"containsCommit": {
|
|
209
|
+
"type": "boolean",
|
|
210
|
+
"description": "True if the stored procedure contains a commit transaction"
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
}
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
//! Canonical name computation for code unit metadata.
|
|
2
|
+
//!
|
|
3
|
+
//! A canonical name is a dot-separated identifier built from a code unit's
|
|
4
|
+
//! metadata fields: `database.schema.name` for most object types, or
|
|
5
|
+
//! `database.schema.name(TYPE,TYPE,...)` for procedures and functions
|
|
6
|
+
//! (using base parameter types with length/precision stripped).
|
|
7
|
+
//!
|
|
8
|
+
//! Two public entry points:
|
|
9
|
+
//! - [`compute`] — low-level, accepts individual fields
|
|
10
|
+
//! - [`for_code_unit`] — convenience wrapper that extracts fields from a [`CodeUnit`]
|
|
11
|
+
|
|
12
|
+
use crate::generated::types::{CodeUnit, ObjectType, ParameterDef};
|
|
13
|
+
|
|
14
|
+
/// Sentinel schema name used when a database is present but no schema
|
|
15
|
+
/// is specified. Consumers should be aware this value may appear in
|
|
16
|
+
/// canonical names for incompletely-specified metadata.
|
|
17
|
+
pub const UNKNOWN_SCHEMA: &str = "UNKNOWN_SCHEMA";
|
|
18
|
+
|
|
19
|
+
/// Selects which side of the code unit metadata to use.
|
|
20
|
+
///
|
|
21
|
+
/// A [`CodeUnit`] has one shared `signature` block containing both source
|
|
22
|
+
/// and target type information on each parameter. `Side` controls which
|
|
23
|
+
/// type field is read: `type_` for [`Source`](Side::Source), `target_type`
|
|
24
|
+
/// for [`Target`](Side::Target).
|
|
25
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
26
|
+
pub enum Side {
|
|
27
|
+
/// Use source metadata and source parameter types (`type_` field).
|
|
28
|
+
Source,
|
|
29
|
+
/// Use target metadata and target parameter types (`target_type` field).
|
|
30
|
+
Target,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Compute a canonical name from individual metadata fields.
|
|
34
|
+
///
|
|
35
|
+
/// Returns `None` when `name` is `None` and `object_type` is not a
|
|
36
|
+
/// container type (`Database` or `Schema`).
|
|
37
|
+
///
|
|
38
|
+
/// `params` comes from the shared `signature.parameters.arguments` array.
|
|
39
|
+
/// Each [`ParameterDef`] carries both source (`type_`) and target
|
|
40
|
+
/// (`target_type`) types; `side` selects which one to use.
|
|
41
|
+
///
|
|
42
|
+
/// # Format
|
|
43
|
+
///
|
|
44
|
+
/// - `database.schema.name` — when all three parts are present
|
|
45
|
+
/// - `schema.name` — when database is missing
|
|
46
|
+
/// - `name` — when both database and schema are missing
|
|
47
|
+
/// - Append `(TYPE,TYPE,...)` for `Procedure` and `Function` object types
|
|
48
|
+
/// - If database is present but schema is missing, [`UNKNOWN_SCHEMA`] is
|
|
49
|
+
/// substituted (except for `Database` object type which has no schema)
|
|
50
|
+
pub fn compute(
|
|
51
|
+
database: Option<&str>,
|
|
52
|
+
schema: Option<&str>,
|
|
53
|
+
name: Option<&str>,
|
|
54
|
+
object_type: Option<&ObjectType>,
|
|
55
|
+
params: Option<&[ParameterDef]>,
|
|
56
|
+
side: Side,
|
|
57
|
+
) -> Option<String> {
|
|
58
|
+
let is_container = matches!(object_type, Some(ObjectType::Database | ObjectType::Schema));
|
|
59
|
+
|
|
60
|
+
if name.is_none() && !is_container {
|
|
61
|
+
return None;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let mut parts: Vec<&str> = Vec::new();
|
|
65
|
+
|
|
66
|
+
if let Some(database) = database {
|
|
67
|
+
parts.push(database);
|
|
68
|
+
if !matches!(object_type, Some(ObjectType::Database)) {
|
|
69
|
+
parts.push(schema.unwrap_or(UNKNOWN_SCHEMA));
|
|
70
|
+
}
|
|
71
|
+
} else if let Some(schema) = schema {
|
|
72
|
+
parts.push(schema);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if let Some(name) = name {
|
|
76
|
+
parts.push(name);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let mut canonical = parts.join(".");
|
|
80
|
+
|
|
81
|
+
let needs_signature = matches!(
|
|
82
|
+
object_type,
|
|
83
|
+
Some(ObjectType::Procedure | ObjectType::Function)
|
|
84
|
+
);
|
|
85
|
+
if needs_signature {
|
|
86
|
+
if let Some(params) = params {
|
|
87
|
+
let param_types: Vec<&str> = params
|
|
88
|
+
.iter()
|
|
89
|
+
.filter_map(|param| {
|
|
90
|
+
let raw_type = match side {
|
|
91
|
+
Side::Source => param.type_.as_deref(),
|
|
92
|
+
Side::Target => param.target_type.as_deref(),
|
|
93
|
+
};
|
|
94
|
+
raw_type.map(strip_type_precision)
|
|
95
|
+
})
|
|
96
|
+
.collect();
|
|
97
|
+
if !param_types.is_empty() {
|
|
98
|
+
canonical.push('(');
|
|
99
|
+
canonical.push_str(¶m_types.join(","));
|
|
100
|
+
canonical.push(')');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Some(canonical)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Compute the canonical name for one side of a [`CodeUnit`].
|
|
109
|
+
///
|
|
110
|
+
/// Extracts metadata and signature fields from the unit, then delegates
|
|
111
|
+
/// to [`compute`]. The shared `signature.parameters.arguments` array is
|
|
112
|
+
/// passed through; `side` determines which type field is read from each
|
|
113
|
+
/// parameter.
|
|
114
|
+
pub fn for_code_unit(unit: &CodeUnit, side: Side) -> Option<String> {
|
|
115
|
+
let (database, schema, name, object_type) = match side {
|
|
116
|
+
Side::Source => {
|
|
117
|
+
let s = unit.source.as_ref()?;
|
|
118
|
+
(
|
|
119
|
+
s.database.as_deref(),
|
|
120
|
+
s.schema.as_deref(),
|
|
121
|
+
s.name.as_deref(),
|
|
122
|
+
s.object_type.as_ref(),
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
Side::Target => {
|
|
126
|
+
let t = unit.target.as_ref()?;
|
|
127
|
+
(
|
|
128
|
+
t.database.as_deref(),
|
|
129
|
+
t.schema.as_deref(),
|
|
130
|
+
t.name.as_deref(),
|
|
131
|
+
t.object_type.as_ref(),
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
let params = unit
|
|
137
|
+
.signature
|
|
138
|
+
.as_ref()
|
|
139
|
+
.and_then(|s| s.parameters.as_ref())
|
|
140
|
+
.map(|p| p.arguments.as_slice());
|
|
141
|
+
|
|
142
|
+
compute(database, schema, name, object_type, params, side)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Strip length/precision qualifiers from a SQL type.
|
|
146
|
+
///
|
|
147
|
+
/// `"NVARCHAR(50)"` → `"NVARCHAR"`, `"INT"` → `"INT"`.
|
|
148
|
+
fn strip_type_precision(ty: &str) -> &str {
|
|
149
|
+
match ty.find('(') {
|
|
150
|
+
Some(pos) => &ty[..pos],
|
|
151
|
+
None => ty,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#[cfg(test)]
|
|
156
|
+
mod tests {
|
|
157
|
+
use super::*;
|
|
158
|
+
use crate::generated::types::{Parameters, Signature, SourceMetadata, TargetMetadata};
|
|
159
|
+
|
|
160
|
+
#[test]
|
|
161
|
+
fn table_full_qualified() {
|
|
162
|
+
let result = compute(
|
|
163
|
+
Some("DB"),
|
|
164
|
+
Some("dbo"),
|
|
165
|
+
Some("MyTable"),
|
|
166
|
+
Some(&ObjectType::Table),
|
|
167
|
+
None,
|
|
168
|
+
Side::Source,
|
|
169
|
+
);
|
|
170
|
+
assert_eq!(result.as_deref(), Some("DB.dbo.MyTable"));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#[test]
|
|
174
|
+
fn procedure_with_params_source() {
|
|
175
|
+
let params = vec![
|
|
176
|
+
ParameterDef {
|
|
177
|
+
type_: Some("DATETIME".to_string()),
|
|
178
|
+
target_type: Some("TIMESTAMP_NTZ".to_string()),
|
|
179
|
+
..Default::default()
|
|
180
|
+
},
|
|
181
|
+
ParameterDef {
|
|
182
|
+
type_: Some("NVARCHAR(50)".to_string()),
|
|
183
|
+
target_type: Some("VARCHAR(50)".to_string()),
|
|
184
|
+
..Default::default()
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
let result = compute(
|
|
188
|
+
Some("DB"),
|
|
189
|
+
Some("dbo"),
|
|
190
|
+
Some("MyProc"),
|
|
191
|
+
Some(&ObjectType::Procedure),
|
|
192
|
+
Some(¶ms),
|
|
193
|
+
Side::Source,
|
|
194
|
+
);
|
|
195
|
+
assert_eq!(result.as_deref(), Some("DB.dbo.MyProc(DATETIME,NVARCHAR)"));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
#[test]
|
|
199
|
+
fn procedure_with_params_target() {
|
|
200
|
+
let params = vec![
|
|
201
|
+
ParameterDef {
|
|
202
|
+
type_: Some("DATETIME".to_string()),
|
|
203
|
+
target_type: Some("TIMESTAMP_NTZ".to_string()),
|
|
204
|
+
..Default::default()
|
|
205
|
+
},
|
|
206
|
+
ParameterDef {
|
|
207
|
+
type_: Some("NVARCHAR(50)".to_string()),
|
|
208
|
+
target_type: Some("VARCHAR(50)".to_string()),
|
|
209
|
+
..Default::default()
|
|
210
|
+
},
|
|
211
|
+
];
|
|
212
|
+
let result = compute(
|
|
213
|
+
Some("DB"),
|
|
214
|
+
Some("DBO"),
|
|
215
|
+
Some("MYPROC"),
|
|
216
|
+
Some(&ObjectType::Procedure),
|
|
217
|
+
Some(¶ms),
|
|
218
|
+
Side::Target,
|
|
219
|
+
);
|
|
220
|
+
assert_eq!(
|
|
221
|
+
result.as_deref(),
|
|
222
|
+
Some("DB.DBO.MYPROC(TIMESTAMP_NTZ,VARCHAR)")
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
#[test]
|
|
227
|
+
fn function_with_params() {
|
|
228
|
+
let params = vec![ParameterDef {
|
|
229
|
+
type_: Some("INT".to_string()),
|
|
230
|
+
target_type: Some("NUMBER".to_string()),
|
|
231
|
+
..Default::default()
|
|
232
|
+
}];
|
|
233
|
+
let result = compute(
|
|
234
|
+
Some("DB"),
|
|
235
|
+
Some("dbo"),
|
|
236
|
+
Some("MyFunc"),
|
|
237
|
+
Some(&ObjectType::Function),
|
|
238
|
+
Some(¶ms),
|
|
239
|
+
Side::Source,
|
|
240
|
+
);
|
|
241
|
+
assert_eq!(result.as_deref(), Some("DB.dbo.MyFunc(INT)"));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
#[test]
|
|
245
|
+
fn view_ignores_params() {
|
|
246
|
+
let params = vec![ParameterDef {
|
|
247
|
+
type_: Some("INT".to_string()),
|
|
248
|
+
..Default::default()
|
|
249
|
+
}];
|
|
250
|
+
let result = compute(
|
|
251
|
+
Some("DB"),
|
|
252
|
+
Some("dbo"),
|
|
253
|
+
Some("MyView"),
|
|
254
|
+
Some(&ObjectType::View),
|
|
255
|
+
Some(¶ms),
|
|
256
|
+
Side::Source,
|
|
257
|
+
);
|
|
258
|
+
assert_eq!(
|
|
259
|
+
result.as_deref(),
|
|
260
|
+
Some("DB.dbo.MyView"),
|
|
261
|
+
"views should not include parameter signature"
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
#[test]
|
|
266
|
+
fn schema_and_name_only() {
|
|
267
|
+
let result = compute(
|
|
268
|
+
None,
|
|
269
|
+
Some("dbo"),
|
|
270
|
+
Some("Orphan"),
|
|
271
|
+
Some(&ObjectType::Table),
|
|
272
|
+
None,
|
|
273
|
+
Side::Source,
|
|
274
|
+
);
|
|
275
|
+
assert_eq!(result.as_deref(), Some("dbo.Orphan"));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
#[test]
|
|
279
|
+
fn name_only() {
|
|
280
|
+
let result = compute(
|
|
281
|
+
None,
|
|
282
|
+
None,
|
|
283
|
+
Some("Lonely"),
|
|
284
|
+
Some(&ObjectType::Table),
|
|
285
|
+
None,
|
|
286
|
+
Side::Source,
|
|
287
|
+
);
|
|
288
|
+
assert_eq!(result.as_deref(), Some("Lonely"));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#[test]
|
|
292
|
+
fn unknown_schema_fallback() {
|
|
293
|
+
let result = compute(
|
|
294
|
+
Some("MyDB"),
|
|
295
|
+
None,
|
|
296
|
+
Some("Widget"),
|
|
297
|
+
Some(&ObjectType::Table),
|
|
298
|
+
None,
|
|
299
|
+
Side::Source,
|
|
300
|
+
);
|
|
301
|
+
assert_eq!(result.as_deref(), Some("MyDB.UNKNOWN_SCHEMA.Widget"));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
#[test]
|
|
305
|
+
fn none_when_name_missing() {
|
|
306
|
+
let result = compute(
|
|
307
|
+
Some("DB"),
|
|
308
|
+
Some("dbo"),
|
|
309
|
+
None,
|
|
310
|
+
Some(&ObjectType::Table),
|
|
311
|
+
None,
|
|
312
|
+
Side::Source,
|
|
313
|
+
);
|
|
314
|
+
assert_eq!(result, None);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
#[test]
|
|
318
|
+
fn database_object_type() {
|
|
319
|
+
let result = compute(
|
|
320
|
+
Some("MyDB"),
|
|
321
|
+
None,
|
|
322
|
+
None,
|
|
323
|
+
Some(&ObjectType::Database),
|
|
324
|
+
None,
|
|
325
|
+
Side::Source,
|
|
326
|
+
);
|
|
327
|
+
assert_eq!(result.as_deref(), Some("MyDB"));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
#[test]
|
|
331
|
+
fn schema_object_type_with_database() {
|
|
332
|
+
let result = compute(
|
|
333
|
+
Some("MyDB"),
|
|
334
|
+
Some("Sales"),
|
|
335
|
+
None,
|
|
336
|
+
Some(&ObjectType::Schema),
|
|
337
|
+
None,
|
|
338
|
+
Side::Source,
|
|
339
|
+
);
|
|
340
|
+
assert_eq!(result.as_deref(), Some("MyDB.Sales"));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
#[test]
|
|
344
|
+
fn schema_object_type_without_database() {
|
|
345
|
+
let result = compute(
|
|
346
|
+
None,
|
|
347
|
+
Some("Sales"),
|
|
348
|
+
None,
|
|
349
|
+
Some(&ObjectType::Schema),
|
|
350
|
+
None,
|
|
351
|
+
Side::Source,
|
|
352
|
+
);
|
|
353
|
+
assert_eq!(result.as_deref(), Some("Sales"));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
#[test]
|
|
357
|
+
fn procedure_no_params_no_parens() {
|
|
358
|
+
let result = compute(
|
|
359
|
+
Some("DB"),
|
|
360
|
+
Some("dbo"),
|
|
361
|
+
Some("NoArgs"),
|
|
362
|
+
Some(&ObjectType::Procedure),
|
|
363
|
+
None,
|
|
364
|
+
Side::Source,
|
|
365
|
+
);
|
|
366
|
+
assert_eq!(
|
|
367
|
+
result.as_deref(),
|
|
368
|
+
Some("DB.dbo.NoArgs"),
|
|
369
|
+
"procedures with no params should not have empty parens"
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
#[test]
|
|
374
|
+
fn strip_type_precision_works() {
|
|
375
|
+
assert_eq!(strip_type_precision("NVARCHAR(50)"), "NVARCHAR");
|
|
376
|
+
assert_eq!(strip_type_precision("DECIMAL(18,2)"), "DECIMAL");
|
|
377
|
+
assert_eq!(strip_type_precision("INT"), "INT");
|
|
378
|
+
assert_eq!(strip_type_precision("TIMESTAMP_NTZ"), "TIMESTAMP_NTZ");
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
#[test]
|
|
382
|
+
fn for_code_unit_source() {
|
|
383
|
+
let unit = CodeUnit {
|
|
384
|
+
source: Some(SourceMetadata {
|
|
385
|
+
object_type: Some(ObjectType::Table),
|
|
386
|
+
database: Some("DB".to_string()),
|
|
387
|
+
schema: Some("dbo".to_string()),
|
|
388
|
+
name: Some("Orders".to_string()),
|
|
389
|
+
..Default::default()
|
|
390
|
+
}),
|
|
391
|
+
..Default::default()
|
|
392
|
+
};
|
|
393
|
+
assert_eq!(
|
|
394
|
+
for_code_unit(&unit, Side::Source).as_deref(),
|
|
395
|
+
Some("DB.dbo.Orders")
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
#[test]
|
|
400
|
+
fn for_code_unit_target() {
|
|
401
|
+
let unit = CodeUnit {
|
|
402
|
+
target: Some(TargetMetadata {
|
|
403
|
+
object_type: Some(ObjectType::Table),
|
|
404
|
+
database: Some("DB".to_string()),
|
|
405
|
+
schema: Some("DBO".to_string()),
|
|
406
|
+
name: Some("ORDERS".to_string()),
|
|
407
|
+
..Default::default()
|
|
408
|
+
}),
|
|
409
|
+
..Default::default()
|
|
410
|
+
};
|
|
411
|
+
assert_eq!(
|
|
412
|
+
for_code_unit(&unit, Side::Target).as_deref(),
|
|
413
|
+
Some("DB.DBO.ORDERS")
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
#[test]
|
|
418
|
+
fn for_code_unit_with_signature() {
|
|
419
|
+
let unit = CodeUnit {
|
|
420
|
+
source: Some(SourceMetadata {
|
|
421
|
+
object_type: Some(ObjectType::Procedure),
|
|
422
|
+
database: Some("DB".to_string()),
|
|
423
|
+
schema: Some("dbo".to_string()),
|
|
424
|
+
name: Some("MyProc".to_string()),
|
|
425
|
+
..Default::default()
|
|
426
|
+
}),
|
|
427
|
+
signature: Some(Signature {
|
|
428
|
+
parameters: Some(Parameters {
|
|
429
|
+
arguments: vec![ParameterDef {
|
|
430
|
+
type_: Some("DATETIME".to_string()),
|
|
431
|
+
target_type: Some("TIMESTAMP_NTZ".to_string()),
|
|
432
|
+
..Default::default()
|
|
433
|
+
}],
|
|
434
|
+
..Default::default()
|
|
435
|
+
}),
|
|
436
|
+
..Default::default()
|
|
437
|
+
}),
|
|
438
|
+
..Default::default()
|
|
439
|
+
};
|
|
440
|
+
assert_eq!(
|
|
441
|
+
for_code_unit(&unit, Side::Source).as_deref(),
|
|
442
|
+
Some("DB.dbo.MyProc(DATETIME)")
|
|
443
|
+
);
|
|
444
|
+
assert_eq!(
|
|
445
|
+
for_code_unit(&unit, Side::Target),
|
|
446
|
+
None,
|
|
447
|
+
"target metadata is None, should return None"
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
#[test]
|
|
452
|
+
fn for_code_unit_no_metadata() {
|
|
453
|
+
let unit = CodeUnit::default();
|
|
454
|
+
assert_eq!(for_code_unit(&unit, Side::Source), None);
|
|
455
|
+
assert_eq!(for_code_unit(&unit, Side::Target), None);
|
|
456
|
+
}
|
|
457
|
+
}
|