relationalai 0.11.2__py3-none-any.whl → 0.11.4__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.
Files changed (42) hide show
  1. relationalai/clients/snowflake.py +44 -15
  2. relationalai/clients/types.py +1 -0
  3. relationalai/clients/use_index_poller.py +446 -178
  4. relationalai/early_access/builder/std/__init__.py +1 -1
  5. relationalai/early_access/dsl/bindings/csv.py +4 -4
  6. relationalai/semantics/internal/internal.py +22 -4
  7. relationalai/semantics/lqp/executor.py +69 -18
  8. relationalai/semantics/lqp/intrinsics.py +23 -0
  9. relationalai/semantics/lqp/model2lqp.py +16 -6
  10. relationalai/semantics/lqp/passes.py +3 -4
  11. relationalai/semantics/lqp/primitives.py +38 -14
  12. relationalai/semantics/metamodel/builtins.py +152 -11
  13. relationalai/semantics/metamodel/factory.py +3 -2
  14. relationalai/semantics/metamodel/helpers.py +78 -2
  15. relationalai/semantics/reasoners/graph/core.py +343 -40
  16. relationalai/semantics/reasoners/optimization/solvers_dev.py +20 -1
  17. relationalai/semantics/reasoners/optimization/solvers_pb.py +24 -3
  18. relationalai/semantics/rel/compiler.py +5 -17
  19. relationalai/semantics/rel/executor.py +2 -2
  20. relationalai/semantics/rel/rel.py +6 -0
  21. relationalai/semantics/rel/rel_utils.py +37 -1
  22. relationalai/semantics/rel/rewrite/extract_common.py +153 -242
  23. relationalai/semantics/sql/compiler.py +540 -202
  24. relationalai/semantics/sql/executor/duck_db.py +21 -0
  25. relationalai/semantics/sql/executor/result_helpers.py +7 -0
  26. relationalai/semantics/sql/executor/snowflake.py +9 -2
  27. relationalai/semantics/sql/rewrite/denormalize.py +4 -6
  28. relationalai/semantics/sql/rewrite/recursive_union.py +23 -3
  29. relationalai/semantics/sql/sql.py +120 -46
  30. relationalai/semantics/std/__init__.py +9 -4
  31. relationalai/semantics/std/datetime.py +363 -0
  32. relationalai/semantics/std/math.py +77 -0
  33. relationalai/semantics/std/re.py +83 -0
  34. relationalai/semantics/std/strings.py +1 -1
  35. relationalai/tools/cli_controls.py +445 -60
  36. relationalai/util/format.py +78 -1
  37. {relationalai-0.11.2.dist-info → relationalai-0.11.4.dist-info}/METADATA +3 -2
  38. {relationalai-0.11.2.dist-info → relationalai-0.11.4.dist-info}/RECORD +41 -39
  39. relationalai/semantics/std/dates.py +0 -213
  40. {relationalai-0.11.2.dist-info → relationalai-0.11.4.dist-info}/WHEEL +0 -0
  41. {relationalai-0.11.2.dist-info → relationalai-0.11.4.dist-info}/entry_points.txt +0 -0
  42. {relationalai-0.11.2.dist-info → relationalai-0.11.4.dist-info}/licenses/LICENSE +0 -0
@@ -1,14 +1,39 @@
1
1
  def humanized_duration(ms: int) -> str:
2
+ """Format duration in milliseconds to human-readable format with spaces.
3
+
4
+ Converts milliseconds to a human-readable string with up to 3 time components
5
+ (days, hours, minutes, seconds) separated by spaces.
6
+
7
+ Args:
8
+ ms: Duration in milliseconds
9
+
10
+ Returns:
11
+ Formatted string like '1h 2m 3.5s' (max 3 components).
12
+ Returns empty string for zero duration.
13
+
14
+ Examples:
15
+ >>> humanized_duration(1000)
16
+ '1.0s'
17
+ >>> humanized_duration(90000)
18
+ '1m 30.0s'
19
+ >>> humanized_duration(3665000)
20
+ '1h 1m 5.0s'
21
+ >>> humanized_duration(95400000)
22
+ '1d 2h 30m'
23
+ """
24
+ # Convert milliseconds to other time units
2
25
  seconds = ms / 1000
3
26
  minutes = seconds / 60
4
27
  hours = minutes / 60
5
28
  days = hours / 24
6
29
 
30
+ # Extract display components using modulo to get remainders
7
31
  display_days = int(days)
8
32
  display_hours = int(hours % 24)
9
33
  display_minutes = int(minutes % 60)
10
34
  display_seconds = seconds % 60
11
35
 
36
+ # Build list of non-zero time components
12
37
  parts = []
13
38
  if display_days > 0:
14
39
  parts.append(f"{display_days}d")
@@ -17,10 +42,62 @@ def humanized_duration(ms: int) -> str:
17
42
  if display_minutes > 0:
18
43
  parts.append(f"{display_minutes}m")
19
44
  if display_seconds > 0:
20
- parts.append(f"{display_seconds:,.1f}s")
45
+ # Show seconds with one decimal place (no thousand separators for time)
46
+ parts.append(f"{display_seconds:.1f}s")
47
+
48
+ # Return up to 3 components, space-separated
21
49
  return " ".join(parts[:3])
22
50
 
