-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SNOW-692968: Async queries support #787
base: master
Are you sure you want to change the base?
Conversation
include/snowflake/client.h
Outdated
* | ||
* @return sfstmt SNOWFLAKE_STMT context for async queries. | ||
*/ | ||
SF_STMT* STDCALL snowflake_async_stmt(SF_CONNECT *sf, const char *query_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function name sounds confusing since it seems to be an equivalent of snowflake_stmt
. Maybe use the similar function name as JDBC, create_resultset
or to be more specific, create_async_query_result
? Still return a SF_STMT instance since libsfclient doesn't have an struct specifically for result set, but would be easier to understand the functionality of the function.
lib/client.c
Outdated
char* queryStatus = snowflake_cJSON_GetStringValue(status); | ||
ret = get_status_from_string(queryStatus); | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After seeing the logic in get_real_results
I'm not quite sure whether we should set error here. Seems no data is acceptable, the error log in get_query_metadata
would be the same.
lib/client.c
Outdated
#ifdef _WIN32 | ||
Sleep(sleep_time); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
define this as a common function in platform.c? I think same logic being used in http_perform.c as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add test cases to cover typical use case, checking query status before calling any fetch/metadata API. Take JDBC doc as example, https://docs.snowflake.com/en/developer-guide/jdbc/jdbc-using#examples-of-asynchronous-queries
Add usage example in PR description as well (could be reference to test case if the code is clean enough).
Calling fetch/metadata function without checking query status also needed. Please test with queries would take some time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove unnecessary formatting changes. It's hard to review with so much (unnecessary?) changes.
lib/connection.c
Outdated
// Remove old result URL and query code if this isn't our first rodeo | ||
SF_FREE(result_url); | ||
memset(query_code, 0, QUERYCODE_LEN); | ||
data = snowflake_cJSON_GetObjectItem(*json, "data"); | ||
if (json_copy_string(&result_url, data, "getResultUrl") != | ||
SF_JSON_ERROR_NONE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No changes? No reason to reformat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think VS automatically did that accidentally when I wrapped it in an if clause. I'll revert these
lib/connection.c
Outdated
// Error came from request up, just break | ||
stop = SF_BOOLEAN_TRUE; | ||
break; | ||
GET_REQUEST_TYPE, error, SF_BOOLEAN_FALSE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
lib/connection.c
Outdated
SET_SNOWFLAKE_ERROR(error, SF_STATUS_ERROR_BAD_JSON, error_msg, | ||
SF_SQLSTATE_UNABLE_TO_CONNECT); | ||
break; | ||
stop = SF_BOOLEAN_TRUE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
// Get query stats | ||
char* metadata_str = get_query_metadata(sfstmt); | ||
if (metadata_str) { | ||
cJSON* metadata = snowflake_cJSON_Parse(metadata_str); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error handling?
lib/client.c
Outdated
char* metadata_str = get_query_metadata(sfstmt); | ||
if (metadata_str) { | ||
cJSON* metadata = snowflake_cJSON_Parse(metadata_str); | ||
cJSON* stats = snowflake_cJSON_GetObjectItem(metadata, "stats"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We assume it's an object?
lib/client.c
Outdated
@@ -2073,6 +2284,13 @@ SF_STATUS STDCALL _snowflake_execute_ex(SF_STMT *sfstmt, | |||
body = create_query_json_body(sfstmt->sql_text, sfstmt->sequence_counter, | |||
is_string_empty(sfstmt->connection->directURL) ? | |||
NULL : sfstmt->request_id, is_describe_only); | |||
|
|||
if (is_async_exec) { | |||
snowflake_cJSON_AddBoolToObject(body, "asyncExec", SF_BOOLEAN_TRUE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
snowflake_cJSON_AddBoolToObject(body, "asyncExec", is_async_exec); ?
while (strcmp(query_code, QUERY_IN_PROGRESS_CODE) == 0 || | ||
strcmp(query_code, QUERY_IN_PROGRESS_ASYNC_CODE) == 0) { | ||
sf_bool isAsyncExec = SF_BOOLEAN_FALSE; | ||
cJSON *json_body = snowflake_cJSON_Parse(body); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error handling?
…m/snowflakedb/libsnowflakeclient into SNOW-692968-async-queries-support
include/snowflake/client.h
Outdated
* The query status | ||
*/ | ||
typedef enum SF_QUERY_STATUS { | ||
SF_QUERY_STATUS_RUNNING, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's sort statuses alphabetically
include/snowflake/platform.h
Outdated
@@ -142,6 +142,9 @@ void STDCALL sf_memory_error_handler(); | |||
// this should be called by application before any calls of sfclient | |||
void STDCALL sf_exception_on_memory_failure(); | |||
|
|||
void STDCALL sf_sleep_ms(int sleep_ms); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be in out public api?
lib/client.c
Outdated
@@ -54,12 +56,193 @@ static SF_STATUS STDCALL | |||
_reset_connection_parameters(SF_CONNECT *sf, cJSON *parameters, | |||
cJSON *session_info, sf_bool do_validate); | |||
|
|||
static const char* query_status_names[] = { | |||
"RUNNING", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we keep the statuses sorted?
lib/client.c
Outdated
*/ | ||
SF_QUERY_STATUS get_status_from_string(const char *query_status) { | ||
if (query_status == NULL) { | ||
return SF_QUERY_STATUS_NO_DATA; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it no data or more UNKNOWN?
lib/client.c
Outdated
cJSON *data = NULL; | ||
cJSON *queries = NULL; | ||
char *s_resp = NULL; | ||
size_t url_size = strlen(QUERY_MONITOR_URL) -2 + strlen(sfstmt->sfqid) + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's apply code formatter on changed files
cmocka_unit_test(test_premature_fetch), | ||
cmocka_unit_test(test_new_connection), | ||
cmocka_unit_test(test_fake_table), | ||
cmocka_unit_test(test_invalid_query_id), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add a test that fetches chunks
Added snowflake_async_execute to execute async queries and snowflake_async_stmt to get previously run async queries using query id.