relationalai 0.12.12__py3-none-any.whl → 0.12.13__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.
- relationalai/clients/snowflake.py +105 -64
- {relationalai-0.12.12.dist-info → relationalai-0.12.13.dist-info}/METADATA +1 -1
- {relationalai-0.12.12.dist-info → relationalai-0.12.13.dist-info}/RECORD +6 -6
- {relationalai-0.12.12.dist-info → relationalai-0.12.13.dist-info}/WHEEL +0 -0
- {relationalai-0.12.12.dist-info → relationalai-0.12.13.dist-info}/entry_points.txt +0 -0
- {relationalai-0.12.12.dist-info → relationalai-0.12.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -441,7 +441,8 @@ class Resources(ResourcesBase):
|
|
|
441
441
|
code: str,
|
|
442
442
|
params: List[Any] | Any | None = None,
|
|
443
443
|
raw: bool = False,
|
|
444
|
-
help: bool = True
|
|
444
|
+
help: bool = True,
|
|
445
|
+
skip_engine_db_error_retry: bool = False
|
|
445
446
|
) -> Any:
|
|
446
447
|
# print(f"\n--- sql---\n{code}\n--- end sql---\n")
|
|
447
448
|
if not self._session:
|
|
@@ -467,7 +468,8 @@ class Resources(ResourcesBase):
|
|
|
467
468
|
if re.search(f"database '{rai_app}' does not exist or not authorized.".lower(), orig_message):
|
|
468
469
|
exception = SnowflakeAppMissingException(rai_app, current_role)
|
|
469
470
|
raise exception from None
|
|
470
|
-
if
|
|
471
|
+
# skip initializing the index if the query is a user transaction. exec_raw/exec_lqp will handle that case with the correct request headers.
|
|
472
|
+
if (_is_engine_issue(orig_message) or _is_database_issue(orig_message)) and not skip_engine_db_error_retry:
|
|
471
473
|
try:
|
|
472
474
|
self._poll_use_index(
|
|
473
475
|
app_name=self.get_app_name(),
|
|
@@ -1609,9 +1611,11 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1609
1611
|
sql_string = f"CALL {APP_NAME}.api.exec_async_v2('{database}','{engine}', ?, {inputs}, {readonly}, {nowait_durable}, '{language}', {query_timeout_mins}, {request_headers});"
|
|
1610
1612
|
else:
|
|
1611
1613
|
sql_string = f"CALL {APP_NAME}.api.exec_async_v2('{database}','{engine}', ?, {inputs}, {readonly}, {nowait_durable}, '{language}', {request_headers});"
|
|
1614
|
+
# Don't let exec setup GI on failure, exec_raw and exec_lqp will do that and add the correct headers.
|
|
1612
1615
|
response = self._exec(
|
|
1613
1616
|
sql_string,
|
|
1614
1617
|
raw_code,
|
|
1618
|
+
skip_engine_db_error_retry=True,
|
|
1615
1619
|
)
|
|
1616
1620
|
if not response:
|
|
1617
1621
|
raise Exception("Failed to create transaction")
|
|
@@ -1629,6 +1633,7 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1629
1633
|
bypass_index=False,
|
|
1630
1634
|
language: str = "rel",
|
|
1631
1635
|
query_timeout_mins: int | None = None,
|
|
1636
|
+
gi_setup_skipped: bool = False,
|
|
1632
1637
|
):
|
|
1633
1638
|
if inputs is None:
|
|
1634
1639
|
inputs = {}
|
|
@@ -1638,6 +1643,8 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1638
1643
|
with debugging.span("transaction", **query_attrs_dict) as txn_span:
|
|
1639
1644
|
with debugging.span("create_v2", **query_attrs_dict) as create_span:
|
|
1640
1645
|
request_headers['user-agent'] = get_pyrel_version(self.generation)
|
|
1646
|
+
request_headers['gi_setup_skipped'] = str(gi_setup_skipped)
|
|
1647
|
+
request_headers['pyrel_program_id'] = debugging.get_program_span_id() or ""
|
|
1641
1648
|
response = self._exec_rai_app(
|
|
1642
1649
|
database=database,
|
|
1643
1650
|
engine=engine,
|
|
@@ -1897,26 +1904,29 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1897
1904
|
# Exec
|
|
1898
1905
|
#--------------------------------------------------
|
|
1899
1906
|
|
|
1900
|
-
def
|
|
1907
|
+
def _exec_with_gi_retry(
|
|
1901
1908
|
self,
|
|
1902
1909
|
database: str,
|
|
1903
1910
|
engine: str | None,
|
|
1904
|
-
raw_code:
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
query_timeout_mins: int | None
|
|
1911
|
+
raw_code: str,
|
|
1912
|
+
inputs: Dict | None,
|
|
1913
|
+
readonly: bool,
|
|
1914
|
+
nowait_durable: bool,
|
|
1915
|
+
headers: Dict | None,
|
|
1916
|
+
bypass_index: bool,
|
|
1917
|
+
language: str,
|
|
1918
|
+
query_timeout_mins: int | None,
|
|
1912
1919
|
):
|
|
1913
|
-
|
|
1920
|
+
"""Execute with graph index retry logic.
|
|
1914
1921
|
|
|
1922
|
+
Attempts execution with gi_setup_skipped=True first. If an engine or database
|
|
1923
|
+
issue occurs, polls use_index and retries with gi_setup_skipped=False.
|
|
1924
|
+
"""
|
|
1915
1925
|
try:
|
|
1916
1926
|
return self._exec_async_v2(
|
|
1917
|
-
database, engine,
|
|
1918
|
-
headers=headers, bypass_index=bypass_index, language=
|
|
1919
|
-
query_timeout_mins=query_timeout_mins,
|
|
1927
|
+
database, engine, raw_code, inputs, readonly, nowait_durable,
|
|
1928
|
+
headers=headers, bypass_index=bypass_index, language=language,
|
|
1929
|
+
query_timeout_mins=query_timeout_mins, gi_setup_skipped=True,
|
|
1920
1930
|
)
|
|
1921
1931
|
except Exception as e:
|
|
1922
1932
|
err_message = str(e).lower()
|
|
@@ -1933,13 +1943,32 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1933
1943
|
)
|
|
1934
1944
|
|
|
1935
1945
|
return self._exec_async_v2(
|
|
1936
|
-
database, engine,
|
|
1937
|
-
headers=headers, bypass_index=bypass_index, language=
|
|
1938
|
-
query_timeout_mins=query_timeout_mins,
|
|
1946
|
+
database, engine, raw_code, inputs, readonly, nowait_durable,
|
|
1947
|
+
headers=headers, bypass_index=bypass_index, language=language,
|
|
1948
|
+
query_timeout_mins=query_timeout_mins, gi_setup_skipped=False,
|
|
1939
1949
|
)
|
|
1940
1950
|
else:
|
|
1941
1951
|
raise e
|
|
1942
1952
|
|
|
1953
|
+
def exec_lqp(
|
|
1954
|
+
self,
|
|
1955
|
+
database: str,
|
|
1956
|
+
engine: str | None,
|
|
1957
|
+
raw_code: bytes,
|
|
1958
|
+
readonly=True,
|
|
1959
|
+
*,
|
|
1960
|
+
inputs: Dict | None = None,
|
|
1961
|
+
nowait_durable=False,
|
|
1962
|
+
headers: Dict | None = None,
|
|
1963
|
+
bypass_index=False,
|
|
1964
|
+
query_timeout_mins: int | None = None,
|
|
1965
|
+
):
|
|
1966
|
+
raw_code_b64 = base64.b64encode(raw_code).decode("utf-8")
|
|
1967
|
+
return self._exec_with_gi_retry(
|
|
1968
|
+
database, engine, raw_code_b64, inputs, readonly, nowait_durable,
|
|
1969
|
+
headers, bypass_index, 'lqp', query_timeout_mins
|
|
1970
|
+
)
|
|
1971
|
+
|
|
1943
1972
|
|
|
1944
1973
|
def exec_raw(
|
|
1945
1974
|
self,
|
|
@@ -1955,45 +1984,10 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
1955
1984
|
query_timeout_mins: int | None = None,
|
|
1956
1985
|
):
|
|
1957
1986
|
raw_code = raw_code.replace("'", "\\'")
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
engine,
|
|
1963
|
-
raw_code,
|
|
1964
|
-
inputs,
|
|
1965
|
-
readonly,
|
|
1966
|
-
nowait_durable,
|
|
1967
|
-
headers=headers,
|
|
1968
|
-
bypass_index=bypass_index,
|
|
1969
|
-
query_timeout_mins=query_timeout_mins,
|
|
1970
|
-
)
|
|
1971
|
-
except Exception as e:
|
|
1972
|
-
err_message = str(e).lower()
|
|
1973
|
-
if _is_engine_issue(err_message) or _is_database_issue(err_message):
|
|
1974
|
-
engine_name = engine or self.get_default_engine_name()
|
|
1975
|
-
engine_size = self.config.get_default_engine_size()
|
|
1976
|
-
self._poll_use_index(
|
|
1977
|
-
app_name=self.get_app_name(),
|
|
1978
|
-
sources=self.sources,
|
|
1979
|
-
model=database,
|
|
1980
|
-
engine_name=engine_name,
|
|
1981
|
-
engine_size=engine_size,
|
|
1982
|
-
headers=headers,
|
|
1983
|
-
)
|
|
1984
|
-
return self._exec_async_v2(
|
|
1985
|
-
database,
|
|
1986
|
-
engine,
|
|
1987
|
-
raw_code,
|
|
1988
|
-
inputs,
|
|
1989
|
-
readonly,
|
|
1990
|
-
nowait_durable,
|
|
1991
|
-
headers=headers,
|
|
1992
|
-
bypass_index=bypass_index,
|
|
1993
|
-
query_timeout_mins=query_timeout_mins,
|
|
1994
|
-
)
|
|
1995
|
-
else:
|
|
1996
|
-
raise e
|
|
1987
|
+
return self._exec_with_gi_retry(
|
|
1988
|
+
database, engine, raw_code, inputs, readonly, nowait_durable,
|
|
1989
|
+
headers, bypass_index, 'rel', query_timeout_mins
|
|
1990
|
+
)
|
|
1997
1991
|
|
|
1998
1992
|
|
|
1999
1993
|
def format_results(self, results, task:m.Task|None=None) -> Tuple[DataFrame, List[Any]]:
|
|
@@ -3281,6 +3275,7 @@ class DirectAccessResources(Resources):
|
|
|
3281
3275
|
path_params: Dict[str, str] | None = None,
|
|
3282
3276
|
query_params: Dict[str, str] | None = None,
|
|
3283
3277
|
skip_auto_create: bool = False,
|
|
3278
|
+
skip_engine_db_error_retry: bool = False,
|
|
3284
3279
|
) -> requests.Response:
|
|
3285
3280
|
with debugging.span("direct_access_request"):
|
|
3286
3281
|
def _send_request():
|
|
@@ -3314,8 +3309,8 @@ class DirectAccessResources(Resources):
|
|
|
3314
3309
|
message = "" # Not used when we check status_code directly
|
|
3315
3310
|
|
|
3316
3311
|
# fix engine on engine error and retry
|
|
3317
|
-
# Skip
|
|
3318
|
-
if (_is_engine_issue(message) and not skip_auto_create) or _is_database_issue(message):
|
|
3312
|
+
# Skip setting up GI if skip_auto_create is True to avoid recursion or skip_engine_db_error_retry is true to let _exec_async_v2 perform the retry with the correct headers.
|
|
3313
|
+
if ((_is_engine_issue(message) and not skip_auto_create) or _is_database_issue(message)) and not skip_engine_db_error_retry:
|
|
3319
3314
|
engine_name = payload.get("caller_engine_name", "") if payload else ""
|
|
3320
3315
|
engine_name = engine_name or self.get_default_engine_name()
|
|
3321
3316
|
engine_size = self.config.get_default_engine_size()
|
|
@@ -3340,6 +3335,48 @@ class DirectAccessResources(Resources):
|
|
|
3340
3335
|
raise e
|
|
3341
3336
|
return response
|
|
3342
3337
|
|
|
3338
|
+
def _txn_request_with_gi_retry(
|
|
3339
|
+
self,
|
|
3340
|
+
payload: Dict,
|
|
3341
|
+
headers: Dict[str, str],
|
|
3342
|
+
query_params: Dict,
|
|
3343
|
+
engine: Union[str, None],
|
|
3344
|
+
):
|
|
3345
|
+
"""Make request with graph index retry logic.
|
|
3346
|
+
|
|
3347
|
+
Attempts request with gi_setup_skipped=True first. If an engine or database
|
|
3348
|
+
issue occurs, polls use_index and retries with gi_setup_skipped=False.
|
|
3349
|
+
"""
|
|
3350
|
+
response = self.request(
|
|
3351
|
+
"create_txn", payload=payload, headers=headers, query_params=query_params, skip_auto_create=True, skip_engine_db_error_retry=True
|
|
3352
|
+
)
|
|
3353
|
+
|
|
3354
|
+
if response.status_code != 200:
|
|
3355
|
+
try:
|
|
3356
|
+
message = response.json().get("message", "")
|
|
3357
|
+
except requests.exceptions.JSONDecodeError:
|
|
3358
|
+
message = ""
|
|
3359
|
+
|
|
3360
|
+
if _is_engine_issue(message) or _is_database_issue(message):
|
|
3361
|
+
engine_name = engine or self.get_default_engine_name()
|
|
3362
|
+
engine_size = self.config.get_default_engine_size()
|
|
3363
|
+
self._poll_use_index(
|
|
3364
|
+
app_name=self.get_app_name(),
|
|
3365
|
+
sources=self.sources,
|
|
3366
|
+
model=self.database,
|
|
3367
|
+
engine_name=engine_name,
|
|
3368
|
+
engine_size=engine_size,
|
|
3369
|
+
headers=headers,
|
|
3370
|
+
)
|
|
3371
|
+
headers['gi_setup_skipped'] = 'False'
|
|
3372
|
+
response = self.request(
|
|
3373
|
+
"create_txn", payload=payload, headers=headers, query_params=query_params, skip_auto_create=True, skip_engine_db_error_retry=True
|
|
3374
|
+
)
|
|
3375
|
+
else:
|
|
3376
|
+
raise ResponseStatusException("Failed to create transaction.", response)
|
|
3377
|
+
|
|
3378
|
+
return response
|
|
3379
|
+
|
|
3343
3380
|
def _exec_async_v2(
|
|
3344
3381
|
self,
|
|
3345
3382
|
database: str,
|
|
@@ -3352,6 +3389,7 @@ class DirectAccessResources(Resources):
|
|
|
3352
3389
|
bypass_index=False,
|
|
3353
3390
|
language: str = "rel",
|
|
3354
3391
|
query_timeout_mins: int | None = None,
|
|
3392
|
+
gi_setup_skipped: bool = False,
|
|
3355
3393
|
):
|
|
3356
3394
|
|
|
3357
3395
|
with debugging.span("transaction") as txn_span:
|
|
@@ -3374,12 +3412,15 @@ class DirectAccessResources(Resources):
|
|
|
3374
3412
|
payload["timeout_mins"] = query_timeout_mins
|
|
3375
3413
|
query_params={"use_graph_index": str(use_graph_index and not bypass_index)}
|
|
3376
3414
|
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3415
|
+
# Add gi_setup_skipped to headers
|
|
3416
|
+
if headers is None:
|
|
3417
|
+
headers = {}
|
|
3418
|
+
headers["gi_setup_skipped"] = str(gi_setup_skipped)
|
|
3419
|
+
headers['pyrel_program_id'] = debugging.get_program_span_id() or ""
|
|
3380
3420
|
|
|
3381
|
-
|
|
3382
|
-
|
|
3421
|
+
response = self._txn_request_with_gi_retry(
|
|
3422
|
+
payload, headers, query_params, engine
|
|
3423
|
+
)
|
|
3383
3424
|
|
|
3384
3425
|
artifact_info = {}
|
|
3385
3426
|
response_content = response.json()
|
|
@@ -29,7 +29,7 @@ relationalai/clients/hash_util.py,sha256=pZVR1FX3q4G_19p_r6wpIR2tIM8_WUlfAR7AVZJ
|
|
|
29
29
|
relationalai/clients/local.py,sha256=uX1Or2WO0juDuqa6TCCvm3G2ieP6p0PtYp_jfrCMlVc,23577
|
|
30
30
|
relationalai/clients/profile_polling.py,sha256=pUH7WKH4nYDD0SlQtg3wsWdj0K7qt6nZqUw8jTthCBs,2565
|
|
31
31
|
relationalai/clients/result_helpers.py,sha256=wDSD02Ngx6W-YQqBIGKnpXD4Ju3pA1e9Nz6ORRI6SRI,17808
|
|
32
|
-
relationalai/clients/snowflake.py,sha256=
|
|
32
|
+
relationalai/clients/snowflake.py,sha256=pB_4t70vTmfGPUJnJpbrrsNH5pojPJyqodsMtUL6b9c,168261
|
|
33
33
|
relationalai/clients/types.py,sha256=eNo6akcMTbnBFbBbHd5IgVeY-zuAgtXlOs8Bo1SWmVU,2890
|
|
34
34
|
relationalai/clients/use_index_poller.py,sha256=rrkg35xiHqY0-2dZlPkgixEGENrIrl7bf_2TboX_qew,46794
|
|
35
35
|
relationalai/clients/util.py,sha256=NJC8fnrWHR01NydwESPSetIHRWf7jQJURYpaWJjmDyE,12311
|
|
@@ -442,8 +442,8 @@ frontend/debugger/dist/index.html,sha256=0wIQ1Pm7BclVV1wna6Mj8OmgU73B9rSEGPVX-Wo
|
|
|
442
442
|
frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png,sha256=tPXOEhOrM4tJyZVJQVBO_yFgNAlgooY38ZsjyrFstgg,620
|
|
443
443
|
frontend/debugger/dist/assets/index-Cssla-O7.js,sha256=MxgIGfdKQyBWgufck1xYggQNhW5nj6BPjCF6Wleo-f0,298886
|
|
444
444
|
frontend/debugger/dist/assets/index-DlHsYx1V.css,sha256=21pZtAjKCcHLFjbjfBQTF6y7QmOic-4FYaKNmwdNZVE,60141
|
|
445
|
-
relationalai-0.12.
|
|
446
|
-
relationalai-0.12.
|
|
447
|
-
relationalai-0.12.
|
|
448
|
-
relationalai-0.12.
|
|
449
|
-
relationalai-0.12.
|
|
445
|
+
relationalai-0.12.13.dist-info/METADATA,sha256=qiiOC2n_SXtlfEHafFp8hVqY1M2VSzGOl5fqOPt1_ZQ,2563
|
|
446
|
+
relationalai-0.12.13.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
447
|
+
relationalai-0.12.13.dist-info/entry_points.txt,sha256=fo_oLFJih3PUgYuHXsk7RnCjBm9cqRNR--ab6DgI6-0,88
|
|
448
|
+
relationalai-0.12.13.dist-info/licenses/LICENSE,sha256=pPyTVXFYhirkEW9VsnHIgUjT0Vg8_xsE6olrF5SIgpc,11343
|
|
449
|
+
relationalai-0.12.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|