recce-nightly 1.2.0.20250506__py3-none-any.whl → 1.26.0.20251124__py3-none-any.whl

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.

Potentially problematic release.


This version of recce-nightly might be problematic. Click here for more details.

Files changed (213) hide show
  1. recce/VERSION +1 -1
  2. recce/__init__.py +27 -22
  3. recce/adapter/base.py +11 -14
  4. recce/adapter/dbt_adapter/__init__.py +810 -480
  5. recce/adapter/dbt_adapter/dbt_version.py +3 -0
  6. recce/adapter/sqlmesh_adapter.py +24 -35
  7. recce/apis/check_api.py +39 -28
  8. recce/apis/check_func.py +33 -27
  9. recce/apis/run_api.py +25 -19
  10. recce/apis/run_func.py +29 -23
  11. recce/artifact.py +119 -51
  12. recce/cli.py +1299 -323
  13. recce/config.py +42 -33
  14. recce/connect_to_cloud.py +138 -0
  15. recce/core.py +55 -47
  16. recce/data/404.html +1 -1
  17. recce/data/__next.__PAGE__.txt +10 -0
  18. recce/data/__next._full.txt +23 -0
  19. recce/data/__next._head.txt +8 -0
  20. recce/data/__next._index.txt +8 -0
  21. recce/data/__next._tree.txt +5 -0
  22. recce/data/_next/static/52aV_JrNUZU6dMFgvTQEO/_buildManifest.js +11 -0
  23. recce/data/_next/static/52aV_JrNUZU6dMFgvTQEO/_clientMiddlewareManifest.json +1 -0
  24. recce/data/_next/static/chunks/02b996c7f6a29a06.js +4 -0
  25. recce/data/_next/static/chunks/19c10d219a6a21ff.js +1 -0
  26. recce/data/_next/static/chunks/2df9ec28a061971d.js +11 -0
  27. recce/data/_next/static/chunks/3098c987393bda15.js +1 -0
  28. recce/data/_next/static/chunks/393dc43e483f717a.css +2 -0
  29. recce/data/_next/static/chunks/399e8d91a7e45073.js +2 -0
  30. recce/data/_next/static/chunks/4d0186f631230245.js +1 -0
  31. recce/data/_next/static/chunks/5794ba9e10a9c060.js +11 -0
  32. recce/data/_next/static/chunks/715761c929a3f28b.js +110 -0
  33. recce/data/_next/static/chunks/71f88fcc615bf282.js +1 -0
  34. recce/data/_next/static/chunks/80d2a95eaf1201ea.js +1 -0
  35. recce/data/_next/static/chunks/9979c6109bbbee35.js +1 -0
  36. recce/data/_next/static/chunks/99d638224186c118.js +1 -0
  37. recce/data/_next/static/chunks/d003eb36240e92f3.js +1 -0
  38. recce/data/_next/static/chunks/d3167cdfec4fc351.js +1 -0
  39. recce/data/_next/static/chunks/e124bccf574a3361.css +1 -0
  40. recce/data/_next/static/chunks/f40141db1bdb46f0.css +6 -0
  41. recce/data/_next/static/chunks/fcc53a88741a52f9.js +1 -0
  42. recce/data/_next/static/chunks/turbopack-b1920d28cfb1f28d.js +3 -0
  43. recce/data/_next/static/media/favicon.a8d38d84.ico +0 -0
  44. recce/data/_next/static/media/montserrat-cyrillic-800-normal.d80d830d.woff2 +0 -0
  45. recce/data/_next/static/media/montserrat-cyrillic-800-normal.f9d58125.woff +0 -0
  46. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.076c2a93.woff2 +0 -0
  47. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.a4fa76b5.woff +0 -0
  48. recce/data/_next/static/media/montserrat-latin-800-normal.cde454cc.woff2 +0 -0
  49. recce/data/_next/static/media/montserrat-latin-800-normal.d5761935.woff +0 -0
  50. recce/data/_next/static/media/montserrat-latin-ext-800-normal.40ec0659.woff2 +0 -0
  51. recce/data/_next/static/media/montserrat-latin-ext-800-normal.b671449b.woff +0 -0
  52. recce/data/_next/static/media/montserrat-vietnamese-800-normal.9f7b8541.woff +0 -0
  53. recce/data/_next/static/media/montserrat-vietnamese-800-normal.f9eb854e.woff2 +0 -0
  54. recce/data/_next/static/media/reload-image.7aa931c7.svg +4 -0
  55. recce/data/_not-found/__next._full.txt +17 -0
  56. recce/data/_not-found/__next._head.txt +8 -0
  57. recce/data/_not-found/__next._index.txt +8 -0
  58. recce/data/_not-found/__next._not-found.__PAGE__.txt +5 -0
  59. recce/data/_not-found/__next._not-found.txt +4 -0
  60. recce/data/_not-found/__next._tree.txt +3 -0
  61. recce/data/_not-found.html +1 -0
  62. recce/data/_not-found.txt +17 -0
  63. recce/data/auth_callback.html +68 -0
  64. recce/data/imgs/reload-image.svg +4 -0
  65. recce/data/index.html +1 -27
  66. recce/data/index.txt +23 -7
  67. recce/diff.py +6 -12
  68. recce/event/__init__.py +86 -74
  69. recce/event/collector.py +33 -22
  70. recce/event/track.py +49 -27
  71. recce/exceptions.py +1 -1
  72. recce/git.py +7 -7
  73. recce/github.py +57 -53
  74. recce/mcp_server.py +716 -0
  75. recce/models/__init__.py +4 -1
  76. recce/models/check.py +6 -7
  77. recce/models/run.py +1 -0
  78. recce/models/types.py +131 -28
  79. recce/pull_request.py +27 -25
  80. recce/run.py +165 -121
  81. recce/server.py +303 -111
  82. recce/state/__init__.py +31 -0
  83. recce/state/cloud.py +632 -0
  84. recce/state/const.py +26 -0
  85. recce/state/local.py +56 -0
  86. recce/state/state.py +119 -0
  87. recce/state/state_loader.py +174 -0
  88. recce/summary.py +188 -143
  89. recce/tasks/__init__.py +19 -3
  90. recce/tasks/core.py +11 -13
  91. recce/tasks/dataframe.py +82 -18
  92. recce/tasks/histogram.py +69 -34
  93. recce/tasks/lineage.py +2 -2
  94. recce/tasks/profile.py +152 -86
  95. recce/tasks/query.py +139 -87
  96. recce/tasks/rowcount.py +37 -31
  97. recce/tasks/schema.py +18 -15
  98. recce/tasks/top_k.py +35 -35
  99. recce/tasks/valuediff.py +216 -152
  100. recce/util/__init__.py +3 -0
  101. recce/util/api_token.py +80 -0
  102. recce/util/breaking.py +87 -85
  103. recce/util/cll.py +274 -219
  104. recce/util/io.py +22 -17
  105. recce/util/lineage.py +65 -16
  106. recce/util/logger.py +1 -1
  107. recce/util/onboarding_state.py +45 -0
  108. recce/util/perf_tracking.py +85 -0
  109. recce/util/recce_cloud.py +322 -72
  110. recce/util/singleton.py +4 -4
  111. recce/yaml/__init__.py +7 -10
  112. recce_cloud/__init__.py +24 -0
  113. recce_cloud/api/__init__.py +17 -0
  114. recce_cloud/api/base.py +111 -0
  115. recce_cloud/api/client.py +150 -0
  116. recce_cloud/api/exceptions.py +26 -0
  117. recce_cloud/api/factory.py +63 -0
  118. recce_cloud/api/github.py +76 -0
  119. recce_cloud/api/gitlab.py +82 -0
  120. recce_cloud/artifact.py +57 -0
  121. recce_cloud/ci_providers/__init__.py +9 -0
  122. recce_cloud/ci_providers/base.py +82 -0
  123. recce_cloud/ci_providers/detector.py +147 -0
  124. recce_cloud/ci_providers/github_actions.py +136 -0
  125. recce_cloud/ci_providers/gitlab_ci.py +130 -0
  126. recce_cloud/cli.py +245 -0
  127. recce_cloud/upload.py +214 -0
  128. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.26.0.20251124.dist-info}/METADATA +68 -37
  129. recce_nightly-1.26.0.20251124.dist-info/RECORD +180 -0
  130. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.26.0.20251124.dist-info}/WHEEL +1 -1
  131. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.26.0.20251124.dist-info}/top_level.txt +1 -0
  132. tests/adapter/dbt_adapter/conftest.py +9 -5
  133. tests/adapter/dbt_adapter/dbt_test_helper.py +37 -22
  134. tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -15
  135. tests/adapter/dbt_adapter/test_dbt_cll.py +656 -41
  136. tests/adapter/dbt_adapter/test_selector.py +22 -21
  137. tests/recce_cloud/__init__.py +0 -0
  138. tests/recce_cloud/test_ci_providers.py +351 -0
  139. tests/recce_cloud/test_cli.py +372 -0
  140. tests/recce_cloud/test_client.py +273 -0
  141. tests/recce_cloud/test_platform_clients.py +333 -0
  142. tests/tasks/conftest.py +1 -1
  143. tests/tasks/test_histogram.py +58 -66
  144. tests/tasks/test_lineage.py +36 -23
  145. tests/tasks/test_preset_checks.py +45 -31
  146. tests/tasks/test_profile.py +339 -15
  147. tests/tasks/test_query.py +46 -46
  148. tests/tasks/test_row_count.py +65 -46
  149. tests/tasks/test_schema.py +65 -42
  150. tests/tasks/test_top_k.py +22 -18
  151. tests/tasks/test_valuediff.py +43 -32
  152. tests/test_cli.py +174 -60
  153. tests/test_cli_mcp_optional.py +45 -0
  154. tests/test_cloud_listing_cli.py +324 -0
  155. tests/test_config.py +7 -9
  156. tests/test_connect_to_cloud.py +82 -0
  157. tests/test_core.py +151 -4
  158. tests/test_dbt.py +7 -7
  159. tests/test_mcp_server.py +332 -0
  160. tests/test_pull_request.py +1 -1
  161. tests/test_server.py +25 -19
  162. tests/test_summary.py +29 -17
  163. recce/data/_next/static/Kcbs3GEIyH2LxgLYat0es/_buildManifest.js +0 -1
  164. recce/data/_next/static/chunks/1f229bf6-d9fe92e56db8d93b.js +0 -1
  165. recce/data/_next/static/chunks/29e3cc0d-8c150e37dff9631b.js +0 -1
  166. recce/data/_next/static/chunks/368-7587b306577df275.js +0 -65
  167. recce/data/_next/static/chunks/36e1c10d-bb0210cbd6573a8d.js +0 -1
  168. recce/data/_next/static/chunks/3998a672-eaad84bdd88cc73e.js +0 -1
  169. recce/data/_next/static/chunks/3a92ee20-3b5d922d4157af5e.js +0 -1
  170. recce/data/_next/static/chunks/450c323b-1bb5db526e54435a.js +0 -1
  171. recce/data/_next/static/chunks/47d8844f-79a1b53c66a7d7ec.js +0 -1
  172. recce/data/_next/static/chunks/6dc81886-c94b9b91bc2c3caf.js +0 -1
  173. recce/data/_next/static/chunks/6ef81909-694dc38134099299.js +0 -1
  174. recce/data/_next/static/chunks/700-3b65fc3666820d00.js +0 -2
  175. recce/data/_next/static/chunks/7a8a3e83-d7fa409d97b38b2b.js +0 -1
  176. recce/data/_next/static/chunks/7f27ae6c-413f6b869a04183a.js +0 -1
  177. recce/data/_next/static/chunks/8d700b6a-f0b1f6b9e0d97ce2.js +0 -1
  178. recce/data/_next/static/chunks/9746af58-d74bef4d03eea6ab.js +0 -1
  179. recce/data/_next/static/chunks/a30376cd-7d806e1602f2dc3a.js +0 -1
  180. recce/data/_next/static/chunks/app/_not-found/page-8a886fa0855c3105.js +0 -1
  181. recce/data/_next/static/chunks/app/layout-9102e22cb73f74d6.js +0 -1
  182. recce/data/_next/static/chunks/app/page-cee661090afbd6aa.js +0 -1
  183. recce/data/_next/static/chunks/b63b1b3f-7395c74e11a14e95.js +0 -1
  184. recce/data/_next/static/chunks/c132bf7d-8102037f9ccf372a.js +0 -1
  185. recce/data/_next/static/chunks/c1ceaa8b-a1e442154d23515e.js +0 -1
  186. recce/data/_next/static/chunks/cd9f8d63-cf0d5a7b0f7a92e8.js +0 -54
  187. recce/data/_next/static/chunks/ce84277d-f42c2c58049cea2d.js +0 -1
  188. recce/data/_next/static/chunks/e24bf851-0f8cbc99656833e7.js +0 -1
  189. recce/data/_next/static/chunks/fee69bc6-f17d36c080742e74.js +0 -1
  190. recce/data/_next/static/chunks/framework-ded83d71b51ce901.js +0 -1
  191. recce/data/_next/static/chunks/main-a0859f1f36d0aa6c.js +0 -1
  192. recce/data/_next/static/chunks/main-app-0225a2255968e566.js +0 -1
  193. recce/data/_next/static/chunks/pages/_app-d5672bf3d8b6371b.js +0 -1
  194. recce/data/_next/static/chunks/pages/_error-ed75be3f25588548.js +0 -1
  195. recce/data/_next/static/chunks/webpack-567d72f0bc0820d5.js +0 -1
  196. recce/data/_next/static/css/c9ecb46a4b21c126.css +0 -14
  197. recce/data/_next/static/media/montserrat-cyrillic-800-normal.22628180.woff2 +0 -0
  198. recce/data/_next/static/media/montserrat-cyrillic-800-normal.31d693bb.woff +0 -0
  199. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.7e2c1e62.woff +0 -0
  200. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.94a63aea.woff2 +0 -0
  201. recce/data/_next/static/media/montserrat-latin-800-normal.6f8fa298.woff2 +0 -0
  202. recce/data/_next/static/media/montserrat-latin-800-normal.97e20d5e.woff +0 -0
  203. recce/data/_next/static/media/montserrat-latin-ext-800-normal.013b84f9.woff2 +0 -0
  204. recce/data/_next/static/media/montserrat-latin-ext-800-normal.aff52ab0.woff +0 -0
  205. recce/data/_next/static/media/montserrat-vietnamese-800-normal.5f21869b.woff +0 -0
  206. recce/data/_next/static/media/montserrat-vietnamese-800-normal.c0035377.woff2 +0 -0
  207. recce/state.py +0 -753
  208. recce_nightly-1.2.0.20250506.dist-info/RECORD +0 -142
  209. tests/test_state.py +0 -123
  210. /recce/data/_next/static/{Kcbs3GEIyH2LxgLYat0es → 52aV_JrNUZU6dMFgvTQEO}/_ssgManifest.js +0 -0
  211. /recce/data/_next/static/chunks/{polyfills-42372ed130431b0a.js → a6dad97d9634a72d.js} +0 -0
  212. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.26.0.20251124.dist-info}/entry_points.txt +0 -0
  213. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.26.0.20251124.dist-info}/licenses/LICENSE +0 -0
