Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ inline std::string FormatDatetimeToString(
const SQL_TIMESTAMP_STRUCT& datetime) {
char buffer[30];
auto const* datetime_format = (datetime.fraction == 0)
? "%04d-%02d-%02dT%02d:%02d:%02d"
: "%04d-%02d-%02dT%02d:%02d:%02d.%06d";
? "%04d-%02d-%02d %02d:%02d:%02d"
: "%04d-%02d-%02d %02d:%02d:%02d.%06d";
snprintf(buffer, sizeof(buffer), datetime_format, datetime.year,
datetime.month, datetime.day, datetime.hour, datetime.minute,
datetime.second, datetime.fraction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ TEST(FormatDatetimeToString, DatetimeStringWithZeros) {

std::string datetime_string = FormatDatetimeToString(datetime);

std::string expected_string = "2020-01-10T00:05:03";
std::string expected_string = "2020-01-10 00:05:03";
EXPECT_EQ(datetime_string, expected_string);
}

Expand All @@ -285,7 +285,7 @@ TEST(FormatDatetimeToString, DatetimeString) {

std::string datetime_string = FormatDatetimeToString(datetime);

std::string expected_string = "2020-01-10T01:59:43.123456";
std::string expected_string = "2020-01-10 01:59:43.123456";
EXPECT_EQ(datetime_string, expected_string);
}

Expand Down
53 changes: 36 additions & 17 deletions google/cloud/odbc/bq_driver/internal/odbc_sql_execute_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,16 @@ StatusRecordOr<std::shared_ptr<arrow::Schema>> GetArrowSchema(
case arrow::Type::BOOL:
col_schema.col_type = BQDataType::kBool;
break;
case arrow::Type::TIMESTAMP:
col_schema.col_type = BQDataType::kTimeStamp;
case arrow::Type::TIMESTAMP: {
auto ts_type =
std::static_pointer_cast<arrow::TimestampType>(field->type());
if (ts_type->timezone().empty()) {
col_schema.col_type = BQDataType::kDatetime;
} else {
col_schema.col_type = BQDataType::kTimeStamp;
}
break;
}
case arrow::Type::TIME64:
col_schema.col_type = BQDataType::kTime;
break;
Expand Down Expand Up @@ -982,29 +989,45 @@ StatusRecordOr<DSResults> FetchBQData(
StatementHandle& stmt_handle, PostQueryRequest const& post_query_request,
[[maybe_unused]] bool with_htapi) {
ConnectionHandle& conn_handle = *(stmt_handle.GetConnectionHandle());

auto pq_status = PostQueryWithoutResults(conn_handle, post_query_request);
if (!pq_status) {
return pq_status.GetStatusRecord();
}

// If session started, propagate session ID to the connection handle
if (!conn_handle.IsSessionStarted() &&
!pq_status->session_info.session_id.empty()) {
conn_handle.SetSessionId(pq_status->session_info.session_id);
}

DSResults results;
results.num_dml_affected_rows = pq_status->num_dml_affected_rows;
results.job_ref = pq_status->job_reference;
stmt_handle.GetPagingInfo().job_id = pq_status->job_reference.job_id;
stmt_handle.GetPagingInfo().page_token = pq_status->page_token;

if (pq_status->job_complete && pq_status->page_token.empty()) {
// Only one page of results, return it directly.
results.data_source_results = *pq_status;
return results;
}

// If there are more pages, check if we should use HTAPI fallback
#if (!defined(_WIN32) || defined(_WIN64)) && !defined(NO_ARROW)
if (with_htapi && conn_handle.GetDsn().allow_htapi) {
// Fallback to HTAPI
StatusRecord read_status = FetchBQDataRead(stmt_handle, post_query_request);
if (!read_status.ok()) {
return read_status;
}
DSResults results;
results.data_source_results = stmt_handle.GetResultSet();
return results;
}
#endif // (!defined(_WIN32) || defined(_WIN64)) && !defined(NO_ARROW)

auto pq_status = PostQueryWithoutResults(conn_handle, post_query_request);
if (!pq_status) {
return pq_status.GetStatusRecord();
}
DSResults results;
results.num_dml_affected_rows = pq_status->num_dml_affected_rows;
results.job_ref = pq_status->job_reference;
stmt_handle.GetPagingInfo().job_id = pq_status->job_reference.job_id;
stmt_handle.GetPagingInfo().page_token = pq_status->page_token;
// Otherwise, continue with standard REST API pagination
if (pq_status->job_complete) {
// we have gotten all the results
results.data_source_results = *pq_status;
} else {
auto gq_status =
Expand All @@ -1017,10 +1040,6 @@ StatusRecordOr<DSResults> FetchBQData(
results.num_dml_affected_rows = gq_status->num_dml_affected_rows;
results.data_source_results = *gq_status;
}
if (!conn_handle.IsSessionStarted() &&
!pq_status->session_info.session_id.empty()) {
conn_handle.SetSessionId(pq_status->session_info.session_id);
}
return results;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2486,19 +2486,13 @@ void TestTranslationsFromDateTime(std::shared_ptr<ODBCHandles> conn,
switch (expected.target_c_type) {
case SQL_C_CHAR: {
std::string returned_val = reinterpret_cast<char*>(data);
if (kIsBqDriver) {
expected_val = FormatToGoogleDatetimeStr(expected_val);
}
EXPECT_EQ(returned_val, expected_val);
break;
}
case SQL_C_WCHAR: {
SQLINTEGER length = strlen_or_ind / sizeof(SQLWCHAR);
std::string returned_val =
ConvertSQLWCHARToString(reinterpret_cast<SQLWCHAR*>(data), length);
if (kIsBqDriver) {
expected_val = FormatToGoogleDatetimeStr(expected_val);
}
EXPECT_STREQ(returned_val.data(), expected_val.data());
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,10 @@ static RowWiseResults const kBasicTypesExpected{
{6, "{\"age\":30,\"name\":\"John\"}"},
{7, "2025-11-12 23:22:27.500000"},
{8, kIsBqDriver ? "12:34:56" : "12:34:56.000000"},
{9, kIsBqDriver
? (kIsWin32 ? "2024-05-01T08:00:00" : "2024-05-01 08:00:00")
: "2024-05-01 08:00:00.000000"},
{9, kIsBqDriver ? "2024-05-01 08:00:00" : "2024-05-01 08:00:00.000000"},
{10, "2023-04-01"},
{11, kIsBqDriver
? (kIsWin32 ? "[\"3\",\"4\",\"5\"]" : "[3, 4, 5]")
? "[\"3\",\"4\",\"5\"]"
: "{\"v\":[{\"v\":\"3\"},{\"v\":\"4\"},{\"v\":\"5\"}]}"},
}},
};
Expand Down
Loading