Skip to content

Commit e7c42b7

Browse files
committed
Clean up compiler warnings on Windows builds
Also provides the explanation of what's going on with the use of a dummy buffer address when binding parameters, as requested by a reviewer for another issue. Fixes #1476
1 parent cfe0575 commit e7c42b7

11 files changed

Lines changed: 124 additions & 148 deletions

File tree

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ def get_compiler_settings():
8989
'/wd4514', # unreference inline function removed
9090
'/wd4820', # padding after struct member
9191
'/wd4668', # is not defined as a preprocessor macro
92+
'/wd4710', # function not inlined
9293
'/wd4711', # function selected for automatic inline expansion
9394
'/wd4100', # unreferenced formal parameter
9495
'/wd4127', # "conditional expression is constant" testing compilation constants
9596
'/wd4191', # casts to PYCFunction which doesn't have the keywords parameter
97+
'/wd5045', # information note about Spectre mitigation (which we're not using)
9698
])
9799

98100
if '--windbg' in sys.argv:

src/connection.cpp

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,18 @@ static bool ApplyPreconnAttrs(HDBC hdbc, SQLINTEGER ikey, PyObject *value, char
109109

110110
if (PyLong_Check(value))
111111
{
112-
if (_PyLong_Sign(value) >= 0)
112+
unsigned long long uval = PyLong_AsUnsignedLongLong(value);
113+
if (PyErr_Occurred())
113114
{
114-
ivalue = (SQLPOINTER)PyLong_AsUnsignedLong(value);
115-
vallen = SQL_IS_UINTEGER;
116-
} else
117-
{
118-
ivalue = (SQLPOINTER)PyLong_AsLong(value);
115+
PyErr_Clear();
116+
ivalue = (SQLPOINTER)PyLong_AsLongLong(value);
119117
vallen = SQL_IS_INTEGER;
120118
}
119+
else
120+
{
121+
ivalue = (SQLPOINTER)uval;
122+
vallen = SQL_IS_UINTEGER;
123+
}
121124
}
122125
else if (PyByteArray_Check(value))
123126
{
@@ -377,9 +380,8 @@ static char conv_clear_doc[] =
377380
"clear_output_converters() --> None\n\n"
378381
"Remove all output converter functions.";
379382

380-
static PyObject* Connection_conv_clear(PyObject* self, PyObject* args)
383+
static PyObject* Connection_conv_clear(PyObject* self, PyObject* /* args (unused) */)
381384
{
382-
UNUSED(args);
383385
Connection* cnxn = (Connection*)self;
384386
Py_XDECREF(cnxn->map_sqltype_to_converter);
385387
cnxn->map_sqltype_to_converter = 0;
@@ -445,10 +447,8 @@ static char close_doc[] =
445447
"Note that closing a connection without committing the changes first will cause\n"
446448
"an implicit rollback to be performed.";
447449

448-
static PyObject* Connection_close(PyObject* self, PyObject* args)
450+
static PyObject* Connection_close(PyObject* self, PyObject* /* args (unused) */)
449451
{
450-
UNUSED(args);
451-
452452
Connection* cnxn = Connection_Validate(self);
453453
if (!cnxn)
454454
return 0;
@@ -458,10 +458,8 @@ static PyObject* Connection_close(PyObject* self, PyObject* args)
458458
Py_RETURN_NONE;
459459
}
460460

461-
static PyObject* Connection_cursor(PyObject* self, PyObject* args)
461+
static PyObject* Connection_cursor(PyObject* self, PyObject* /* args (unused) */)
462462
{
463-
UNUSED(args);
464-
465463
Connection* cnxn = Connection_Validate(self);
466464
if (!cnxn)
467465
return 0;
@@ -759,10 +757,8 @@ PyObject* Connection_endtrans(Connection* cnxn, SQLSMALLINT type)
759757
Py_RETURN_NONE;
760758
}
761759

762-
static PyObject* Connection_commit(PyObject* self, PyObject* args)
760+
static PyObject* Connection_commit(PyObject* self, PyObject* /* args (unused) */)
763761
{
764-
UNUSED(args);
765-
766762
Connection* cnxn = Connection_Validate(self);
767763
if (!cnxn)
768764
return 0;
@@ -772,10 +768,8 @@ static PyObject* Connection_commit(PyObject* self, PyObject* args)
772768
return Connection_endtrans(cnxn, SQL_COMMIT);
773769
}
774770

775-
static PyObject* Connection_rollback(PyObject* self, PyObject* args)
771+
static PyObject* Connection_rollback(PyObject* self, PyObject* /* args (unused) */)
776772
{
777-
UNUSED(args);
778-
779773
Connection* cnxn = Connection_Validate(self);
780774
if (!cnxn)
781775
return 0;
@@ -810,10 +804,8 @@ static char getinfo_doc[] =
810804
"Calls SQLGetInfo, passing `type`, and returns the result formatted as a Python object.";
811805

812806

813-
PyObject* Connection_getautocommit(PyObject* self, void* closure)
807+
PyObject* Connection_getautocommit(PyObject* self, void* /* closure (unused) */)
814808
{
815-
UNUSED(closure);
816-
817809
Connection* cnxn = Connection_Validate(self);
818810
if (!cnxn)
819811
return 0;
@@ -823,10 +815,8 @@ PyObject* Connection_getautocommit(PyObject* self, void* closure)
823815
return result;
824816
}
825817

826-
static int Connection_setautocommit(PyObject* self, PyObject* value, void* closure)
818+
static int Connection_setautocommit(PyObject* self, PyObject* value, void* /* closure (unused) */)
827819
{
828-
UNUSED(closure);
829-
830820
Connection* cnxn = Connection_Validate(self);
831821
if (!cnxn)
832822
return -1;
@@ -854,9 +844,8 @@ static int Connection_setautocommit(PyObject* self, PyObject* value, void* closu
854844
}
855845

856846

857-
static PyObject* Connection_getclosed(PyObject* self, void* closure)
847+
static PyObject* Connection_getclosed(PyObject* self, void* /* closure (unused) */)
858848
{
859-
UNUSED(closure);
860849
Connection* cnxn;
861850

862851
if (self == 0 || !Connection_Check(self))
@@ -876,10 +865,8 @@ static PyObject* Connection_getclosed(PyObject* self, void* closure)
876865
}
877866

878867

879-
static PyObject* Connection_getsearchescape(PyObject* self, void* closure)
868+
static PyObject* Connection_getsearchescape(PyObject* self, void* /* closure (unused) */)
880869
{
881-
UNUSED(closure);
882-
883870
Connection* cnxn = (Connection*)self;
884871

885872
if (!cnxn->searchescape)
@@ -901,21 +888,17 @@ static PyObject* Connection_getsearchescape(PyObject* self, void* closure)
901888
return cnxn->searchescape;
902889
}
903890

904-
static PyObject* Connection_getmaxwrite(PyObject* self, void* closure)
891+
static PyObject* Connection_getmaxwrite(PyObject* self, void* /* closure (unused) */)
905892
{
906-
UNUSED(closure);
907-
908893
Connection* cnxn = Connection_Validate(self);
909894
if (!cnxn)
910895
return 0;
911896

912897
return PyLong_FromSsize_t(cnxn->maxwrite);
913898
}
914899

915-
static int Connection_setmaxwrite(PyObject* self, PyObject* value, void* closure)
900+
static int Connection_setmaxwrite(PyObject* self, PyObject* value, void* /* closure (unused) */)
916901
{
917-
UNUSED(closure);
918-
919902
Connection* cnxn = Connection_Validate(self);
920903
if (!cnxn)
921904
return -1;
@@ -943,21 +926,17 @@ static int Connection_setmaxwrite(PyObject* self, PyObject* value, void* closure
943926
}
944927

945928

946-
static PyObject* Connection_gettimeout(PyObject* self, void* closure)
929+
static PyObject* Connection_gettimeout(PyObject* self, void* /* closure (unused) */)
947930
{
948-
UNUSED(closure);
949-
950931
Connection* cnxn = Connection_Validate(self);
951932
if (!cnxn)
952933
return 0;
953934

954935
return PyLong_FromLong(cnxn->timeout);
955936
}
956937

957-
static int Connection_settimeout(PyObject* self, PyObject* value, void* closure)
938+
static int Connection_settimeout(PyObject* self, PyObject* value, void* /* closure (unused) */)
958939
{
959-
UNUSED(closure);
960-
961940
Connection* cnxn = Connection_Validate(self);
962941
if (!cnxn)
963942
return -1;
@@ -1328,9 +1307,8 @@ static PyObject* Connection_setdecoding(PyObject* self, PyObject* args, PyObject
13281307

13291308

13301309
static char enter_doc[] = "__enter__() -> self.";
1331-
static PyObject* Connection_enter(PyObject* self, PyObject* args)
1310+
static PyObject* Connection_enter(PyObject* self, PyObject* /* args (unused) */)
13321311
{
1333-
UNUSED(args);
13341312
Py_INCREF(self);
13351313
return self;
13361314
}

src/cursor.cpp

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,8 @@ static char close_doc[] =
435435
"be unusable from this point forward; a ProgrammingError exception will be\n"
436436
"raised if any operation is attempted with the cursor.";
437437

438-
static PyObject* Cursor_close(PyObject* self, PyObject* args)
438+
static PyObject* Cursor_close(PyObject* self, PyObject* /* args (unused) */)
439439
{
440-
UNUSED(args);
441-
442440
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
443441
if (!cursor)
444442
return 0;
@@ -643,13 +641,12 @@ int GetDiagRecs(Cursor* cur)
643641
// Default to UTF-16, which may not work if the driver/manager is using some other encoding
644642
const char *unicode_enc = cur->cnxn ? cur->cnxn->metadata_enc.name : ENCSTR_UTF16NE;
645643
PyObject* msg_value = PyUnicode_Decode(
646-
(char*)cMessageText, iTextLength * sizeof(uint16_t), unicode_enc, "strict"
644+
(char*)cMessageText, (Py_ssize_t)(iTextLength * sizeof(uint16_t)), unicode_enc, "strict"
647645
);
648646
if (!msg_value)
649647
{
650648
// If the char cannot be decoded, return something rather than nothing.
651-
Py_XDECREF(msg_value);
652-
msg_value = PyBytes_FromStringAndSize((char*)cMessageText, iTextLength * sizeof(uint16_t));
649+
msg_value = PyBytes_FromStringAndSize((char*)cMessageText, (Py_ssize_t)(iTextLength * sizeof(uint16_t)));
653650
}
654651

655652
PyObject* msg_tuple = PyTuple_New(2); // the message as a Python tuple of class and value
@@ -1272,10 +1269,8 @@ static PyObject* Cursor_iternext(PyObject* self)
12721269
return result;
12731270
}
12741271

1275-
static PyObject* Cursor_fetchval(PyObject* self, PyObject* args)
1272+
static PyObject* Cursor_fetchval(PyObject* self, PyObject* /* args (unused) */)
12761273
{
1277-
UNUSED(args);
1278-
12791274
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_RESULTS | CURSOR_RAISE_ERROR);
12801275
if (!cursor)
12811276
return 0;
@@ -1292,10 +1287,8 @@ static PyObject* Cursor_fetchval(PyObject* self, PyObject* args)
12921287
return Row_item(row, 0);
12931288
}
12941289

1295-
static PyObject* Cursor_fetchone(PyObject* self, PyObject* args)
1290+
static PyObject* Cursor_fetchone(PyObject* self, PyObject* /* args (unused) */)
12961291
{
1297-
UNUSED(args);
1298-
12991292
PyObject* row;
13001293
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_RESULTS | CURSOR_RAISE_ERROR);
13011294
if (!cursor)
@@ -1314,10 +1307,8 @@ static PyObject* Cursor_fetchone(PyObject* self, PyObject* args)
13141307
}
13151308

13161309

1317-
static PyObject* Cursor_fetchall(PyObject* self, PyObject* args)
1310+
static PyObject* Cursor_fetchall(PyObject* self, PyObject* /* args (unused) */)
13181311
{
1319-
UNUSED(args);
1320-
13211312
PyObject* result;
13221313
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_RESULTS | CURSOR_RAISE_ERROR);
13231314
if (!cursor)
@@ -1809,10 +1800,8 @@ static char getTypeInfo_doc[] =
18091800
"17) num_prec_radix\n"
18101801
"18) interval_precision";
18111802

1812-
static PyObject* Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* kwargs)
1803+
static PyObject* Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* /* kwargs (unused) */)
18131804
{
1814-
UNUSED(kwargs);
1815-
18161805
int nDataType = SQL_ALL_TYPES;
18171806

18181807
if (!PyArg_ParseTuple(args, "|i", &nDataType))
@@ -1851,10 +1840,8 @@ static PyObject* Cursor_getTypeInfo(PyObject* self, PyObject* args, PyObject* kw
18511840
}
18521841

18531842

1854-
static PyObject* Cursor_nextset(PyObject* self, PyObject* args)
1843+
static PyObject* Cursor_nextset(PyObject* self, PyObject* /* args (unused) */)
18551844
{
1856-
UNUSED(args);
1857-
18581845
Cursor* cur = Cursor_Validate(self, 0);
18591846

18601847
if (!cur)
@@ -2149,9 +2136,8 @@ static char cancel_doc[] =
21492136
"This calls SQLCancel and is designed to be called from another thread to"
21502137
"stop processing of an ongoing query.";
21512138

2152-
static PyObject* Cursor_cancel(PyObject* self, PyObject* args)
2139+
static PyObject* Cursor_cancel(PyObject* self, PyObject* /* args (unused) */)
21532140
{
2154-
UNUSED(args);
21552141
Cursor* cur = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
21562142
if (!cur)
21572143
return 0;
@@ -2167,9 +2153,8 @@ static PyObject* Cursor_cancel(PyObject* self, PyObject* args)
21672153
}
21682154

21692155

2170-
static PyObject* Cursor_ignored(PyObject* self, PyObject* args)
2156+
static PyObject* Cursor_ignored(PyObject* /* self (unused) */, PyObject* /* args (unused) */)
21712157
{
2172-
UNUSED(self, args);
21732158
Py_RETURN_NONE;
21742159
}
21752160

@@ -2223,10 +2208,8 @@ static PyMemberDef Cursor_members[] =
22232208
{ 0 }
22242209
};
22252210

2226-
static PyObject* Cursor_getnoscan(PyObject* self, void *closure)
2211+
static PyObject* Cursor_getnoscan(PyObject* self, void* /* closure (unused) */)
22272212
{
2228-
UNUSED(closure);
2229-
22302213
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
22312214
if (!cursor)
22322215
return 0;
@@ -2249,10 +2232,8 @@ static PyObject* Cursor_getnoscan(PyObject* self, void *closure)
22492232
Py_RETURN_TRUE;
22502233
}
22512234

2252-
static int Cursor_setnoscan(PyObject* self, PyObject* value, void *closure)
2235+
static int Cursor_setnoscan(PyObject* self, PyObject* value, void* /* closure (unused) */)
22532236
{
2254-
UNUSED(closure);
2255-
22562237
Cursor* cursor = Cursor_Validate(self, CURSOR_REQUIRE_OPEN | CURSOR_RAISE_ERROR);
22572238
if (!cursor)
22582239
return -1;
@@ -2351,9 +2332,8 @@ static char setinputsizes_doc[] =
23512332
"Setting sizes to None reverts all parameters to the defaults.";
23522333

23532334
static char enter_doc[] = "__enter__() -> self.";
2354-
static PyObject* Cursor_enter(PyObject* self, PyObject* args)
2335+
static PyObject* Cursor_enter(PyObject* self, PyObject* /* args (unused) */)
23552336
{
2356-
UNUSED(args);
23572337
Py_INCREF(self);
23582338
return self;
23592339
}

src/cursor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ struct Cursor
100100
PyObject* pPreparedSQL;
101101

102102
// The number of parameter markers in pPreparedSQL. This will be zero when pPreparedSQL is zero but is set
103-
// immediately after preparing the SQL.
103+
// immediately after preparing the SQL. Must be between 0 and SHRT_MAX - 1 because ODBC uses a signed short for
104+
// indexing into the parameters in some places, with one-based (not zero-based) counting.
104105
int paramcount;
105106

106107
// If non-zero, a pointer to an array of SQL type values allocated via malloc. This is zero until we actually ask

src/errors.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ PyObject* GetErrorFromHandle(Connection *conn, const char* szFunction, HDBC hdbc
269269
// For now, default to UTF-16 if this is not in the context of a connection.
270270
// Note that this will not work if the DM is using a different wide encoding (e.g. UTF-32).
271271
const char *unicode_enc = conn ? conn->metadata_enc.name : ENCSTR_UTF16NE;
272-
Object msgStr(PyUnicode_Decode((char*)szMsg, cchMsg * sizeof(uint16_t), unicode_enc, "strict"));
272+
Object msgStr(PyUnicode_Decode((char*)szMsg, (Py_ssize_t)(cchMsg * sizeof(uint16_t)), unicode_enc, "strict"));
273273

274274
if (cchMsg != 0 && msgStr.Get())
275275
{

src/getdata.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -779,14 +779,14 @@ PyObject *GetData_SqlVariant(Cursor *cur, Py_ssize_t iCol) {
779779
// the ODBC driver read the sql_variant header which contains the underlying data type
780780
pBuff = 0;
781781
indicator = 0;
782-
retcode = SQLGetData(cur->hstmt, static_cast<SQLSMALLINT>(iCol + 1), SQL_C_BINARY,
782+
retcode = SQLGetData(cur->hstmt, static_cast<SQLUSMALLINT>(iCol + 1), SQL_C_BINARY,
783783
&pBuff, 0, &indicator);
784784
if (!SQL_SUCCEEDED(retcode))
785785
return RaiseErrorFromHandle(cur->cnxn, "SQLGetData", cur->cnxn->hdbc, cur->hstmt);
786786

787787
// Get the SQL_CA_SS_VARIANT_TYPE field for the column which will contain the underlying data type
788788
variantType = 0;
789-
retcode = SQLColAttribute(cur->hstmt, iCol + 1, SQL_CA_SS_VARIANT_TYPE, NULL, 0, NULL, &variantType);
789+
retcode = SQLColAttribute(cur->hstmt, static_cast<SQLUSMALLINT>(iCol + 1), SQL_CA_SS_VARIANT_TYPE, NULL, 0, NULL, &variantType);
790790
if (!SQL_SUCCEEDED(retcode))
791791
return RaiseErrorFromHandle(cur->cnxn, "SQLColAttribute", cur->cnxn->hdbc, cur->hstmt);
792792

0 commit comments

Comments
 (0)