@@ -4,47 +4,61 @@ import pytest
4
4
  def test_default_validator():
5
5
  from recce.tasks.core import CheckValidator
6
6
 
7
- CheckValidator().validate({
8
- "name": "test",
9
- "type": "row_count_diff",
10
- "params": {},
11
- })
7
+ CheckValidator().validate(
8
+ {
9
+ "name": "test",
10
+ "type": "row_count_diff",
11
+ "params": {},
12
+ }
13
+ )
12
14
 
13
15
  with pytest.raises(ValueError):
14
- CheckValidator().validate({
15
- "type": "row_count_diff",
16
- })
16
+ CheckValidator().validate(
17
+ {
18
+ "type": "row_count_diff",
19
+ }
20
+ )
17
21
 
18
22
 
19
23
  def test_query_diff_validator():
20
24
  from recce.tasks.query import QueryDiffCheckValidator
21
- QueryDiffCheckValidator().validate({
22
- "name": "test",
23
- "type": "query_diff",
24
- "params": {
25
- "sql_template": "select * from {{ model }}"
26
- },
27
- })
28
- with pytest.raises(ValueError):
29
- QueryDiffCheckValidator().validate({
25
+
26
+ QueryDiffCheckValidator().validate(
27
+ {
30
28
  "name": "test",
31
29
  "type": "query_diff",
32
- })
30
+ "params": {"sql_template": "select * from {{ model }}"},
31
+ }
32
+ )
33
+ with pytest.raises(ValueError):
34
+ QueryDiffCheckValidator().validate(
35
+ {
36
+ "name": "test",
37
+ "type": "query_diff",
38
+ }
39
+ )
33
40
 