51
+
52
+ def format_duration(duration_seconds: float) -> str:
53
+ """Format duration in seconds to human-readable format.
54
+
55
+ Args:
56
+ duration_seconds: Duration in seconds
57
+
58
+ Returns:
59
+ Formatted string like '500ms', '2.5s', '1m30s', '1h5m'
60
+
61
+ Examples:
62
+ >>> format_duration(0.5)
63
+ '500ms'
64
+ >>> format_duration(2.5)
65
+ '2.5s'
66
+ >>> format_duration(90)
67
+ '1m30s'
68
+ >>> format_duration(3665)
69
+ '1h1m'
70
+ """
71
+ # For durations less than 1 second, show milliseconds
72
+ if duration_seconds < 1:
73
+ milliseconds = round(duration_seconds * 1000)
74
+ # Handle edge case where rounding gives us 1000ms
75
+ if milliseconds >= 1000:
76
+ return "1.0s"
77
+ return f"{milliseconds}ms"
78
+
79
+ # For durations less than 1 minute, show seconds with one decimal
80
+ elif duration_seconds < 60:
81
+ return f"{round(duration_seconds, 1)}s"
82
+
83
+ # For durations less than 1 hour, show minutes and seconds
84
+ elif duration_seconds < 3600:
85
+ minutes = int(duration_seconds // 60)
86
+ seconds = int(duration_seconds % 60)
87
+ if seconds == 0:
88
+ return f"{minutes}m"
89
+ else:
90
+ return f"{minutes}m{seconds}s"
91
+ else:
92
+ hours = int(duration_seconds // 3600)
93
+ minutes = int((duration_seconds % 3600) // 60)
94
+ if minutes == 0:
95
+ return f"{hours}h"
96
+ else:
97
+ return f"{hours}h{minutes}m"
98
+
23
99
  def humanized_bytes(bytes: int) -> str:
100
+ """Format bytes to human-readable format."""
24
101
  if bytes < 1024:
25
102
  return f"{bytes} B"
26
103
  elif bytes < 1024 ** 2:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: relationalai
3
- Version: 0.11.2
3
+ Version: 0.11.4
4
4
  Summary: RelationalAI Library and CLI
5
5
  Author-email: RelationalAI <support@relational.ai>
6
6
  License-File: LICENSE
@@ -12,7 +12,7 @@ Requires-Dist: cryptography
12
12
  Requires-Dist: gravis
13
13
  Requires-Dist: inquirerpy
14
14
  Requires-Dist: lqp==0.1.16
15
- Requires-Dist: nicegui
15
+ Requires-Dist: nicegui==2.16.1
16
16
  Requires-Dist: numpy<2
17
17
  Requires-Dist: opentelemetry-api
18
18
  Requires-Dist: opentelemetry-exporter-otlp-proto-http
@@ -52,6 +52,7 @@ Requires-Dist: pytest-mock; extra == 'dev'
52
52
  Requires-Dist: pytest-snapshot; extra == 'dev'
53
53
  Requires-Dist: pytest-timeout; extra == 'dev'
54
54
  Requires-Dist: ruff; extra == 'dev'
55
+ Requires-Dist: scipy; extra == 'dev'
55
56
  Requires-Dist: sqlite-utils; extra == 'dev'
56
57
  Requires-Dist: sympy; extra == 'dev'
57
58
  Requires-Dist: tablescope; extra == 'dev'
@@ -27,15 +27,15 @@ relationalai/clients/export_procedure.py.jinja,sha256=nhvVcs5hQyWExFDuROQbi1VyYz
27
27
  relationalai/clients/hash_util.py,sha256=pZVR1FX3q4G_19p_r6wpIR2tIM8_WUlfAR7AVZJjIYM,1495
28
28
  relationalai/clients/profile_polling.py,sha256=pUH7WKH4nYDD0SlQtg3wsWdj0K7qt6nZqUw8jTthCBs,2565
29
29
  relationalai/clients/result_helpers.py,sha256=wDSD02Ngx6W-YQqBIGKnpXD4Ju3pA1e9Nz6ORRI6SRI,17808
30
- relationalai/clients/snowflake.py,sha256=DDr5HgttyYg_baBQ1D-190f5GiRmxo9SOxJy2IDgC8Q,153865
31
- relationalai/clients/types.py,sha256=gZk8WJiiZqkOrolQ0aU6boZr_4GCrg_N83pRdVKC4Zs,2749
32
- relationalai/clients/use_index_poller.py,sha256=XWnJK5Z4blpidpF3JzOBsuEOZi9pbBYL7TiNjPHnzpE,33645
30
+ relationalai/clients/snowflake.py,sha256=lfMwypFnsw18ZG4ixOCuEqZwf0lvvthk4pPtj97pZNE,155717
31
+ relationalai/clients/types.py,sha256=z33RlnXFml-aVAtZ1pJsbixrGnlPfhkAjZXM_ySZGuY,2776
32
+ relationalai/clients/use_index_poller.py,sha256=rQaHmlNLYDQ4NJh3i6CVAS1XxUjazwzTv-OiacrldGI,44662
33
33
  relationalai/clients/util.py,sha256=3iLY5DgUkQcRAPXrvP4xdIYZtc3trrryy5jfX2QAFEA,12014
34
34
  relationalai/early_access/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  relationalai/early_access/builder/__init__.py,sha256=mrR-aGLPquUGc_e9-DOkVCCCo8QRE5A56GTTtgILNa4,993
36
36
  relationalai/early_access/builder/builder/__init__.py,sha256=QOVGGdEf-5OirBLjY75W4ANiqGKDknwAAl3YUFEzHVI,1462
37
37
  relationalai/early_access/builder/snowflake/__init__.py,sha256=wTL4AY0sFeZAk0SZKQuMbXOLyaYq-fuiG2hj_nh3L4Y,335
38
- relationalai/early_access/builder/std/__init__.py,sha256=u_wqev15xN0jn244Xd82KgMbiEO2_9qYw1qVwkzd1SU,514
38
+ relationalai/early_access/builder/std/__init__.py,sha256=gNhYq4DqN4a68d8DpUe8ECyVdFeOM0NK-EvuVCpOZHg,526
39
39
  relationalai/early_access/builder/std/decimals/__init__.py,sha256=yv6oS-ea8Db2Qc-GTSTCQacmjj-6_KAaUwFpUA0aoa8,317
40
40
  relationalai/early_access/builder/std/integers/__init__.py,sha256=0BNLdIZ3p1yvtQo9RCZfXwXNqk6uWsdW7WaWoyAdmOY,373
41
41
  relationalai/early_access/builder/std/math/__init__.py,sha256=63xJuisAC4NurB9djBme74DNXxIPxbTAPC6hmGzZODM,409
@@ -60,7 +60,7 @@ relationalai/early_access/dsl/adapters/owl/model.py,sha256=D9ZcFygy2cE0L-G149F_g
60
60
  relationalai/early_access/dsl/adapters/owl/parser.py,sha256=5tbfOOwPwrTwr9t3hzH9FBOwMQUu8SEOZfd0V4D75cc,7165
61
61
  relationalai/early_access/dsl/bindings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  relationalai/early_access/dsl/bindings/common.py,sha256=6xiYkGkS5JFNOxoFChK2Aqy-G2YGcry3zaJSbK811Q4,16772
63
- relationalai/early_access/dsl/bindings/csv.py,sha256=6cfKunQCTP6gUPakcTcgcfAB4WVppBePEq25EHkvkUY,6876
63
+ relationalai/early_access/dsl/bindings/csv.py,sha256=5vkGRok5APHNSSAhgGvpFUXE1HtQwI8GV2h8WPuGfVk,6900
64
64
  relationalai/early_access/dsl/bindings/snowflake.py,sha256=wsX6Lc35mAE_9PZ00xQkhjaxaQxxIEf6lorin5Tsny4,2334
65
65
  relationalai/early_access/dsl/bindings/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
66
  relationalai/early_access/dsl/bindings/legacy/binding_models.py,sha256=BpL6-KNEkxJyy_WaKmmRh_MsJUa8PDwnfzWtoVsMpMU,5735
@@ -255,30 +255,31 @@ relationalai/semantics/devtools/compilation_manager.py,sha256=XBqG_nYWtK3s_J6MeC
255
255
  relationalai/semantics/devtools/extract_lqp.py,sha256=gxI3EvPUTPAkwgnkCKAkEm2vA6QkLfoM8AXXiVz0c34,3696
256
256
  relationalai/semantics/internal/__init__.py,sha256=JXrpFaL-fdZrvKpWTEn1UoLXITOoTGnAYwmgeiglhSk,774
257
257
  relationalai/semantics/internal/annotations.py,sha256=NuOcaca6H8osWqJAwe9nxezu10X2sPV7ti7iROAxiBM,267
258
- relationalai/semantics/internal/internal.py,sha256=b_kM7kkIrmM86AE9ZkwubRazOEo5tIZgUo7QyWbtTOs,147462
258
+ relationalai/semantics/internal/internal.py,sha256=5Wf0XitUqWo0j30aRTtkQ6KKsBDmD3mklLitpPSzB90,148333
259
259
  relationalai/semantics/internal/snowflake.py,sha256=DR6rgbPawen2ZOFegRuPkXt8aQUfciiCYzDI74u1Iwc,13036
260
260
  relationalai/semantics/lqp/__init__.py,sha256=XgcQZxK-zz_LqPDVtwREhsIvjTuUIt4BZhIedCeMY-s,48
261
261
  relationalai/semantics/lqp/builtins.py,sha256=N1hJwyvwgFvBbt2X7-4U-Pq1LVOYV-zAUeSqS39OZcQ,515
262
262
  relationalai/semantics/lqp/compiler.py,sha256=Nury1gPw_-Oi_mqT1-rhr13L4UmyIP2BGuotbuklQKA,949
263
263
  relationalai/semantics/lqp/constructors.py,sha256=8U4eUL8-m1wYRQnws_YWC1coGquTugVH5YC0Zek6VT8,2309
264
- relationalai/semantics/lqp/executor.py,sha256=CXS7RUFHT8s7C0ucM5Xp3m2J0X-RCJRn2fgeMBFwSbQ,16776
264
+ relationalai/semantics/lqp/executor.py,sha256=At0IdBlNlOM0E533V0urRgeIkfbv-pPWuQ_sfRkKqPQ,18926
265
+ relationalai/semantics/lqp/intrinsics.py,sha256=Pb1mLIme7Q-5Y-CVacUOEvapfhKs076bgtRNi3f0ayY,833
265
266
  relationalai/semantics/lqp/ir.py,sha256=DUw0ltul0AS9CRjntNlmllWTwXpxMyYg4iJ9t7NFYMA,1791
266
- relationalai/semantics/lqp/model2lqp.py,sha256=47KGeYmzgAaKwdXyfDtLUKORdOzRYuu848p6NioCm7c,31220
267
- relationalai/semantics/lqp/passes.py,sha256=9a4rbTRzNlSYW8VosnqHmOH0R-fylJFOP3MMSaaJjts,27658
267
+ relationalai/semantics/lqp/model2lqp.py,sha256=L63A2ECLiLTbUoZB7wTB2dP0ahUAA-8WhxiddVO2znQ,31647
268
+ relationalai/semantics/lqp/passes.py,sha256=TBsYmWYh4qZtKzlSiZcJJDt3-Bwl_wRv0c9L8P2H1fE,27683
268
269
  relationalai/semantics/lqp/pragmas.py,sha256=FzzldrJEAZ1AIcEw6D-FfaVg3CoahRYgPCFo7xHfg1g,375
269
- relationalai/semantics/lqp/primitives.py,sha256=xfJh-yUOyqYAF3IYkVU9Fzij4ukYzSPORYppUHSeYj4,9642
270
+ relationalai/semantics/lqp/primitives.py,sha256=Gbh6cohoAArhqEJTN_TgIRc7wmtdxXt231NRW0beEj0,10898
270
271
  relationalai/semantics/lqp/result_helpers.py,sha256=oYpLoTBnzsiyOVIWA2rLMHlgs7P7BoEkqthQ2aMosnk,10123
271
272
  relationalai/semantics/lqp/types.py,sha256=3TZ61ybwNV8lDyUMujZIWNFz3Fgn4uifsJb8ExfoMDg,4508
272
273
  relationalai/semantics/lqp/utils.py,sha256=x8dcfVoyqzCznNFtI4qSNSL-vWcdxzC-QrnFJlAARXs,6121
273
274
  relationalai/semantics/lqp/validators.py,sha256=YO_ciSgEVNILWUbkxIagKpIxI4oqV0fRSTO2Ok0rPJk,1526
274
275
  relationalai/semantics/metamodel/__init__.py,sha256=I-XqQAGycD0nKkKYvnF3G9d0QK_1LIM4xXICw8g8fBA,805
275
- relationalai/semantics/metamodel/builtins.py,sha256=u0qet3aGVgND7CYrLhyYADVDqy5pcXO43ox_zI7gTs8,27514
276
+ relationalai/semantics/metamodel/builtins.py,sha256=0NIy94ay2-Yy0tvL750kRLoavyjnwARdmn07hn6LDFs,35310
276
277
  relationalai/semantics/metamodel/compiler.py,sha256=XBsAnbFwgZ_TcRry6yXGWLyw_MaO2WJDp1EnC_ubhps,4525
277
278
  relationalai/semantics/metamodel/dataflow.py,sha256=wfj1tARrR4yEAaTwUTrAcxEcz81VkUal4U_AX1esovk,3929
278
279
  relationalai/semantics/metamodel/dependency.py,sha256=YU-nTm9Hq6ufkwoA5D1iPciGw7WW6Hk4Cyq0EQbkl2s,32845
279
280
  relationalai/semantics/metamodel/executor.py,sha256=k9IpWdCOa-Pl6DQFP8Wd0p4NFUnNeELTxNa-j9RyKVY,2572
280
- relationalai/semantics/metamodel/factory.py,sha256=HBzSOokqJjA5YPqwv4upLQKav1ehbKaOI07sT55U5uM,12507
281
- relationalai/semantics/metamodel/helpers.py,sha256=B31-nzpJV5BHSBh8XKMtu_0EZh-Lcn1lxqsZgCwnjzw,12074
281
+ relationalai/semantics/metamodel/factory.py,sha256=Vk3ASwWan08mfGehoOOwMixuU_mEbG2vNl8JLSCJ2OU,12581
282
+ relationalai/semantics/metamodel/helpers.py,sha256=F70rZUzBtVf7VfQRC3XnwxJPvbz_tQP4fCdUeysZsUQ,15342
282
283
  relationalai/semantics/metamodel/ir.py,sha256=4Xl3oc92Q7_s33axtrZUXr-GL8VGJsKc7yaSNcO6jXY,33578
283
284
  relationalai/semantics/metamodel/types.py,sha256=m3NolF3B_fBSnkQKA9o1feEawaW7RhR-t6W9OSxSFfc,11492
284
285
  relationalai/semantics/metamodel/util.py,sha256=cmSmeww34JVMqcFudwVAY820IPM2ETSELJylwJ3GRJk,16654
@@ -299,7 +300,7 @@ relationalai/semantics/metamodel/typer/typer.py,sha256=jBo0CwY6G0qKBzqoAmQ09dPtc
299
300
  relationalai/semantics/reasoners/__init__.py,sha256=Tu4U26rrkBIzAk3a4tXRJaeD5mAtK9Z7JXh2c6VJ-J4,249
300
301
  relationalai/semantics/reasoners/graph/README.md,sha256=QgKEXTllp5PO-yK8oDfMx1PNTYF2uVoneMRKsWTY5GU,23953
301
302
  relationalai/semantics/reasoners/graph/__init__.py,sha256=jSXR6J05SQZdjxQ5Y-ovqFqGTAXCOWeQDcvpfoBYgDA,1282
302
- relationalai/semantics/reasoners/graph/core.py,sha256=7nE8XTJYkPiC4V9T99DZtWtwz4yvmYo0mWMlV8cy3pg,246651
303
+ relationalai/semantics/reasoners/graph/core.py,sha256=pdjfEUlPtX3rbVObqG9RuhUckaFSkUym-cmZmmxrPpc,262065
303
304
  relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md,sha256=Givh0W6B6Hlow6TpmK-8adpEYd8b3O_WmdgMOQIyKs0,55749
304
305
  relationalai/semantics/reasoners/graph/paths/README.md,sha256=ydm6CzMN_vOOgq7a6_hBCiyGi3D6g5gxAbf4OXbQbDE,3433
305
306
  relationalai/semantics/reasoners/graph/paths/__init__.py,sha256=oCoDJVg4moGe0tNMNeRn7XQqa1AIEZGlxAiaD5bBahg,211
@@ -367,41 +368,42 @@ relationalai/semantics/reasoners/graph/paths/utilities/utilities.py,sha256=OnqVd
367
368
  relationalai/semantics/reasoners/graph/tests/README.md,sha256=XbauTzt6VA_YEOcrlZwsu4WOW5UoWV8M6F57wmxe5QU,1023
368
369
  relationalai/semantics/reasoners/optimization/__init__.py,sha256=ceDYhGtFuewYGILKcjpuNHnTaCK2qc7pmJEsDWUfrEo,598
369
370
  relationalai/semantics/reasoners/optimization/common.py,sha256=TVa9n9n97BwfMyYOTt895kkNiNkEX8WbaqReYM1PkuQ,1107
370
- relationalai/semantics/reasoners/optimization/solvers_dev.py,sha256=I3v4g3B03iYoDkxzD1VyyQ5SQ0U8miNUrOnlKIp8dhI,23072
371
- relationalai/semantics/reasoners/optimization/solvers_pb.py,sha256=usoRZ--xfy9jpOiVajVghEBC0O6JEx5LJpYwVPEjcuI,21053
371
+ relationalai/semantics/reasoners/optimization/solvers_dev.py,sha256=BjFcEfmqmdxM6jnd34pt1AlkrdwHd_HapqpB2oIvNP4,24142
372
+ relationalai/semantics/reasoners/optimization/solvers_pb.py,sha256=ryNARpyph3uvr1dhWb7pNU3uuxuL1FLZZiTqFcr3Xf8,22148
372
373
  relationalai/semantics/rel/__init__.py,sha256=pMlVTC_TbQ45mP1LpzwFBBgPxpKc0H3uJDvvDXEWzvs,55
373
374
  relationalai/semantics/rel/builtins.py,sha256=bLMX4pJ62J62qn-TX5WQWl3Nhhy6q9Zz827pY3ihaBc,1286
374
- relationalai/semantics/rel/compiler.py,sha256=nbSKTLo_yiJeWVhEli3I2qxZagQ0ULVNi7t_xs-RxtE,42827
375
- relationalai/semantics/rel/executor.py,sha256=TE-DmvIIZZJqeClY9Bk8wK7mvRI5NjSQycPuLlrN4Uo,14870
376
- relationalai/semantics/rel/rel.py,sha256=Sxunq2ML44SL_2I8atV0nqmZ8Tx4xCYn1vQXPFLPJo4,15451
377
- relationalai/semantics/rel/rel_utils.py,sha256=fwYp-v7jRX852JLR-rvpN9Mo_yJBgY8knigoRi0oMDE,7674
375
+ relationalai/semantics/rel/compiler.py,sha256=9d0-75t08vkdS5n3wvyCN68qlxVywIZ8JD7sph4f5LM,42298
376
+ relationalai/semantics/rel/executor.py,sha256=BcQUJht5G2so2Af9GszLBTK90LqFUmv3gshRGFeiG-s,14943
377
+ relationalai/semantics/rel/rel.py,sha256=9I_V6dQ83QRaLzq04Tt-KjBWhmNxNO3tFzeornBK4zc,15738
378
+ relationalai/semantics/rel/rel_utils.py,sha256=F14Ch8mn45J8SmM7HZnIHUNqDnb3WQLnkEGLme04iBk,9386
378
379
  relationalai/semantics/rel/rewrite/__init__.py,sha256=Ke85L9DMO_d6qQbjb17k_LoMqar8-vOHKmxHGynIh3s,170
379
380
  relationalai/semantics/rel/rewrite/cdc.py,sha256=I6DeMOZScx-3UAVoSCMn9cuOgLzwdvJVKNwsgFa6R_k,10390
380
- relationalai/semantics/rel/rewrite/extract_common.py,sha256=gA6kP6NCw49aodvAOt8LQmb7WGAeYeNfL6Ltqdrstiw,21318
381
+ relationalai/semantics/rel/rewrite/extract_common.py,sha256=TY4wYhMy6bbKC9YZqrBeQgaZ41Sf4BCI3Zy26yavgAM,17301
381
382
  relationalai/semantics/rel/rewrite/quantify_vars.py,sha256=wYMEXzCW_D_Y_1rSLvuAAqw9KN1oIOn_vIMxELzRVb4,11568
382
383
  relationalai/semantics/snowflake/__init__.py,sha256=BW_zvPQBWGTAtY6cluG6tDDG-QmU_jRb-F7PeCpDhIU,134
383
384
  relationalai/semantics/sql/__init__.py,sha256=59uuKmQOFUzwlYwc7anSuwhQ45bJTYVmd9nOJXr9mQs,80
384
- relationalai/semantics/sql/compiler.py,sha256=fIB7dPeZPNalxKMY5wha9dk_ec4qCrPYf7pX7jJCGJs,110195
385
- relationalai/semantics/sql/sql.py,sha256=UVtdtZvMZG1WKmGIjBAFWLe8XR1thkw5YSih-8uXk4I,14072
385
+ relationalai/semantics/sql/compiler.py,sha256=4NeOp4YnMZz25IfLpPeEWL1iO46y8h2D0HW05d4RY4A,128816
386
+ relationalai/semantics/sql/sql.py,sha256=7nUnm0RbHlOGSGQbnFrgzPYdmnoppifQ5jylR5Wtgcc,17122
386
387
  relationalai/semantics/sql/executor/__init__.py,sha256=F3HqQPJVP9wgV3rkwI5jy1_QBCD_3qj2IGxbdT_pX9k,120
387
- relationalai/semantics/sql/executor/duck_db.py,sha256=Tq22vTWU4M0ppOGZI2dcHzN1GGrAdJ9iV-eO_9LCsqQ,1095
388
- relationalai/semantics/sql/executor/result_helpers.py,sha256=j2IpyDTIdmsnBxx-8R-6S6TGe7c9wuC-vXd5nml3E3o,2844
389
- relationalai/semantics/sql/executor/snowflake.py,sha256=mB1UUbUtGfce30ttDhSSL8_YeRZnG3WTX9eCgN3P8VY,5439
388
+ relationalai/semantics/sql/executor/duck_db.py,sha256=pS_93nV5vKPnjkK62fc0YHHFdRyBEHlXe_Y4H2zB6lQ,1654
389
+ relationalai/semantics/sql/executor/result_helpers.py,sha256=kVfspHHuzyq4SNklrtvhYte1wqRFzct-dAKin_lOmR4,3215
390
+ relationalai/semantics/sql/executor/snowflake.py,sha256=GMfeutObRWOUnH5UVflHZgFxn-soUtjTky37daBtBi4,5825
390
391
  relationalai/semantics/sql/rewrite/__init__.py,sha256=AT1WR0rqQHQ7E06NLoVym0zrZpBVPqK85uRFNJUTDp4,254
391
- relationalai/semantics/sql/rewrite/denormalize.py,sha256=tiVM14RuHAYuta7xaYkVdWI2vq70E4TWzzFt71vyBIg,9072
392
+ relationalai/semantics/sql/rewrite/denormalize.py,sha256=gPF0s1edthoHfuBIdS9-hnEaX5RFYBdtOlK5iAfB5CA,9040
392
393
  relationalai/semantics/sql/rewrite/double_negation.py,sha256=QXynhjwfPW52Hpdo78VWPNk2TXe_mMTWYN470in51z8,1710
393
- relationalai/semantics/sql/rewrite/recursive_union.py,sha256=NZf9vaxQKiTioHXI1kMvPrXelU9nDMz9xUYnTkVu7vs,4339
394
+ relationalai/semantics/sql/rewrite/recursive_union.py,sha256=PdcGWjFiyrShb3M45tFyIYErmc75DK1HAMMP7fVhxbk,5208
394
395
  relationalai/semantics/sql/rewrite/sort_output_query.py,sha256=Nc-34OOPwfavoTWXhkN1an56V_9Z3OB2NCXE8sUswqk,11130
395
- relationalai/semantics/std/__init__.py,sha256=pYW30Ubi19j2eRL35K3rKmMJFQxMYd4k0S3OIOtbtnc,1701
396
+ relationalai/semantics/std/__init__.py,sha256=kLkMl81WwLn7vLPyuIccDooeWqS3oLk8XlyWghH-mE4,1848
396
397
  relationalai/semantics/std/constraints.py,sha256=9S6z-aZvlx1bRity72h9J6UrdSPCI76IEpftzt2M0ko,2050
397
- relationalai/semantics/std/dates.py,sha256=lLH6AbAuHu0UgrJTofSOiPUy6t4TZOfVDbR2FEf8TJ0,8471
398
+ relationalai/semantics/std/datetime.py,sha256=C3pg8ca7U7cHn31SeaIbd_G_WkyuXH4uZaCW1JQnQn8,14839
398
399
  relationalai/semantics/std/decimals.py,sha256=aWySCSR6XliFSYkzj-s_gxvlALC0G4nbpRo_7VD5Tl8,2403
399
400
  relationalai/semantics/std/floats.py,sha256=WswJaQBytGDtacUq6Ght5zGmZFNHHBjvthRqXNNKar8,243
400
401
  relationalai/semantics/std/integers.py,sha256=wacxpVzNccJN4Lcfb5Nh5tssIztp32rTVQfLBl7MGKI,740
401
- relationalai/semantics/std/math.py,sha256=rIun4nEAPF69HwZtxrZPvpk0Q6xmALfdMUY5_j-1OOQ,2205
402
+ relationalai/semantics/std/math.py,sha256=583CpP4J-OBSfId4-iYjBikWL-97BxfAy59rOxUKaTQ,5425
402
403
  relationalai/semantics/std/pragmas.py,sha256=3QyAXv5W5GCbMGdBw7_F-VMovv3gMfgjmXvciqXqBFA,400
404
+ relationalai/semantics/std/re.py,sha256=8XvWWC85OCE8HnfLbQzOPvSGv9ayFkM8ppVkrRH82BU,3424
403
405
  relationalai/semantics/std/std.py,sha256=Ql27y2Rs0d1kluktWi-t6_M_uYIxQUfO94GjlVfiNbI,462
404
- relationalai/semantics/std/strings.py,sha256=ZWxwFAcWLkthiD5PmdycirAuy3mHfc4aKj5uugOhDwA,2703
406
+ relationalai/semantics/std/strings.py,sha256=Q_7kvx5dud6gppNURHOi4SMvgZNPRuWwEKDIPSEIOJI,2702
405
407
  relationalai/semantics/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
406
408
  relationalai/semantics/tests/logging.py,sha256=oJTrUS_Bq6WxqqO8QLtrjdkUB02Uu5erZ7FTl__-lNY,1432
407
409
  relationalai/semantics/tests/test_snapshot_abstract.py,sha256=IVQ72lBIpYJLOXGn26Yjb8Tp1PQ67kcSOUKKb4-I7Fw,6051
@@ -418,7 +420,7 @@ relationalai/std/strings.py,sha256=vHvex_W5GHhhsVws6Dfyl4w1EHdbDE3nPjT09DnpvSE,4
418
420
  relationalai/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
419
421
  relationalai/tools/cleanup_snapshots.py,sha256=s1q1ophi1RmiTZ9QQolQ6q1K9ZwseCaOuDtI1Rm99MQ,3434
420
422
  relationalai/tools/cli.py,sha256=k7r1VG9YiY3o8ZqgEhWI2naYyMzKyJ2gR-KAL-vfzIs,76195
421
- relationalai/tools/cli_controls.py,sha256=PeLHDU7hKkd6N2b_ScvW8qkrB8y214ZQqLRQuawVI6I,55605
423
+ relationalai/tools/cli_controls.py,sha256=6k2nu6km9IYGDwG7pSZGBXrEN64Ehw0tamKgcPotZoM,71822
422
424
  relationalai/tools/cli_helpers.py,sha256=r-gJnWnb3d6yIn_ccyp3qx_Vpqh-FINCFMyPBVCA-Jg,14041
423
425
  relationalai/tools/constants.py,sha256=mDdWelpf-u9tb0tspFgq8V0fCxLSzbS0Hl9WGJMJa_4,4417
424
426
  relationalai/tools/debugger.py,sha256=yb03qO8ENHG2rBOPOF-rPKHGrJmaNy6iWXijg6T0dUI,6881
@@ -431,7 +433,7 @@ relationalai/tools/snapshot_viewer.py,sha256=60DW41X4NpjxmPjf1B8mG3oIocHMLLNEbTh
431
433
  relationalai/util/__init__.py,sha256=FcHFPzeyDcQwENQg2KA70lBsFx5TtN7xo0quy_cJDQI,208
432
434
  relationalai/util/clean_up_databases.py,sha256=f7L5CtJkQCSm5Tms98Q6JrhZShHJltlxMYkq_0xvzgY,3120
433
435
  relationalai/util/constants.py,sha256=rq6c1Q5tLIewiG_M_lUtRAbmrKFUUL1jfl_nxU0989M,882
434
- relationalai/util/format.py,sha256=eQPR9a2-A5Vks183M3D2uQIP_lPwRD8Tg1KBZKnNb0Q,1340
436
+ relationalai/util/format.py,sha256=fLRovumUa2cu0_2gy3O5vaEbpND4p9_IIgr-vDaIGDc,3754
435
437
  relationalai/util/graph.py,sha256=eT8s0yCiJIu6D1T1fjZsLSPCcuQb2Mzl6qnljtQ5TuA,1504
436
438
  relationalai/util/list_databases.py,sha256=xJZGHzE0VLaDItWo5XvQSx75OwV045h2rjCBBnhNB3o,152
437
439
  relationalai/util/otel_configuration.py,sha256=oWjsPJ6nn2q7KaGN4l-XaMVkZyxCEfcXmOepSmQlm8I,1065
@@ -451,8 +453,8 @@ frontend/debugger/dist/index.html,sha256=0wIQ1Pm7BclVV1wna6Mj8OmgU73B9rSEGPVX-Wo
451
453
  frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png,sha256=tPXOEhOrM4tJyZVJQVBO_yFgNAlgooY38ZsjyrFstgg,620
452
454
  frontend/debugger/dist/assets/index-Cssla-O7.js,sha256=MxgIGfdKQyBWgufck1xYggQNhW5nj6BPjCF6Wleo-f0,298886
453
455
  frontend/debugger/dist/assets/index-DlHsYx1V.css,sha256=21pZtAjKCcHLFjbjfBQTF6y7QmOic-4FYaKNmwdNZVE,60141
454
- relationalai-0.11.2.dist-info/METADATA,sha256=wnEN6zPcH8E9wd5M6IH-Wad-GCKjD9oEcD5_nKd5nwY,2474
455
- relationalai-0.11.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
456
- relationalai-0.11.2.dist-info/entry_points.txt,sha256=fo_oLFJih3PUgYuHXsk7RnCjBm9cqRNR--ab6DgI6-0,88
457
- relationalai-0.11.2.dist-info/licenses/LICENSE,sha256=pPyTVXFYhirkEW9VsnHIgUjT0Vg8_xsE6olrF5SIgpc,11343
458
- relationalai-0.11.2.dist-info/RECORD,,
456
+ relationalai-0.11.4.dist-info/METADATA,sha256=B3VzqLxv4_NTOySacfpH2EgQmwYc5yFOhojNgkKXego,2519
457
+ relationalai-0.11.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
458
+ relationalai-0.11.4.dist-info/entry_points.txt,sha256=fo_oLFJih3PUgYuHXsk7RnCjBm9cqRNR--ab6DgI6-0,88
459
+ relationalai-0.11.4.dist-info/licenses/LICENSE,sha256=pPyTVXFYhirkEW9VsnHIgUjT0Vg8_xsE6olrF5SIgpc,11343
460
+ relationalai-0.11.4.dist-info/RECORD,,
@@ -1,213 +0,0 @@
1
- from __future__ import annotations
2
- from typing import Union, Literal
3
- import datetime as dt
4
-
5
- from relationalai.semantics.internal import internal as b
6
- from .std import _DateTime, _Date, _Integer, _String, _make_expr
7
- from .. import std
8
-
9
- # TODO support DateTime below as well, but this needs e.g. Rel `datetime_year`
10
-
11
- def year(date: _Date) -> b.Expression:
12
- return _make_expr("date_year", date, b.Int64.ref("res"))
13
-
14
- def month(date: _Date) -> b.Expression:
15
- return _make_expr("date_month", date, b.Int64.ref("res"))
16
-
17
- def week(date: _Date) -> b.Expression:
18
- return _make_expr("date_week", date, b.Int64.ref("res"))
19
-
20
- def day(date: _Date) -> b.Expression:
21
- return _make_expr("date_day", date, b.Int64.ref("res"))
22
-
23
- def dates_period_days(start: _Date, end: _Date) -> b.Expression:
24
- return _make_expr("dates_period_days", start, end, b.Int64.ref("res"))
25
-
26
- def datetime_week(datetime: _DateTime, tz: dt.tzinfo|str|None = None) -> b.Expression:
27
- tz = _extract_tz(datetime, tz)
28
- return _make_expr("datetime_week", datetime, tz, b.Int64.ref("res"))
29
-
30
- def datetimes_period_milliseconds(start: _DateTime, end: _DateTime) -> b.Expression:
31
- return _make_expr("datetimes_period_milliseconds", start, end, b.Int64.ref("res"))
32
-
33
- def date_fromordinal(ordinal: _Integer) -> b.Expression:
34
- # ordinal 1 = '0001-01-01'. Minus 1 day since we can't declare date 0000-00-00
35
- return date_add(b.Date(dt.date(1, 1, 1)), days(ordinal - 1))
36
-
37
- def datetime_fromordinal(ordinal: _Integer) -> b.Expression:
38
- # Convert ordinal to milliseconds, since ordinals in Python are days
39
- # Minus 1 day since we can't declare date 0000-00-00
40
- ordinal_milliseconds = (ordinal - 1) * 86400000 # 24 * 60 * 60 * 1000
41
- return datetime_add(b.DateTime(dt.datetime(1, 1, 1, 0, 0, 0)), milliseconds(ordinal_milliseconds))
42
-
43
- #--------------------------------------------------
44
- # Periods
45
- #--------------------------------------------------
46
- def milliseconds(period: _Integer) -> b.Expression:
47
- return _make_expr("millisecond", std.cast_to_int64(period), b.Int64.ref("res"))
48
-
49
- def seconds(period: _Integer) -> b.Expression:
50
- return _make_expr("second", std.cast_to_int64(period), b.Int64.ref("res"))
51
-
52
- def minutes(period: _Integer) -> b.Expression:
53
- return _make_expr("minute", std.cast_to_int64(period), b.Int64.ref("res"))
54
-
55
- def hours(period: _Integer) -> b.Expression:
56
- return _make_expr("hour", std.cast_to_int64(period), b.Int64.ref("res"))
57
-
58
- def days(period: _Integer) -> b.Expression:
59
- return _make_expr("day", std.cast_to_int64(period), b.Int64.ref("res"))
60
-
61
- def weeks(period: _Integer) -> b.Expression:
62
- return _make_expr("week", std.cast_to_int64(period), b.Int64.ref("res"))
63
-
64
- def months(period: _Integer) -> b.Expression:
65
- return _make_expr("month", std.cast_to_int64(period), b.Int64.ref("res"))
66
-
67
- def years(period: _Integer) -> b.Expression:
68
- return _make_expr("year", std.cast_to_int64(period), b.Int64.ref("res"))
69
-
70
- def date_to_datetime(date: _Date, hour: int = 0, minute: int = 0, second: int = 0, millisecond: int = 0, tz: str = "UTC") -> b.Expression:
71
- _year = year(date)
72
- _month = month(date)
73
- _day = day(date)
74
- return _make_expr("construct_datetime_ms_tz", _year, _month, _day, hour, minute, second, millisecond, tz, b.DateTime.ref("res"))
75
-
76
- def datetime_to_date(datetime: _DateTime, tz: dt.tzinfo | str | None = None) -> b.Expression:
77
- tz = _extract_tz(datetime, tz)
78
- return _make_expr("construct_date_from_datetime", datetime, tz, b.Date.ref("res"))
79
-
80
- #--------------------------------------------------
81
- # String Formatting
82
- #--------------------------------------------------
83
-
84
- def date_format(date: _Date, format: _String) -> b.Expression:
85
- return _make_expr("date_format", date, format, b.String.ref("res"))
86
-
87
- def datetime_format(date: _DateTime, format: _String, tz: _String = "UTC") -> b.Expression:
88
- return _make_expr("datetime_format", date, format, tz, b.String.ref("res"))
89
-
90
- #--------------------------------------------------
91
- # Arithmetic
92
- #--------------------------------------------------
93
- def date_add(date: _Date, period: b.Producer) -> b.Expression:
94
- return _make_expr("date_add", date, period, b.Date.ref("res"))
95
-
96
- def date_subtract(date: _Date, period: b.Producer) -> b.Expression:
97
- return _make_expr("date_subtract", date, period, b.Date.ref("res"))
98
-
99
- def datetime_add(date: _DateTime, period: b.Producer) -> b.Expression:
100
- return _make_expr("datetime_add", date, period, b.DateTime.ref("res"))
101
-
102
- def datetime_subtract(date: _DateTime, period: b.Producer) -> b.Expression:
103
- return _make_expr("datetime_subtract", date, period, b.DateTime.ref("res"))
104
-
105
-
106
- Frequency = Union[
107
- Literal["ms"],
108
- Literal["s"],
109
- Literal["m"],
110
- Literal["H"],
111
- Literal["D"],
112
- Literal["W"],
113
- Literal["M"],
114
- Literal["Y"],
115
- ]
116
-
117
- _periods = {
118
- "ms": milliseconds,
119
- "s": seconds,
120
- "m": minutes,
121
- "H": hours,
122
- "D": days,
123
- "W": weeks,
124
- "M": months,
125
- "Y": years,
126
- }
127
-
128
- # Note on date_ranges and datetime_range: The way the computation works is that it first overapproximates the number of periods.
129
- # For example date_range(2025-02-01, 2025-03-01, freq='M') and date_range(2025-02-01, 2025-03-31, freq='M') will compute
130
- # range_end to be ceil(28*1/(365/12))=1 and ceil(58*1/(365/12))=2. Then, the computation fetches range_end+1 items into _date, which
131
- # is the right number in the first case but one too many in the second case. That's why a filter end >= _date (or variant of) is
132
- # applied, to remove any extra item. The result is two items in both cases.
133
-
134
- def date_range(start: _Date | None = None, end: _Date | None = None, periods: int = 1, freq: Frequency = "D") -> b.Expression:
135
- if start is None and end is None:
136
- raise ValueError("Invalid start/end date for date_range. Must provide at least start date or end date")
137
- _days = {
138
- "D": 1,
139
- "W": 1/7,
140
- "M": 1/(365/12),
141
- "Y": 1/365,
142
- }
143
- if freq not in _days.keys():
144
- raise ValueError(f"Frequency '{freq}' is not allowed for date_range. List of allowed frequencies: {list(_days.keys())}")
145
- date_func = date_add
146
- if start is None:
147
- start = end
148
- end = None
149
- date_func = date_subtract
150
- assert start is not None
151
- if end is not None:
152
- num_days = std.dates.dates_period_days(start, end)
153
- if freq in ["W", "M", "Y"]:
154
- range_end = std.cast(b.Int64, std.math.ceil(num_days * _days[freq]))
155
- else:
156
- range_end = num_days
157
- # date_range is inclusive. add 1 since std.range is exclusive
158
- ix = std.range(0, range_end + 1, 1)
159
- else:
160
- ix = std.range(0, periods, 1)
161
- _date = date_func(start, _periods[freq](ix))
162
- if isinstance(end, dt.date) :
163
- return b.Date(end) >= _date
164
- elif end is not None:
165
- return end >= _date
166
- return _date
167
-
168
- def datetime_range(start: _DateTime | None = None, end: _DateTime | None = None, periods: int = 1, freq: Frequency = "D") -> b.Expression:
169
- if start is None and end is None:
170
- raise ValueError("Invalid start/end datetime for datetime_range. Must provide at least start datetime or end datetime")
171
- _milliseconds = {
172
- "ms": 1,
173
- "s": 1 / 1_000,
174
- "m": 1 / 60_000,
175
- "H": 1 / 3_600_000,
176
- "D": 1 / 86_400_000,
177
- "W": 1 / (86_400_000 * 7),
178
- "M": 1 / (86_400_000 * (365 / 12)),
179
- "Y": 1 / (86_400_000 * 365),
180
- }
181
- date_func = datetime_add
182
- if start is None:
183
- start = end
184
- end = None
185
- date_func = datetime_subtract
186
- assert start is not None
187
- if end is not None:
188
- num_ms = datetimes_period_milliseconds(start, end)
189
- if freq == "ms":
190
- _end = num_ms
191
- else:
192
- _end = std.cast(b.Int64, std.math.ceil(num_ms * _milliseconds[freq]))
193
- # datetime_range is inclusive. add 1 since std.range is exclusive
194
- ix = std.range(0, _end + 1, 1)
195
- else:
196
- ix = std.range(0, periods, 1)
197
- _date = date_func(start, _periods[freq](ix))
198
- if isinstance(end, dt.datetime) :
199
- return b.DateTime(end) >= _date
200
- elif end is not None:
201
- return end >= _date
202
- return _date
203
-
204
- def _extract_tz(datetime: _DateTime, tz: dt.tzinfo|str|None) -> str:
205
- default_tz = "UTC"
206
- if tz is None:
207
- if isinstance(datetime, dt.datetime):
208
- tz = datetime.tzname() or default_tz
209
- else:
210
- tz = default_tz
211
- elif isinstance(tz, dt.tzinfo) :
212
- tz = tz.tzname(None) or default_tz
213
- return tz