@@ -270,17 +270,17 @@ bool TryTransformPythonIntegerToDouble(Value &res, py::handle ele) {
270270 return true ;
271271}
272272
273- // Converts a Python integer that overflows int64/uint64 into a HUGEINT or UHUGEINT Value by decomposing it into upper
274- // and lower 64-bit components. Tries HUGEINT first; falls back to UHUGEINT for large positive values.
275- static Value TransformPythonLongToHugeInt (py::handle ele, const LogicalType &target_type) {
273+ // Tries to convert a Python integer that overflows int64/uint64 into a HUGEINT or UHUGEINT Value
274+ // by decomposing it into upper and lower 64-bit components. Tries HUGEINT first; falls back to
275+ // UHUGEINT for large positive values. Returns false if the value doesn't fit in 128 bits.
276+ static bool TryTransformPythonLongToHugeInt (py::handle ele, const LogicalType &target_type, Value &result) {
276277 auto ptr = ele.ptr ();
277278
278279 // Extract lower 64 bits (two's complement, works for negative values too)
279280 uint64_t lower = PyLong_AsUnsignedLongLongMask (ptr);
280281 if (lower == static_cast <uint64_t >(-1 ) && PyErr_Occurred ()) {
281282 PyErr_Clear ();
282- throw InvalidInputException (" Failed to convert Python integer to 128-bit integer: %s" ,
283- std::string (py::str (ele)));
283+ return false ;
284284 }
285285
286286 // Extract upper bits by right-shifting by 64
@@ -293,24 +293,37 @@ static Value TransformPythonLongToHugeInt(py::handle ele, const LogicalType &tar
293293 if (overflow == 0 && !(upper_signed == -1 && PyErr_Occurred ())) {
294294 auto val = Value::HUGEINT (hugeint_t {upper_signed, lower});
295295 if (target_type.id () == LogicalTypeId::UNKNOWN || target_type.id () == LogicalTypeId::HUGEINT) {
296- return val;
296+ result = val;
297+ } else {
298+ result = CastToTarget (std::move (val), target_type);
297299 }
298- return CastToTarget ( std::move (val), target_type) ;
300+ return true ;
299301 }
300302 PyErr_Clear ();
301303
302304 // Try unsigned 128-bit (uhugeint)
303305 uint64_t upper_unsigned = PyLong_AsUnsignedLongLong (upper_obj.ptr ());
304306 if (PyErr_Occurred ()) {
305307 PyErr_Clear ();
306- throw InvalidInputException ( " Python integer too large for 128-bit integer type: %s " , std::string ( py::str (ele))) ;
308+ return false ;
307309 }
308310
309311 auto val = Value::UHUGEINT (uhugeint_t {upper_unsigned, lower});
310312 if (target_type.id () == LogicalTypeId::UNKNOWN || target_type.id () == LogicalTypeId::UHUGEINT) {
311- return val;
313+ result = val;
314+ } else {
315+ result = CastToTarget (std::move (val), target_type);
316+ }
317+ return true ;
318+ }
319+
320+ // Throwing wrapper for contexts that require a result (e.g. prepared statement parameters).
321+ static Value TransformPythonLongToHugeInt (py::handle ele, const LogicalType &target_type) {
322+ Value result;
323+ if (!TryTransformPythonLongToHugeInt (ele, target_type, result)) {
324+ throw InvalidInputException (" Python integer too large for 128-bit integer type: %s" , std::string (py::str (ele)));
312325 }
313- return CastToTarget ( std::move (val), target_type) ;
326+ return result ;
314327}
315328
316329void TransformPythonUnsigned (uint64_t value, Value &res) {
@@ -347,8 +360,7 @@ bool TryTransformPythonNumeric(Value &res, py::handle ele, const LogicalType &ta
347360 throw InvalidInputException (StringUtil::Format (" Failed to cast value: Python value '%s' to INT64" ,
348361 std::string (pybind11::str (ele))));
349362 }
350- res = TransformPythonLongToHugeInt (ele, target_type);
351- return true ;
363+ return TryTransformPythonLongToHugeInt (ele, target_type, res);
352364 } else if (overflow == 1 ) {
353365 if (target_type.InternalType () == PhysicalType::INT64) {
354366 throw InvalidInputException (StringUtil::Format (" Failed to cast value: Python value '%s' to INT64" ,
@@ -357,8 +369,7 @@ bool TryTransformPythonNumeric(Value &res, py::handle ele, const LogicalType &ta
357369 uint64_t unsigned_value = PyLong_AsUnsignedLongLong (ptr);
358370 if (PyErr_Occurred ()) {
359371 PyErr_Clear ();
360- res = TransformPythonLongToHugeInt (ele, target_type);
361- return true ;
372+ return TryTransformPythonLongToHugeInt (ele, target_type, res);
362373 }
363374 TransformPythonUnsigned (unsigned_value, res);
364375 PyErr_Clear ();
0 commit comments