34
41
 
35
42
  def test_lineage_diff_validator():
36
43
  from recce.tasks.lineage import LineageDiffCheckValidator
37
- LineageDiffCheckValidator().validate({
38
- "name": "test",
39
- "type": "lineage_diff",
40
- "params": {},
41
- })
42
- LineageDiffCheckValidator().validate({
43
- "name": "test",
44
- "type": "lineage_diff",
45
- "view_options": {},
46
- })
47
- with pytest.raises(ValueError):
48
- LineageDiffCheckValidator().validate({
44
+
45
+ LineageDiffCheckValidator().validate(
46
+ {
47
+ "name": "test",
49
48
  "type": "lineage_diff",
50
- })
49
+ "params": {},
50
+ }
51
+ )
52
+ LineageDiffCheckValidator().validate(
53
+ {
54
+ "name": "test",
55
+ "type": "lineage_diff",
56
+ "view_options": {},
57
+ }
58
+ )
59
+ with pytest.raises(ValueError):
60
+ LineageDiffCheckValidator().validate(
61
+ {
62
+ "type": "lineage_diff",
63
+ }
64
+ )
@@ -1,6 +1,9 @@
1
1
  import pytest
2
+ from jinja2 import Template
3
+ from sqlglot import parse_one
2
4
 
3
5
  from recce.tasks import ProfileDiffTask, ProfileTask
