diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-05-20 13:41:44 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-05-21 14:16:03 -0400 |
| commit | 4550983e0ce2f35b3585e53894c941c23693e71d (patch) | |
| tree | 3928e6e333c2b9bb6e23a4de079565a387d309ae /lib/sqlalchemy/cextension | |
| parent | 3d55263c92ee29a0257d823124c353a35246cf31 (diff) | |
| download | sqlalchemy-4550983e0ce2f35b3585e53894c941c23693e71d.tar.gz | |
Performance fixes for new result set
A few small mistakes led to huge callcounts. Additionally,
the warn-on-get behavior which is attempting to warn for
deprecated access in SQLAlchemy 2.0 is very expensive; it's not clear
if its feasible to have this warning or to somehow alter how it
works.
Fixes: #5340
Change-Id: I73bdd2d7b6f1b25cc0222accabd585cf761a5af4
Diffstat (limited to 'lib/sqlalchemy/cextension')
| -rw-r--r-- | lib/sqlalchemy/cextension/resultproxy.c | 137 |
1 files changed, 104 insertions, 33 deletions
diff --git a/lib/sqlalchemy/cextension/resultproxy.c b/lib/sqlalchemy/cextension/resultproxy.c index d5a6ea0c8..244379116 100644 --- a/lib/sqlalchemy/cextension/resultproxy.c +++ b/lib/sqlalchemy/cextension/resultproxy.c @@ -45,12 +45,19 @@ typedef struct { PyObject *parent; PyObject *row; PyObject *keymap; + long key_style; } BaseRow; static PyObject *sqlalchemy_engine_row = NULL; static PyObject *sqlalchemy_engine_result = NULL; + +//static int KEY_INTEGER_ONLY = 0; +//static int KEY_OBJECTS_ONLY = 1; +static int KEY_OBJECTS_BUT_WARN = 2; +//static int KEY_OBJECTS_NO_WARN = 3; + /**************** * BaseRow * ****************/ @@ -90,13 +97,13 @@ safe_rowproxy_reconstructor(PyObject *self, PyObject *args) static int BaseRow_init(BaseRow *self, PyObject *args, PyObject *kwds) { - PyObject *parent, *keymap, *row, *processors; + PyObject *parent, *keymap, *row, *processors, *key_style; Py_ssize_t num_values, num_processors; PyObject **valueptr, **funcptr, **resultptr; PyObject *func, *result, *processed_value, *values_fastseq; - if (!PyArg_UnpackTuple(args, "BaseRow", 4, 4, - &parent, &processors, &keymap, &row)) + if (!PyArg_UnpackTuple(args, "BaseRow", 5, 5, + &parent, &processors, &keymap, &key_style, &row)) return -1; Py_INCREF(parent); @@ -107,44 +114,61 @@ BaseRow_init(BaseRow *self, PyObject *args, PyObject *kwds) return -1; num_values = PySequence_Length(values_fastseq); - num_processors = PySequence_Size(processors); - if (num_values != num_processors) { - PyErr_Format(PyExc_RuntimeError, - "number of values in row (%d) differ from number of column " - "processors (%d)", - (int)num_values, (int)num_processors); - return -1; + + + if (processors != Py_None) { + num_processors = PySequence_Size(processors); + if (num_values != num_processors) { + PyErr_Format(PyExc_RuntimeError, + "number of values in row (%d) differ from number of column " + "processors (%d)", + (int)num_values, (int)num_processors); + return -1; + } + + } else { + num_processors = -1; } result = PyTuple_New(num_values); if (result == NULL) return -1; - valueptr = PySequence_Fast_ITEMS(values_fastseq); - funcptr = PySequence_Fast_ITEMS(processors); - resultptr = PySequence_Fast_ITEMS(result); - while (--num_values >= 0) { - func = *funcptr; - if (func != Py_None) { - processed_value = PyObject_CallFunctionObjArgs( - func, *valueptr, NULL); - if (processed_value == NULL) { - Py_DECREF(values_fastseq); - Py_DECREF(result); - return -1; + if (num_processors != -1) { + valueptr = PySequence_Fast_ITEMS(values_fastseq); + funcptr = PySequence_Fast_ITEMS(processors); + resultptr = PySequence_Fast_ITEMS(result); + while (--num_values >= 0) { + func = *funcptr; + if (func != Py_None) { + processed_value = PyObject_CallFunctionObjArgs( + func, *valueptr, NULL); + if (processed_value == NULL) { + Py_DECREF(values_fastseq); + Py_DECREF(result); + return -1; + } + *resultptr = processed_value; + } else { + Py_INCREF(*valueptr); + *resultptr = *valueptr; } - *resultptr = processed_value; - } else { + valueptr++; + funcptr++; + resultptr++; + } + } else { + valueptr = PySequence_Fast_ITEMS(values_fastseq); + resultptr = PySequence_Fast_ITEMS(result); + while (--num_values >= 0) { Py_INCREF(*valueptr); *resultptr = *valueptr; + valueptr++; + resultptr++; } - valueptr++; - funcptr++; - resultptr++; } Py_DECREF(values_fastseq); - self->row = result; if (!PyDict_CheckExact(keymap)) { @@ -153,7 +177,7 @@ BaseRow_init(BaseRow *self, PyObject *args, PyObject *kwds) } Py_INCREF(keymap); self->keymap = keymap; - + self->key_style = PyLong_AsLong(key_style); return 0; } @@ -202,7 +226,7 @@ BaseRow_reduce(PyObject *self) static PyObject * BaseRow_filter_on_values(BaseRow *self, PyObject *filters) { - PyObject *module, *row_class, *new_obj; + PyObject *module, *row_class, *new_obj, *key_style; if (sqlalchemy_engine_row == NULL) { module = PyImport_ImportModule("sqlalchemy.engine.row"); @@ -216,7 +240,12 @@ BaseRow_filter_on_values(BaseRow *self, PyObject *filters) // at the same time row_class = PyObject_GetAttrString(sqlalchemy_engine_row, "Row"); - new_obj = PyObject_CallFunction(row_class, "OOOO", self->parent, filters, self->keymap, self->row); + key_style = PyLong_FromLong(self->key_style); + Py_INCREF(key_style); + + new_obj = PyObject_CallFunction( + row_class, "OOOOO", self->parent, filters, self->keymap, + key_style, self->row); Py_DECREF(row_class); if (new_obj == NULL) { return NULL; @@ -356,7 +385,7 @@ BaseRow_getitem_by_object(BaseRow *self, PyObject *key, int asmapping) /* -1 can be either the actual value, or an error flag. */ return NULL; - if (!asmapping) { + if (!asmapping && self->key_style == KEY_OBJECTS_BUT_WARN) { PyObject *tmp; tmp = PyObject_CallMethod(self->parent, "_warn_for_nonint", "O", key); @@ -416,7 +445,12 @@ BaseRow_subscript(BaseRow *self, PyObject *key) static PyObject * BaseRow_subscript_mapping(BaseRow *self, PyObject *key) { - return BaseRow_subscript_impl(self, key, 1); + if (self->key_style == KEY_OBJECTS_BUT_WARN) { + return BaseRow_subscript_impl(self, key, 0); + } + else { + return BaseRow_subscript_impl(self, key, 1); + } } @@ -567,6 +601,39 @@ BaseRow_setkeymap(BaseRow *self, PyObject *value, void *closure) return 0; } +static PyObject * +BaseRow_getkeystyle(BaseRow *self, void *closure) +{ + PyObject *result; + + result = PyLong_FromLong(self->key_style); + Py_INCREF(result); + return result; +} + + +static int +BaseRow_setkeystyle(BaseRow *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString( + PyExc_TypeError, + "Cannot delete the 'key_style' attribute"); + return -1; + } + + if (!PyLong_CheckExact(value)) { + PyErr_SetString( + PyExc_TypeError, + "The 'key_style' attribute value must be an integer"); + return -1; + } + + self->key_style = PyLong_AsLong(value); + + return 0; +} + static PyGetSetDef BaseRow_getseters[] = { {"_parent", (getter)BaseRow_getparent, (setter)BaseRow_setparent, @@ -580,6 +647,10 @@ static PyGetSetDef BaseRow_getseters[] = { (getter)BaseRow_getkeymap, (setter)BaseRow_setkeymap, "Key to (obj, index) dict", NULL}, + {"_key_style", + (getter)BaseRow_getkeystyle, (setter)BaseRow_setkeystyle, + "Return the key style", + NULL}, {NULL} }; |
