Skip to content

Commit 7375752

Browse files
test
1 parent 895f3fe commit 7375752

1 file changed

Lines changed: 68 additions & 71 deletions

File tree

google/cloud/odbc/bq_driver/internal/data_translation.cc

Lines changed: 68 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -935,79 +935,19 @@ odbc_internal::StatusRecord ConvertFromTimeDSValue(DSValue const& src_dsval,
935935
return status_record;
936936
}
937937

938-
odbc_internal::StatusRecord ConvertTimestampStringToChar(
939-
const std::string& timestamp_src_str,
940-
void* dest_buf,
941-
SQLLEN buffer_length,
942-
SQLLEN* res_len) {
943-
944-
constexpr SQLLEN k_timestamp_src_len = 64; // adjust if needed
945-
auto* dest = reinterpret_cast<char*>(dest_buf);
946-
StatusRecord status_record;
947-
948-
if (buffer_length > k_timestamp_src_len) {
949-
if (res_len) *res_len = k_timestamp_src_len;
950-
std::strncpy(dest, timestamp_src_str.c_str(), k_timestamp_src_len);
951-
dest[k_timestamp_src_len] = '\0';
952-
} else if (20 <= buffer_length && buffer_length <= k_timestamp_src_len) {
953-
if (res_len) *res_len = buffer_length;
954-
std::strncpy(dest, timestamp_src_str.c_str(), buffer_length - 1);
955-
dest[buffer_length - 1] = '\0';
956-
status_record = StatusRecord{SQLStates::k_01004(), "Data truncated"};
957-
} else {
958-
status_record =
959-
StatusRecord{SQLStates::k_22003(), "Buffer length is insufficient"};
960-
}
961-
return status_record;
962-
}
963-
964-
odbc_internal::StatusRecord ConvertTimestampStringToWChar(
965-
const std::string& timestamp_src_str,
966-
void* dest_buf,
967-
SQLLEN buffer_length,
968-
SQLLEN* res_len) {
969-
970-
StatusRecord status_record;
971-
auto wstr_or = Utf8ToUtf16(timestamp_src_str);
972-
if (!wstr_or) {
973-
return StatusRecord{SQLStates::k_HY000(), "DSValueToWchar Conversion Failed"};
974-
}
975-
976-
std::vector<SQLWCHAR> wstr_data(wstr_or->begin(), wstr_or->end());
977-
wstr_data.emplace_back(L'\0');
978-
979-
auto* dest = reinterpret_cast<SQLWCHAR*>(dest_buf);
980-
981-
if (buffer_length > static_cast<SQLLEN>(wstr_or->size())) {
982-
if (res_len) *res_len = wstr_or->size() * sizeof(SQLWCHAR);
983-
std::memcpy(dest, wstr_data.data(), wstr_or->size() * sizeof(SQLWCHAR));
984-
dest[wstr_or->size()] = L'\0';
985-
} else if (20 <= buffer_length && buffer_length <= static_cast<SQLLEN>(wstr_or->size())) {
986-
if (res_len) *res_len = buffer_length * sizeof(SQLWCHAR);
987-
std::memcpy(dest, wstr_data.data(), buffer_length * sizeof(SQLWCHAR));
988-
dest[buffer_length - 1] = L'\0';
989-
status_record = StatusRecord{SQLStates::k_01004(), "Data truncated"};
990-
} else {
991-
status_record =
992-
StatusRecord{SQLStates::k_22003(), "Buffer length is insufficient"};
993-
}
994-
995-
return status_record;
996-
}
997938
odbc_internal::StatusRecord ConvertFromTimestampDSValue(
998939
DSValue const& src_dsval, DataBuffer& dest_data) {
940+
using odbc_internal::SQLStates;
941+
using odbc_internal::StatusRecord;
999942

1000-
using odbc_internal::SQLStates;
1001-
using odbc_internal::StatusRecord;
1002-
1003-
std::string str_val;
1004-
DSValueToString(src_dsval, str_val);
1005-
std::string timestamp_src_str;
943+
std::string str_val;
944+
DSValueToString(src_dsval, str_val);
945+
std::string timestamp_src_str;
1006946

1007-
SQLSMALLINT dest_type = dest_data.type;
1008-
SQLPOINTER dest_buf = dest_data.buf;
1009-
SQLLEN buffer_length = dest_data.buflen;
1010-
SQLLEN* res_len = dest_data.result_len;
947+
SQLSMALLINT dest_type = dest_data.type;
948+
SQLPOINTER dest_buf = dest_data.buf;
949+
SQLLEN buffer_length = dest_data.buflen;
950+
SQLLEN* res_len = dest_data.result_len;
1011951

1012952
if (!dest_buf) {
1013953
return StatusRecord::Ok();
@@ -1020,7 +960,64 @@ odbc_internal::StatusRecord ConvertFromTimestampDSValue(
1020960

1021961
StatusRecord status_record = StatusRecord::Ok();
1022962

1023-
switch (dest_type) {
963+
// --- Check for ISO string with 'T' and long fraction ---
964+
auto t_pos = str_val.find('T');
965+
if (t_pos != std::string::npos) {
966+
auto dot_pos = str_val.find('.', t_pos);
967+
bool long_fraction = false;
968+
969+
if (dot_pos != std::string::npos) {
970+
std::size_t fraction_length = str_val.size() - dot_pos - 1;
971+
if (!str_val.empty() && str_val.back() == 'Z') --fraction_length;
972+
if (fraction_length > 9) long_fraction = true;
973+
}
974+
975+
if (long_fraction) {
976+
// Trim 'Z' and replace 'T' with space
977+
if (!str_val.empty() && str_val.back() == 'Z') str_val.pop_back();
978+
str_val[t_pos] = ' ';
979+
timestamp_src_str = str_val;
980+
981+
switch (dest_type) {
982+
case SQL_C_CHAR:
983+
return ConvertTimestampStringToChar(timestamp_src_str, dest_buf,
984+
buffer_length, res_len);
985+
case SQL_C_WCHAR:
986+
return ConvertTimestampStringToWChar(timestamp_src_str, dest_buf,
987+
buffer_length, res_len);
988+
default:
989+
LOG(ERROR) << "ConvertFromTimestampDSValue:: Conversion unsupported "
990+
"for picosecond for C-type: "
991+
<< dest_type;
992+
return StatusRecord{SQLStates::k_HY000(),
993+
"Conversion unsupported for picosecond"};
994+
}
995+
}
996+
}
997+
// Conversion for unix epoch time
998+
bool looks_like_float_epoch = false;
999+
1000+
try {
1001+
size_t idx = 0;
1002+
std::stod(str_val, &idx);
1003+
if (idx == str_val.length()) {
1004+
looks_like_float_epoch = true;
1005+
}
1006+
} catch (...) {
1007+
looks_like_float_epoch = false;
1008+
}
1009+
SQL_TIMESTAMP_STRUCT timestamp_src_struct;
1010+
if (looks_like_float_epoch) {
1011+
timestamp_src_str = FloatTimestampToString(str_val);
1012+
timestamp_src_struct = ConvertStrToTimestampStruct(timestamp_src_str);
1013+
} else {
1014+
DSValueToTimestamp(src_dsval, timestamp_src_struct);
1015+
timestamp_src_str = FormatTimestampToString(timestamp_src_struct);
1016+
}
1017+
int k_timestamp_src_len = static_cast<int>(timestamp_src_str.length());
1018+
constexpr int kTimestampBinaryLength = sizeof(SQL_TIMESTAMP_STRUCT);
1019+
1020+
switch (dest_type) {
10241021
case SQL_C_CHAR: {
10251022
auto* dest = reinterpret_cast<char*>(dest_buf);
10261023
if (buffer_length > k_timestamp_src_len) {
@@ -2298,4 +2295,4 @@ StatusRecord ConvertFromRangeDSValue(DSValue const& src_dsval,
22982295
}
22992296
}
23002297

2301-
} // namespace google::cloud::odbc_bq_driver_internal
2298+
} // namespace google::cloud::odbc_bq_driver_internal

0 commit comments

Comments
 (0)