6
+ from recce.tasks.profile import PROFILE_COLUMN_JINJA_TEMPLATE
4
7
 
5
8
  csv_data_curr = """
6
9
  customer_id,name,age
@@ -19,7 +22,7 @@ csv_data_base = """
19
22
 
20
23
  def test_profile(dbt_test_helper):
21
24
  dbt_test_helper.create_model("customers", None, csv_data_curr)
22
- params = dict(model='customers')
25
+ params = dict(model="customers")
23
26
  task = ProfileTask(params)
24
27
  run_result = task.execute()
25
28
 
@@ -28,7 +31,7 @@ def test_profile(dbt_test_helper):
28
31
 
29
32
  def test_profile_with_selected_columns(dbt_test_helper):
30
33
  dbt_test_helper.create_model("customers", None, csv_data_curr)
31
- params = dict(model='customers', columns=['name', 'age'])
34
+ params = dict(model="customers", columns=["name", "age"])
32
35
  task = ProfileTask(params)
33
36
  run_result = task.execute()
34
37
  assert len(run_result.current.data) == 2
@@ -36,7 +39,7 @@ def test_profile_with_selected_columns(dbt_test_helper):
36
39
 
37
40
  def test_profile_diff(dbt_test_helper):
38
41
  dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
39
- params = dict(model='customers')
42
+ params = dict(model="customers")
40
43
  task = ProfileDiffTask(params)
