Skip to content

Commit 877e9e6

Browse files
committed
Calculate blob length once at creation
1 parent 4865ee9 commit 877e9e6

File tree

2 files changed

+21
-53
lines changed

2 files changed

+21
-53
lines changed

Modules/_sqlite/blob.c

Lines changed: 20 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ int pysqlite_blob_init(pysqlite_Blob *self, pysqlite_Connection* connection,
1111
self->blob = blob;
1212
self->in_weakreflist = NULL;
1313

14+
Py_BEGIN_ALLOW_THREADS
15+
self->length = sqlite3_blob_bytes(self->blob);
16+
Py_END_ALLOW_THREADS
17+
1418
if (!pysqlite_check_thread(self->connection)) {
1519
return -1;
1620
}
@@ -94,15 +98,11 @@ PyObject* pysqlite_blob_close(pysqlite_Blob *self)
9498

9599
static Py_ssize_t pysqlite_blob_length(pysqlite_Blob *self)
96100
{
97-
int blob_length;
98101
if (!pysqlite_check_blob(self)) {
99102
return -1;
100103
}
101-
Py_BEGIN_ALLOW_THREADS
102-
blob_length = sqlite3_blob_bytes(self->blob);
103-
Py_END_ALLOW_THREADS
104104

105-
return blob_length;
105+
return self->length;
106106
};
107107

108108
static PyObject* inner_read(pysqlite_Blob *self, int read_length, int offset)
@@ -140,7 +140,6 @@ static PyObject* inner_read(pysqlite_Blob *self, int read_length, int offset)
140140
PyObject* pysqlite_blob_read(pysqlite_Blob *self, PyObject *args)
141141
{
142142
int read_length = -1;
143-
int blob_length = 0;
144143
PyObject *buffer;
145144

146145
if (!PyArg_ParseTuple(args, "|i", &read_length)) {
@@ -151,20 +150,14 @@ PyObject* pysqlite_blob_read(pysqlite_Blob *self, PyObject *args)
151150
return NULL;
152151
}
153152

154-
155-
/* TODO: make this multithreaded and safe! */
156-
Py_BEGIN_ALLOW_THREADS
157-
blob_length = sqlite3_blob_bytes(self->blob);
158-
Py_END_ALLOW_THREADS
159-
160153
if (read_length < 0) {
161154
/* same as file read. */
162-
read_length = blob_length;
155+
read_length = self->length;
163156
}
164157

165158
/* making sure we don't read more then blob size */
166-
if (read_length > blob_length - self->offset) {
167-
read_length = blob_length - self->offset;
159+
if (read_length > self->length - self->offset) {
160+
read_length = self->length - self->offset;
168161
}
169162

170163
buffer = inner_read(self, read_length, self->offset);
@@ -236,7 +229,7 @@ PyObject* pysqlite_blob_write(pysqlite_Blob *self, PyObject *data)
236229

237230
PyObject* pysqlite_blob_seek(pysqlite_Blob *self, PyObject *args)
238231
{
239-
int blob_length, offset, from_what = 0;
232+
int offset, from_what = 0;
240233

241234
if (!PyArg_ParseTuple(args, "i|i", &offset, &from_what)) {
242235
return NULL;
@@ -247,10 +240,6 @@ PyObject* pysqlite_blob_seek(pysqlite_Blob *self, PyObject *args)
247240
return NULL;
248241
}
249242

250-
Py_BEGIN_ALLOW_THREADS
251-
blob_length = sqlite3_blob_bytes(self->blob);
252-
Py_END_ALLOW_THREADS
253-
254243
switch (from_what) {
255244
case 0: // relative to blob begin
256245
break;
@@ -261,17 +250,17 @@ PyObject* pysqlite_blob_seek(pysqlite_Blob *self, PyObject *args)
261250
offset = self->offset + offset;
262251
break;
263252
case 2: // relative to blob end
264-
if (offset > INT_MAX - blob_length) {
253+
if (offset > INT_MAX - self->length) {
265254
goto overflow;
266255
}
267-
offset = blob_length + offset;
256+
offset = self->length + offset;
268257
break;
269258
default:
270259
return PyErr_Format(PyExc_ValueError,
271260
"from_what should be 0, 1 or 2");
272261
}
273262

274-
if (offset < 0 || offset > blob_length) {
263+
if (offset < 0 || offset > self->length) {
275264
return PyErr_Format(PyExc_ValueError, "offset out of blob range");
276265
}
277266

@@ -340,17 +329,11 @@ static PyObject* pysqlite_blob_repeat(pysqlite_Blob *self, PyObject *args)
340329

341330
static PyObject* pysqlite_blob_item(pysqlite_Blob *self, Py_ssize_t i)
342331
{
343-
int blob_length = 0;
344-
345332
if (!pysqlite_check_blob(self)) {
346333
return NULL;
347334
}
348335

349-
Py_BEGIN_ALLOW_THREADS
350-
blob_length = sqlite3_blob_bytes(self->blob);
351-
Py_END_ALLOW_THREADS
352-
353-
if (i < 0 || i >= blob_length) {
336+
if (i < 0 || i >= self->length) {
354337
PyErr_SetString(PyExc_IndexError, "Blob index out of range");
355338
return NULL;
356339
}
@@ -360,18 +343,13 @@ static PyObject* pysqlite_blob_item(pysqlite_Blob *self, Py_ssize_t i)
360343

361344
static int pysqlite_blob_ass_item(pysqlite_Blob *self, Py_ssize_t i, PyObject *v)
362345
{
363-
int blob_length = 0;
364346
const char *buf;
365347

366348
if (!pysqlite_check_blob(self)) {
367349
return -1;
368350
}
369351

370-
Py_BEGIN_ALLOW_THREADS
371-
blob_length = sqlite3_blob_bytes(self->blob);
372-
Py_END_ALLOW_THREADS
373-
374-
if (i < 0 || i >= blob_length) {
352+
if (i < 0 || i >= self->length) {
375353
PyErr_SetString(PyExc_IndexError, "Blob index out of range");
376354
return -1;
377355
}
@@ -393,23 +371,17 @@ static int pysqlite_blob_ass_item(pysqlite_Blob *self, Py_ssize_t i, PyObject *v
393371

394372
static PyObject * pysqlite_blob_subscript(pysqlite_Blob *self, PyObject *item)
395373
{
396-
int blob_length = 0;
397-
398374
if (!pysqlite_check_blob(self)) {
399375
return NULL;
400376
}
401377

402-
Py_BEGIN_ALLOW_THREADS
403-
blob_length = sqlite3_blob_bytes(self->blob);
404-
Py_END_ALLOW_THREADS
405-
406378
if (PyIndex_Check(item)) {
407379
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
408380
if (i == -1 && PyErr_Occurred())
409381
return NULL;
410382
if (i < 0)
411-
i += blob_length;
412-
if (i < 0 || i >= blob_length) {
383+
i += self->length;
384+
if (i < 0 || i >= self->length) {
413385
PyErr_SetString(PyExc_IndexError,
414386
"Blob index out of range");
415387
return NULL;
@@ -420,7 +392,7 @@ static PyObject * pysqlite_blob_subscript(pysqlite_Blob *self, PyObject *item)
420392
else if (PySlice_Check(item)) {
421393
Py_ssize_t start, stop, step, slicelen;
422394

423-
if (PySlice_GetIndicesEx(item, blob_length,
395+
if (PySlice_GetIndicesEx(item, self->length,
424396
&start, &stop, &step, &slicelen) < 0) {
425397
return NULL;
426398
}
@@ -484,26 +456,21 @@ static PyObject * pysqlite_blob_subscript(pysqlite_Blob *self, PyObject *item)
484456

485457
static int pysqlite_blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyObject *value)
486458
{
487-
int blob_length = 0;
488459
int rc;
489460

490461
if (!pysqlite_check_blob(self)) {
491462
return -1;
492463
}
493464

494-
Py_BEGIN_ALLOW_THREADS
495-
blob_length = sqlite3_blob_bytes(self->blob);
496-
Py_END_ALLOW_THREADS
497-
498465
if (PyIndex_Check(item)) {
499466
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
500467
const char *buf;
501468

502469
if (i == -1 && PyErr_Occurred())
503470
return -1;
504471
if (i < 0)
505-
i += blob_length;
506-
if (i < 0 || i >= blob_length) {
472+
i += self->length;
473+
if (i < 0 || i >= self->length) {
507474
PyErr_SetString(PyExc_IndexError,
508475
"Blob index out of range");
509476
return -1;
@@ -527,7 +494,7 @@ static int pysqlite_blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyOb
527494
Py_buffer vbuf;
528495

529496
if (PySlice_GetIndicesEx(item,
530-
blob_length, &start, &stop,
497+
self->length, &start, &stop,
531498
&step, &slicelen) < 0) {
532499
return -1;
533500
}

Modules/_sqlite/blob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ typedef struct
1010
pysqlite_Connection* connection;
1111
sqlite3_blob *blob;
1212
int offset;
13+
int length;
1314

1415
PyObject* in_weakreflist; /* List of weak references */
1516
} pysqlite_Blob;

0 commit comments

Comments
 (0)