|
21 | 21 | #define SQL_SS_TIMESTAMPOFFSET (-155) |
22 | 22 | #define SQL_C_SS_TIMESTAMPOFFSET (0x4001) |
23 | 23 | #define MAX_DIGITS_IN_NUMERIC 64 |
| 24 | +#define SQL_MAX_NUMERIC_LEN 16 |
24 | 25 |
|
25 | 26 | #define STRINGIFY_FOR_CASE(x) \ |
26 | 27 | case x: \ |
@@ -56,12 +57,16 @@ struct NumericData { |
56 | 57 | SQLCHAR precision; |
57 | 58 | SQLSCHAR scale; |
58 | 59 | SQLCHAR sign; // 1=pos, 0=neg |
59 | | - std::uint64_t val; // 123.45 -> 12345 |
| 60 | + std::string val; // 123.45 -> 12345 |
60 | 61 |
|
61 | | - NumericData() : precision(0), scale(0), sign(0), val(0) {} |
| 62 | + NumericData() : precision(0), scale(0), sign(0), val(SQL_MAX_NUMERIC_LEN, '\0') {} |
62 | 63 |
|
63 | | - NumericData(SQLCHAR precision, SQLSCHAR scale, SQLCHAR sign, std::uint64_t value) |
64 | | - : precision(precision), scale(scale), sign(sign), val(value) {} |
| 64 | + NumericData(SQLCHAR precision, SQLSCHAR scale, SQLCHAR sign, const std::string& valueBytes) |
| 65 | + : precision(precision), scale(scale), sign(sign) { |
| 66 | + val = valueBytes; |
| 67 | + // Ensure val is always exactly SQL_MAX_NUMERIC_LEN bytes |
| 68 | + val.resize(SQL_MAX_NUMERIC_LEN, '\0'); |
| 69 | + } |
65 | 70 | }; |
66 | 71 |
|
67 | 72 | // Struct to hold the DateTimeOffset structure |
@@ -557,9 +562,21 @@ SQLRETURN BindParameters(SQLHANDLE hStmt, const py::list& params, |
557 | 562 | decimalPtr->sign = decimalParam.sign; |
558 | 563 | // Convert the integer decimalParam.val to char array |
559 | 564 | std::memset(static_cast<void*>(decimalPtr->val), 0, sizeof(decimalPtr->val)); |
560 | | - std::memcpy(static_cast<void*>(decimalPtr->val), |
561 | | - reinterpret_cast<char*>(&decimalParam.val), |
562 | | - sizeof(decimalParam.val)); |
| 565 | + // std::memcpy(static_cast<void*>(decimalPtr->val), |
| 566 | + // reinterpret_cast<char*>(&decimalParam.val), |
| 567 | + // sizeof(decimalParam.val)); |
| 568 | + size_t src_len = decimalParam.val.size(); |
| 569 | + if (src_len > sizeof(decimalPtr->val)) { |
| 570 | + // Defensive: should never happen if Python side ensures 16 bytes; but guard anyway |
| 571 | + ThrowStdException("Numeric value byte buffer too large for SQL_NUMERIC_STRUCT (paramIndex " + std::to_string(paramIndex) + ")"); |
| 572 | + } |
| 573 | + if (src_len > 0) { |
| 574 | + std::memcpy(static_cast<void*>(decimalPtr->val), |
| 575 | + static_cast<const void*>(decimalParam.val.data()), |
| 576 | + src_len); |
| 577 | + } |
| 578 | + //print the data received from python |
| 579 | + LOG("Numeric parameter val bytes: {}", decimalPtr->val); |
563 | 580 | dataPtr = static_cast<void*>(decimalPtr); |
564 | 581 | break; |
565 | 582 | } |
@@ -3794,7 +3811,7 @@ PYBIND11_MODULE(ddbc_bindings, m) { |
3794 | 3811 | // Define numeric data class |
3795 | 3812 | py::class_<NumericData>(m, "NumericData") |
3796 | 3813 | .def(py::init<>()) |
3797 | | - .def(py::init<SQLCHAR, SQLSCHAR, SQLCHAR, std::uint64_t>()) |
| 3814 | + .def(py::init<SQLCHAR, SQLSCHAR, SQLCHAR, const std::string&>()) |
3798 | 3815 | .def_readwrite("precision", &NumericData::precision) |
3799 | 3816 | .def_readwrite("scale", &NumericData::scale) |
3800 | 3817 | .def_readwrite("sign", &NumericData::sign) |
|
0 commit comments