Skip to content

Commit 8f52c85

Browse files
committed
Removing dead code
1 parent 35b5df6 commit 8f52c85

File tree

2 files changed

+0
-220
lines changed

2 files changed

+0
-220
lines changed

mssql_python/pybind/ddbc_bindings.cpp

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#define SQL_MAX_NUMERIC_LEN 16
3131
#define SQL_SS_XML (-152)
3232
#define SQL_SS_UDT (-151)
33-
#define SQL_TIME_TEXT_MAX_LEN 32
3433
#define SQL_SS_VARIANT (-150)
3534
#define SQL_CA_SS_VARIANT_TYPE (1215)
3635
#ifndef SQL_C_DATE
@@ -73,121 +72,6 @@ namespace PythonObjectCache {
7372
py::object get_time_class();
7473
}
7574

76-
inline py::object ParseSqlTimeTextToPythonObject(const char* timeText, SQLLEN timeTextLen) {
77-
if (!timeText || (timeTextLen <= 0 && timeTextLen != SQL_NO_TOTAL)) {
78-
return py::none();
79-
}
80-
81-
size_t len;
82-
if (timeTextLen == SQL_NO_TOTAL) {
83-
// When the driver reports SQL_NO_TOTAL, the buffer may not be null-terminated.
84-
// Bound the scan to the maximum expected TIME/TIME2 text length.
85-
const void* nul = std::memchr(timeText, '\0', SQL_TIME_TEXT_MAX_LEN - 1);
86-
len = nul ? static_cast<size_t>(static_cast<const char*>(nul) - timeText)
87-
: static_cast<size_t>(SQL_TIME_TEXT_MAX_LEN - 1);
88-
} else {
89-
len = static_cast<size_t>(timeTextLen);
90-
if (len > SQL_TIME_TEXT_MAX_LEN - 1) {
91-
len = SQL_TIME_TEXT_MAX_LEN - 1;
92-
}
93-
}
94-
95-
std::string value(timeText, len);
96-
97-
size_t start = value.find_first_not_of(" \t\r\n");
98-
if (start == std::string::npos) {
99-
return py::none();
100-
}
101-
size_t end = value.find_last_not_of(" \t\r\n");
102-
value = value.substr(start, end - start + 1);
103-
104-
size_t firstColon = value.find(':');
105-
size_t secondColon =
106-
(firstColon == std::string::npos) ? std::string::npos : value.find(':', firstColon + 1);
107-
if (firstColon == std::string::npos || secondColon == std::string::npos) {
108-
ThrowStdException("Failed to parse TIME/TIME2 value: missing ':' separators");
109-
}
110-
111-
int hour, minute, second = 0, microsecond = 0;
112-
113-
try {
114-
hour = std::stoi(value.substr(0, firstColon));
115-
} catch (const std::exception& e) {
116-
ThrowStdException(
117-
("Failed to parse hour from TIME/TIME2 value '" + value + "': " + e.what()).c_str());
118-
}
119-
try {
120-
minute = std::stoi(value.substr(firstColon + 1, secondColon - firstColon - 1));
121-
} catch (const std::exception& e) {
122-
ThrowStdException(
123-
("Failed to parse minute from TIME/TIME2 value '" + value + "': " + e.what()).c_str());
124-
}
125-
126-
size_t dotPos = value.find('.', secondColon + 1);
127-
128-
if (dotPos == std::string::npos) {
129-
try {
130-
second = std::stoi(value.substr(secondColon + 1));
131-
} catch (const std::exception& e) {
132-
ThrowStdException(
133-
("Failed to parse second from TIME/TIME2 value '" + value + "': " + e.what())
134-
.c_str());
135-
}
136-
} else {
137-
try {
138-
second = std::stoi(value.substr(secondColon + 1, dotPos - secondColon - 1));
139-
} catch (const std::exception& e) {
140-
ThrowStdException(
141-
("Failed to parse second from TIME/TIME2 value '" + value + "': " + e.what())
142-
.c_str());
143-
}
144-
std::string frac = value.substr(dotPos + 1);
145-
146-
size_t digitCount = 0;
147-
while (digitCount < frac.size() &&
148-
std::isdigit(static_cast<unsigned char>(frac[digitCount]))) {
149-
++digitCount;
150-
}
151-
frac = frac.substr(0, digitCount);
152-
153-
if (frac.size() > 6) {
154-
frac = frac.substr(0, 6);
155-
}
156-
while (frac.size() < 6) {
157-
frac.push_back('0');
158-
}
159-
if (!frac.empty()) {
160-
try {
161-
microsecond = std::stoi(frac);
162-
} catch (const std::exception& e) {
163-
ThrowStdException(("Failed to parse microseconds from TIME/TIME2 value '" + value +
164-
"': " + e.what())
165-
.c_str());
166-
}
167-
}
168-
}
169-
170-
if (hour < 0 || hour > 23) {
171-
ThrowStdException(
172-
("Hour out of range (0-23) in TIME/TIME2 value: " + std::to_string(hour)).c_str());
173-
}
174-
if (minute < 0 || minute > 59) {
175-
ThrowStdException(
176-
("Minute out of range (0-59) in TIME/TIME2 value: " + std::to_string(minute)).c_str());
177-
}
178-
if (second < 0 || second > 59) {
179-
ThrowStdException(
180-
("Second out of range (0-59) in TIME/TIME2 value: " + std::to_string(second)).c_str());
181-
}
182-
if (microsecond < 0 || microsecond > 999999) {
183-
ThrowStdException(("Microsecond out of range (0-999999) in TIME/TIME2 value: " +
184-
std::to_string(microsecond))
185-
.c_str());
186-
}
187-
188-
return PythonObjectCache::get_time_class()(hour, minute, second, microsecond);
189-
}
190-
19175
//-------------------------------------------------------------------------------------------------
19276
//-------------------------------------------------------------------------------------------------
19377
// Logging Infrastructure:
@@ -4661,10 +4545,6 @@ PYBIND11_MODULE(ddbc_bindings, m) {
46614545
// Expose architecture-specific constants
46624546
m.attr("ARCHITECTURE") = ARCHITECTURE;
46634547

4664-
// Test helper: expose time-text parser for unit testing edge cases
4665-
m.def("_test_parse_time_text", &ParseSqlTimeTextToPythonObject,
4666-
"Parse a SQL TIME/TIME2 text buffer into a Python datetime.time object (test helper)",
4667-
py::arg("timeText"), py::arg("timeTextLen"));
46684548
m.attr("SQL_NO_TOTAL") = static_cast<int>(SQL_NO_TOTAL);
46694549

46704550
// Expose the C++ functions to Python

tests/test_004_cursor.py

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -482,106 +482,6 @@ def test_time_executemany(cursor, db_connection):
482482
db_connection.commit()
483483

484484

485-
# ---------------------------------------------------------------------------
486-
# Unit tests for ParseSqlTimeTextToPythonObject (exposed via _test_parse_time_text)
487-
# These exercise defensive C++ branches that are unreachable through normal
488-
# ODBC queries: null/zero-length input, SQL_NO_TOTAL, oversized length,
489-
# whitespace-only buffers, and malformed text without colon separators.
490-
# ---------------------------------------------------------------------------
491-
492-
493-
class TestParseSqlTimeText:
494-
"""Direct tests for the C++ ParseSqlTimeTextToPythonObject helper."""
495-
496-
@staticmethod
497-
def _parse(text, length):
498-
from mssql_python.ddbc_bindings import _test_parse_time_text
499-
500-
return _test_parse_time_text(text, length)
501-
502-
@staticmethod
503-
def _sql_no_total():
504-
from mssql_python.ddbc_bindings import SQL_NO_TOTAL
505-
506-
return SQL_NO_TOTAL
507-
508-
def test_zero_length_returns_none(self):
509-
"""Lines 64-65: timeTextLen <= 0 → py::none()"""
510-
assert self._parse("12:00:00", 0) is None
511-
512-
def test_negative_length_returns_none(self):
513-
"""Lines 64-65: timeTextLen < 0 (but not SQL_NO_TOTAL) → py::none()"""
514-
assert self._parse("12:00:00", -999) is None
515-
516-
def test_sql_no_total_uses_bounded_scan(self):
517-
"""Lines 71-73: SQL_NO_TOTAL → memchr-bounded length scan."""
518-
result = self._parse("14:30:00.123456", self._sql_no_total())
519-
assert result == time(14, 30, 0, 123456)
520-
521-
def test_oversized_length_is_clamped(self):
522-
"""Lines 77-78: timeTextLen > SQL_TIME_TEXT_MAX_LEN-1 → clamp."""
523-
result = self._parse("09:15:30.000000", 9999)
524-
assert result == time(9, 15, 30)
525-
526-
def test_whitespace_only_returns_none(self):
527-
"""Lines 85-86: value is all whitespace → py::none()"""
528-
assert self._parse(" \t\n ", 7) is None
529-
530-
def test_missing_colon_raises(self):
531-
"""Lines 94-95: no ':' separators → ThrowStdException."""
532-
with pytest.raises(Exception, match="missing ':' separators"):
533-
self._parse("no-colons-here", 14)
534-
535-
def test_normal_time_with_fraction(self):
536-
"""Sanity check: normal parse path."""
537-
result = self._parse("08:05:03.100000", 15)
538-
assert result == time(8, 5, 3, 100000)
539-
540-
def test_normal_time_without_fraction(self):
541-
"""Sanity check: parse path without fractional part."""
542-
result = self._parse("23:59:59", 8)
543-
assert result == time(23, 59, 59)
544-
545-
# --- try-catch on std::stoi ---
546-
547-
def test_invalid_hour_raises(self):
548-
"""std::stoi fails on non-numeric hour → descriptive error."""
549-
with pytest.raises(Exception, match="Failed to parse hour"):
550-
self._parse("AB:00:00", 8)
551-
552-
def test_invalid_minute_raises(self):
553-
"""std::stoi fails on non-numeric minute → descriptive error."""
554-
with pytest.raises(Exception, match="Failed to parse minute"):
555-
self._parse("12:XY:00", 8)
556-
557-
def test_invalid_second_raises(self):
558-
"""std::stoi fails on non-numeric second → descriptive error."""
559-
with pytest.raises(Exception, match="Failed to parse second"):
560-
self._parse("12:00:ZZ", 8)
561-
562-
def test_invalid_microsecond_treated_as_zero(self):
563-
"""Non-digit fractional chars are stripped, resulting in microsecond=0."""
564-
result = self._parse("12:00:00.ABCDEF", 15)
565-
assert result == time(12, 0, 0, 0)
566-
567-
# --- range validation ---
568-
569-
def test_hour_out_of_range_raises(self):
570-
"""Hour > 23 → descriptive range error."""
571-
with pytest.raises(Exception, match="Hour out of range"):
572-
self._parse("25:00:00", 8)
573-
574-
def test_minute_out_of_range_raises(self):
575-
"""Minute > 59 → descriptive range error."""
576-
with pytest.raises(Exception, match="Minute out of range"):
577-
self._parse("12:60:00", 8)
578-
579-
def test_second_out_of_range_raises(self):
580-
"""Second > 59 → descriptive range error."""
581-
with pytest.raises(Exception, match="Second out of range"):
582-
self._parse("12:00:99", 8)
583-
584-
585485
# ---------------------------------------------------------------------------
586486
# Unit tests for _normalize_time_param helper
587487
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)