41
44
  run_result = task.execute()
42
45
 
@@ -46,7 +49,7 @@ def test_profile_diff(dbt_test_helper):
46
49
 
47
50
  def test_profile_diff_with_selected_columns(dbt_test_helper):
48
51
  dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
49
- params = dict(model='customers', columns=['name', 'age'])
52
+ params = dict(model="customers", columns=["name", "age"])
50
53
  task = ProfileDiffTask(params)
51
54
  run_result = task.execute()
52
55
  assert len(run_result.current.data) == 2
@@ -57,17 +60,338 @@ def test_validator():
57
60
  from recce.tasks.profile import ProfileCheckValidator
58
61
 
59
62
  def validate(params: dict = {}, view_options: dict = {}):
60
- ProfileCheckValidator().validate({
61
- 'name': 'test',
62
- 'type': 'profile_diff',
63
- 'params': params,
64
- 'view_options': view_options,
65
- })
63
+ ProfileCheckValidator().validate(
64
+ {
65
+ "name": "test",
66
+ "type": "profile_diff",
67
+ "params": params,
68
+ "view_options": view_options,
69
+ }
70
+ )
66
71
 
67
- validate({
68
- 'model': 'customers',
69
- })
72
+ validate(
73
+ {
74
+ "model": "customers",
75
+ }
76
+ )
70
77
 
71
78
  with pytest.raises(ValueError):
