summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Modules/_sqlite/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Modules/_sqlite/cursor.c')
-rw-r--r--contrib/tools/python3/Modules/_sqlite/cursor.c145
1 files changed, 92 insertions, 53 deletions
diff --git a/contrib/tools/python3/Modules/_sqlite/cursor.c b/contrib/tools/python3/Modules/_sqlite/cursor.c
index d489d2b3dc2..cc014c37323 100644
--- a/contrib/tools/python3/Modules/_sqlite/cursor.c
+++ b/contrib/tools/python3/Modules/_sqlite/cursor.c
@@ -21,11 +21,18 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "cursor.h"
#include "microprotocols.h"
#include "module.h"
#include "util.h"
+#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
+
typedef enum {
TYPE_LONG,
TYPE_FLOAT,
@@ -174,9 +181,7 @@ cursor_dealloc(pysqlite_Cursor *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- if (self->in_weakreflist != NULL) {
- PyObject_ClearWeakRefs((PyObject*)self);
- }
+ FT_CLEAR_WEAKREFS((PyObject*)self, self->in_weakreflist);
tp->tp_clear((PyObject *)self);
tp->tp_free(self);
Py_DECREF(tp);
@@ -461,6 +466,9 @@ static int check_cursor(pysqlite_Cursor* cur)
return 0;
}
+ assert(cur->connection != NULL);
+ assert(cur->connection->state != NULL);
+
if (cur->closed) {
PyErr_SetString(cur->connection->state->ProgrammingError,
"Cannot operate on a closed cursor.");
@@ -557,43 +565,40 @@ bind_param(pysqlite_state *state, pysqlite_Statement *self, int pos,
switch (paramtype) {
case TYPE_LONG: {
sqlite_int64 value = _pysqlite_long_as_int64(parameter);
- if (value == -1 && PyErr_Occurred())
- rc = -1;
- else
- rc = sqlite3_bind_int64(self->st, pos, value);
+ rc = (value == -1 && PyErr_Occurred())
+ ? SQLITE_ERROR
+ : sqlite3_bind_int64(self->st, pos, value);
break;
}
case TYPE_FLOAT: {
double value = PyFloat_AsDouble(parameter);
- if (value == -1 && PyErr_Occurred()) {
- rc = -1;
- }
- else {
- rc = sqlite3_bind_double(self->st, pos, value);
- }
+ rc = (value == -1 && PyErr_Occurred())
+ ? SQLITE_ERROR
+ : sqlite3_bind_double(self->st, pos, value);
break;
}
case TYPE_UNICODE:
string = PyUnicode_AsUTF8AndSize(parameter, &buflen);
- if (string == NULL)
- return -1;
+ if (string == NULL) {
+ return SQLITE_ERROR;
+ }
if (buflen > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"string longer than INT_MAX bytes");
- return -1;
+ return SQLITE_ERROR;
}
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
break;
case TYPE_BUFFER: {
Py_buffer view;
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
- return -1;
+ return SQLITE_ERROR;
}
if (view.len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"BLOB longer than INT_MAX bytes");
PyBuffer_Release(&view);
- return -1;
+ return SQLITE_ERROR;
}
rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
PyBuffer_Release(&view);
@@ -603,7 +608,7 @@ bind_param(pysqlite_state *state, pysqlite_Statement *self, int pos,
PyErr_Format(state->ProgrammingError,
"Error binding parameter %d: type '%s' is not supported",
pos, Py_TYPE(parameter)->tp_name);
- rc = -1;
+ rc = SQLITE_ERROR;
}
final:
@@ -715,7 +720,6 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
} else if (PyDict_Check(parameters)) {
/* parameters passed as dictionary */
for (i = 1; i <= num_params_needed; i++) {
- PyObject *binding_name_obj;
Py_BEGIN_ALLOW_THREADS
binding_name = sqlite3_bind_parameter_name(self->st, i);
Py_END_ALLOW_THREADS
@@ -727,23 +731,17 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self,
}
binding_name++; /* skip first char (the colon) */
- binding_name_obj = PyUnicode_FromString(binding_name);
- if (!binding_name_obj) {
+ PyObject *current_param = NULL;
+ int found = PyMapping_GetOptionalItemString(parameters,
+ binding_name,
+ &current_param);
+ if (found == -1) {
return;
}
- if (PyDict_CheckExact(parameters)) {
- PyObject *item = PyDict_GetItemWithError(parameters, binding_name_obj);
- current_param = Py_XNewRef(item);
- } else {
- current_param = PyObject_GetItem(parameters, binding_name_obj);
- }
- Py_DECREF(binding_name_obj);
- if (!current_param) {
- if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) {
- PyErr_Format(state->ProgrammingError,
- "You did not supply a value for binding "
- "parameter :%s.", binding_name);
- }
+ else if (found == 0) {
+ PyErr_Format(state->ProgrammingError,
+ "You did not supply a value for binding "
+ "parameter :%s.", binding_name);
return;
}
@@ -1162,35 +1160,37 @@ pysqlite_cursor_fetchone_impl(pysqlite_Cursor *self)
/*[clinic input]
_sqlite3.Cursor.fetchmany as pysqlite_cursor_fetchmany
- size as maxrows: int(c_default='self->arraysize') = 1
+ size as maxrows: size_t(c_default='((pysqlite_Cursor *)self)->arraysize') = 1
The default value is set by the Cursor.arraysize attribute.
Fetches several rows from the resultset.
[clinic start generated code]*/
static PyObject *
-pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, int maxrows)
-/*[clinic end generated code: output=a8ef31fea64d0906 input=c26e6ca3f34debd0]*/
+pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, size_t maxrows)
+/*[clinic end generated code: output=8bff46d4f24c9e84 input=5485f1f2ae46c2ff]*/
{
+ if (maxrows > (size_t)UINT32_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large for C uint32_t");
+ return NULL;
+ }
+
PyObject* row;
PyObject* list;
- int counter = 0;
list = PyList_New(0);
if (!list) {
return NULL;
}
- while ((row = pysqlite_cursor_iternext(self))) {
- if (PyList_Append(list, row) < 0) {
- Py_DECREF(row);
- break;
- }
+ while (maxrows > 0 && (row = pysqlite_cursor_iternext(self))) {
+ int rc = PyList_Append(list, row);
Py_DECREF(row);
-
- if (++counter == maxrows) {
+ if (rc < 0) {
break;
}
+ maxrows--;
}
if (PyErr_Occurred()) {
@@ -1304,6 +1304,40 @@ pysqlite_cursor_close_impl(pysqlite_Cursor *self)
Py_RETURN_NONE;
}
+/*[clinic input]
+@getter
+_sqlite3.Cursor.arraysize
+[clinic start generated code]*/
+
+static PyObject *
+_sqlite3_Cursor_arraysize_get_impl(pysqlite_Cursor *self)
+/*[clinic end generated code: output=e0919d97175e6c50 input=3278f8d3ecbd90e3]*/
+{
+ return PyLong_FromSize_t(self->arraysize);
+}
+
+/*[clinic input]
+@setter
+_sqlite3.Cursor.arraysize
+[clinic start generated code]*/
+
+static int
+_sqlite3_Cursor_arraysize_set_impl(pysqlite_Cursor *self, PyObject *value)
+/*[clinic end generated code: output=af59a6b09f8cce6e input=ace48cb114e26060]*/
+{
+ size_t converted;
+ if (!_PyLong_Size_t_Converter(value, &converted)) {
+ return -1;
+ }
+ if (converted > (size_t)UINT32_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C uint32_t");
+ return -1;
+ }
+ self->arraysize = (uint32_t)converted;
+ return 0;
+}
+
static PyMethodDef cursor_methods[] = {
PYSQLITE_CURSOR_CLOSE_METHODDEF
PYSQLITE_CURSOR_EXECUTEMANY_METHODDEF
@@ -1319,16 +1353,20 @@ static PyMethodDef cursor_methods[] = {
static struct PyMemberDef cursor_members[] =
{
- {"connection", T_OBJECT, offsetof(pysqlite_Cursor, connection), READONLY},
- {"description", T_OBJECT, offsetof(pysqlite_Cursor, description), READONLY},
- {"arraysize", T_INT, offsetof(pysqlite_Cursor, arraysize), 0},
- {"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), READONLY},
- {"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), READONLY},
- {"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0},
- {"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), READONLY},
+ {"connection", _Py_T_OBJECT, offsetof(pysqlite_Cursor, connection), Py_READONLY},
+ {"description", _Py_T_OBJECT, offsetof(pysqlite_Cursor, description), Py_READONLY},
+ {"lastrowid", _Py_T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), Py_READONLY},
+ {"rowcount", Py_T_LONG, offsetof(pysqlite_Cursor, rowcount), Py_READONLY},
+ {"row_factory", _Py_T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0},
+ {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), Py_READONLY},
{NULL}
};
+static struct PyGetSetDef cursor_getsets[] = {
+ _SQLITE3_CURSOR_ARRAYSIZE_GETSETDEF
+ {NULL},
+};
+
static const char cursor_doc[] =
PyDoc_STR("SQLite database cursor class.");
@@ -1339,6 +1377,7 @@ static PyType_Slot cursor_slots[] = {
{Py_tp_iternext, pysqlite_cursor_iternext},
{Py_tp_methods, cursor_methods},
{Py_tp_members, cursor_members},
+ {Py_tp_getset, cursor_getsets},
{Py_tp_init, pysqlite_cursor_init},
{Py_tp_traverse, cursor_traverse},
{Py_tp_clear, cursor_clear},