72
- validate({
73
- })
79
+ validate({})
80
+
81
+
82
+ def test_profile_column_jinja_template():
83
+
84
+ class DummyAdapter:
85
+ def __init__(self, database_type="duckdb"):
86
+ self.database_type = database_type
87
+
88
+ def quote(self, col):
89
+ quote_marks = {
90
+ "athena": '"',
91
+ "bigquery": "`",
92
+ "databricks": "`",
93
+ "duckdb": '"',
94
+ "postgres": '"',
95
+ "redshift": '"',
96
+ "snowflake": '"',
97
+ "sqlite": '"',
98
+ "sqlserver": '"',
99
+ "trino": '"',
100
+ }
101
+ quote_mark = quote_marks.get(self.database_type, '"')
102
+ return f"{quote_mark}{col}{quote_mark}"
103
+
104
+ class DummyDbt:
105
+ def __init__(self, database_type="Postgres"):
106
+ self.database_type = database_type
107
+
108
+ def type_bigint(self):
109
+ bigint_types = {
110
+ "athena": "BIGINT",
111
+ "bigquery": "INT64",
112
+ "databricks": "BIGINT",
113
+ "duckdb": "BIGINT",
114
+ "postgres": "BIGINT",
115
+ "redshift": "BIGINT",
116
+ "snowflake": "NUMBER",
117
+ "sqlite": "INTEGER",
118
+ "sqlserver": "BIGINT",
119
+ "trino": "BIGINT",
120
+ }
121
+ return bigint_types.get(self.database_type, "bigint")
122
+
123
+ def type_numeric(self):
124
+ numeric_types = {
125
+ "athena": "DECIMAL",
126
+ "bigquery": "NUMERIC",
127
+ "databricks": "DECIMAL",
128
+ "duckdb": "DECIMAL",
129
+ "postgres": "NUMERIC",
130
+ "redshift": "DECIMAL",
131
+ "snowflake": "NUMBER",
132
+ "sqlite": "NUMERIC",
133
+ "sqlserver": "DECIMAL",
134
+ "trino": "DECIMAL",
135
+ }
136
+ return numeric_types.get(self.database_type, "numeric")
137
+
138
+ def type_string(self):
139
+ string_types = {
140
+ "athena": "VARCHAR",
141
+ "bigquery": "STRING",
142
+ "databricks": "STRING",
143
+ "duckdb": "VARCHAR",
144
+ "postgres": "TEXT",
145
+ "redshift": "VARCHAR",
146
+ "snowflake": "VARCHAR",
147
+ "sqlite": "TEXT",
148
+ "sqlserver": "VARCHAR",
149
+ "trino": "VARCHAR",
150
+ }
151
+ return string_types.get(self.database_type, "varchar")
152
+
153
+ test_db_column_types = {
154
+ "athena": [
155
+ "boolean",
156
+ "int",
157
+ "double",
158
+ "decimal",
159
+ "char",
160
+ "string",
161
+ "binary",
162
+ "date",
163
+ "array",
164
+ "struct",
165
+ "map",
166
+ ],
167
+ "bigquery": [
168
+ "array",
169
+ "bool",
170
+ "bytes",
171
+ "date",
172
+ "datetime",
173
+ "interval",
174
+ "json",
175
+ "int64",
176
+ "bignumeric",
177
+ "range",
178
+ "string",
179
+ "struct",
180
+ "time",
181
+ "timestamp",
182
+ ],
183
+ "databricks": [
184
+ "bigint",
185
+ "binary",
186
+ "boolean",
187
+ "date",
188
+ "decimal",
189
+ "double",
190
+ "float",
191
+ "int",
192
+ "interval",
193
+ "void",
194
+ "string",
195
+ "timestamp",
196
+ "array",
197
+ "map",
198
+ "struct",
199
+ "variant",
200
+ "object",
201
+ ],
202
+ "duckdb": [
203
+ "boolean",
204
+ "integer",
205
+ "bigint",
206
+ "real",
207
+ "double",
208
+ "decimal",
209
+ "varchar",
210
+ "date",
211
+ "time",
212
+ "timestamp",
213
+ "blob",
214
+ "array",
215
+ "list",
216
+ "struct",
217
+ "map",
218
+ "union",
219
+ "uuid",
220
+ "json",
221
+ ],
222
+ "postgres": [
223
+ "bigint",
224
+ "bigserial",
225
+ "bit",
226
+ "boolean",
227
+ "box",
228
+ "bytea",
229
+ "character",
230
+ "cidr",
231
+ "circle",
232
+ "date",
233
+ "double precision",
234
+ "inet",
235
+ "integer",
236
+ "interval",
237
+ "json",
238
+ "jsonb",
239
+ "line",
240
+ "lseg",
241
+ "macaddr",
242
+ "money",
243
+ "numeric",
244
+ "path",
245
+ "pg_lsn",
246
+ "point",
247
+ "polygon",
248
+ "real",
249
+ "smallint",
250
+ "smallserial",
251
+ "serial",
252
+ "text",
253
+ "time",
254
+ "timestamp",
255
+ "tsquery",
256
+ "tsvector",
257
+ "txid_snapshot",
258
+ "uuid",
259
+ "xml",
260
+ "array",
261
+ ],
262
+ "redshift": [
263
+ "smallint",
264
+ "integer",
265
+ "bigint",
266
+ "decimal",
267
+ "real",
268
+ "double precision",
269
+ "boolean",
270
+ "char",
271
+ "varchar",
272
+ "date",
273
+ "timestamp",
274
+ "timestamptz",
275
+ "super",
276
+ "time",
277
+ "timetz",
278
+ "varbyte",
279
+ "geometry",
280
+ "geography",
281
+ "hllsketch",
282
+ ],
283
+ "snowflake": [
284
+ "number",
285
+ "decimal",
286
+ "numeric",
287
+ "int",
288
+ "integer",
289
+ "bigint",
290
+ "smallint",
291
+ "tinyint",
292
+ "byteint",
293
+ "float",
294
+ "float4",
295
+ "float8",
296
+ "double",
297
+ "double precision",
298
+ "real",
299
+ "varchar",
300
+ "char",
301
+ "character",
302
+ "string",
303
+ "text",
304
+ "binary",
305
+ "varbinary",
306
+ "boolean",
307
+ "date",
308
+ "datetime",
309
+ "time",
310
+ "timestamp",
311
+ "timestamp_ltz",
312
+ "timestamp_ntz",
313
+ "timestamp_tz",
314
+ "variant",
315
+ "object",
316
+ "array",
317
+ "geography",
318
+ "geometry",
319
+ ],
320
+ "sqlite": ["integer", "real", "text", "blob", "numeric", "boolean", "date", "datetime", "json"],
321
+ "trino": [
322
+ "boolean",
323
+ "tinyint",
324
+ "smallint",
325
+ "integer",
326
+ "bigint",
327
+ "real",
328
+ "double",
329
+ "decimal",
330
+ "varchar",
331
+ "char",
332
+ "varbinary",
333
+ "json",
334
+ "date",
335
+ "time",
336
+ "timestamp",
337
+ "timestamp with time zone",
338
+ "interval year to month",
339
+ "interval day to second",
340
+ "array",
341
+ "map",
342
+ "row",
343
+ "ipaddress",
344
+ "uuid",
345
+ "hyperloglog",
346
+ "p4hyperloglog",
347
+ "qdigest",
348
+ ],
349
+ "sqlserver": [
350
+ "bigint",
351
+ "int",
352
+ "smallint",
353
+ "tinyint",
354
+ "bit",
355
+ "decimal",
356
+ "numeric",
357
+ "money",
358
+ "smallmoney",
359
+ "float",
360
+ "real",
361
+ "date",
362
+ "datetime",
363
+ "datetime2",
364
+ "smalldatetime",
365
+ "time",
366
+ "char",
367
+ "varchar",
368
+ "text",
369
+ "nchar",
370
+ "nvarchar",
371
+ "ntext",
372
+ "binary",
373
+ "varbinary",
374
+ "image",
375
+ "timestamp",
376
+ "uniqueidentifier",
377
+ "xml",
378
+ "cursor",
379
+ "table",
380
+ "sql_variant",
381
+ ],
382
+ }
383
+
384
+ for db_type, column_types in test_db_column_types.items():
385
+ for column_type in column_types:
386
+ context = {
387
+ "column_type": column_type,
388
+ "column_name": "profile_column",
389
+ "db_type": db_type,
390
+ "relation": "test_table",
391
+ "adapter": DummyAdapter(),
392
+ "dbt": DummyDbt(),
393
+ }
394
+
395
+ sql = Template(PROFILE_COLUMN_JINJA_TEMPLATE).render(context)
396
+ dialect = db_type if db_type != "sqlserver" else "tsql"
397
+ parse_one(sql, read=dialect)
tests/tasks/test_query.py CHANGED
@@ -19,7 +19,7 @@ def test_query_diff_in_client(dbt_test_helper):
19
19
  """
20
20
 
21
21
  dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
22
- params = dict(sql_template=f'select * from {{{{ ref("customers") }}}}')
22
+ params = dict(sql_template='select * from {{ ref("customers") }}')
23
23
  task = QueryTask(params)
24
24
  run_result = task.execute()
25
25
  assert len(run_result.current.data) == 3
@@ -41,15 +41,15 @@ def test_query_diff_in_client(dbt_test_helper):
41
41
  """
42
42
 
43
43
  dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
44
- params = dict(sql_template=f'select * from {{{{ ref("customers") }}}}')
44
+ params = dict(sql_template='select * from {{ ref("customers") }}')
45
45
  task = QueryDiffTask(params)
46
46
  run_result = task.execute()
47
47
  assert len(run_result.base.data) == 3
48
48
  assert len(run_result.current.data) == 3
49
49
 
50
50
  params = dict(
51
- base_sql_template=f'select * from {{{{ ref("customers") }}}} where customer_id <= 2',
52
- sql_template=f'select * from {{{{ ref("customers") }}}}',
51
+ base_sql_template='select * from {{ ref("customers") }} where customer_id <= 2',
52
+ sql_template='select * from {{ ref("customers") }}',
53
53
  )
54
54
  task = QueryDiffTask(params)
55
55
  run_result = task.execute()
@@ -73,15 +73,15 @@ def test_query_diff_in_warehouse(dbt_test_helper):
73
73
  """
74
74
 
75
75
  dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
76
- params = dict(sql_template=f'select * from {{{{ ref("customers") }}}}', primary_keys=['customer_id'])
76
+ params = dict(sql_template='select * from {{ ref("customers") }}', primary_keys=["customer_id"])
77
77
  task = QueryDiffTask(params)
78
78
  run_result = task.execute()
79
79
  assert len(run_result.diff.data) == 2
80
80
 
81
81
  params = dict(
82
- base_sql_template=f'select * from {{{{ ref("customers") }}}} where customer_id == 1',
83
- sql_template=f'select * from {{{{ ref("customers") }}}}',
84
- primary_keys=['customer_id'],
82
+ base_sql_template='select * from {{ ref("customers") }} where customer_id == 1',
83
+ sql_template='select * from {{ ref("customers") }}',
84
+ primary_keys=["customer_id"],
85
85
  )
86
86
  task = QueryDiffTask(params)
87
87
  run_result = task.execute()
@@ -92,50 +92,50 @@ def test_validator():
92
92
  from recce.tasks.query import QueryCheckValidator, QueryDiffCheckValidator
93
93
 
94
94
  def validate(params: dict = {}, view_options: dict = {}):
95
- QueryCheckValidator().validate({
96
- 'name': 'test',
97
- 'type': 'query',
98
- 'params': params,
99
- 'view_options': view_options,
100
- })
95
+ QueryCheckValidator().validate(
96
+ {
97
+ "name": "test",
98
+ "type": "query",
99
+ "params": params,
100
+ "view_options": view_options,
101
+ }
102
+ )
101
103
 
102
104
  def validate_diff(params: dict = {}, view_options: dict = {}):
103
- QueryDiffCheckValidator().validate({
104
- 'name': 'test',
105
- 'type': 'query_diff',
106
- 'params': params,
107
- 'view_options': view_options,
108
- })
105
+ QueryDiffCheckValidator().validate(
106
+ {
107
+ "name": "test",
108
+ "type": "query_diff",
109
+ "params": params,
110
+ "view_options": view_options,
111
+ }
112
+ )
109
113
 
110
114
  # query
111
- validate({
112
- 'sql_template': 'select * from abc'
113
- })
115
+ validate({"sql_template": "select * from abc"})
114
116
 
115
117
  # diff in client
116
- validate_diff({
117
- 'sql_template': 'select * from abc'
118
- })
119
- validate_diff({
120
- 'sql_template': 'select * from abc',
121
- 'base_sql_template': 'select * from abc',
122
- })
118
+ validate_diff({"sql_template": "select * from abc"})
119
+ validate_diff(
120
+ {
121
+ "sql_template": "select * from abc",
122
+ "base_sql_template": "select * from abc",
123
+ }
124
+ )
123
125
 
124
126
  # diff in warehouse
125
- validate_diff({
126
- 'primary_keys': ['customer_id'],
127
- 'sql_template': 'select * from abc',
128
- })
129
- validate_diff({
130
- 'sql_template': 'select * from abc',
131
- 'base_sql_template': 'select * from abc',
132
- 'primary_keys': ['customer_id']
133
- })
134
- validate_diff({
135
- 'sql_template': 'select * from abc',
136
- 'base_sql_template': 'select * from abc',
137
- 'primary_keys': ['customer_id']
138
- })
127
+ validate_diff(
128
+ {
129
+ "primary_keys": ["customer_id"],
130
+ "sql_template": "select * from abc",
131
+ }
132
+ )
133
+ validate_diff(
134
+ {"sql_template": "select * from abc", "base_sql_template": "select * from abc", "primary_keys": ["customer_id"]}
135
+ )
136
+ validate_diff(
137
+ {"sql_template": "select * from abc", "base_sql_template": "select * from abc", "primary_keys": ["customer_id"]}
138
+ )
139
139
 
140
140
  # invalid
141
141
  with pytest.raises(ValueError):
@@ -145,7 +145,7 @@ def test_validator():
145
145
  validate_diff()
146
146
 
147
147
  with pytest.raises(ValueError):
148
- validate_diff({'sql_template': 123, 'primary_keys': 'xyz'})
148
+ validate_diff({"sql_template": 123, "primary_keys": "xyz"})
149
149
 
150
150
  with pytest.raises(ValueError):
151
- validate_diff({'sql_template': 's', 'primary_keys': 'xyz'})
151
+ validate_diff({"sql_template": "s", "primary_keys": "xyz"})