Skip to content

Commit 479a1f6

Browse files
committed
Fix memory leaks in C extension; add test functions
1 parent 34a685a commit 479a1f6

File tree

2 files changed

+93
-9
lines changed

2 files changed

+93
-9
lines changed

accel.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -363,18 +363,15 @@ static PyObject *apply_transformer(PyObject *transformer, PyObject *value) {
363363
}
364364

365365
if (transformer == NULL || transformer == Py_None) {
366-
// Increment refcount fo Py_None since we are returning it
367-
if (value == Py_None) {
368-
Py_INCREF(value);
369-
}
366+
// No transformation needed, return value as-is
367+
// We steal the reference from the caller
370368
return value;
371369
}
372370

373371
PyObject *out = PyObject_CallFunction(transformer, "O", value);
374-
// Don't decref Py_None since we assume it was passed in literally and not from a new reference
375-
if (value != NULL && value != Py_None) {
376-
Py_DECREF(value);
377-
}
372+
// Always decref value since we're stealing the reference from the caller
373+
// This includes Py_None when it's passed as a new reference (e.g., from PyIter_Next)
374+
Py_DECREF(value);
378375

379376
return out;
380377
}
@@ -4306,7 +4303,10 @@ static PyObject *load_rowdat_1(PyObject *self, PyObject *args, PyObject *kwargs)
43064303
if (!py_row) goto error;
43074304

43084305
row_id = *(int64_t*)data; data += 8;
4309-
CHECKRC(PyList_Append(py_out_row_ids, PyLong_FromLongLong(row_id)));
4306+
PyObject *py_row_id = PyLong_FromLongLong(row_id);
4307+
if (!py_row_id) goto error;
4308+
CHECKRC(PyList_Append(py_out_row_ids, py_row_id));
4309+
Py_DECREF(py_row_id);
43104310

43114311
for (unsigned long long i = 0; i < colspec_l; i++) {
43124312
is_null = data[0] == '\x01'; data += 1;

singlestoredb/tests/ext_funcs/__init__.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,90 @@
3232
from singlestoredb.functions.typing import pyarrow as pat
3333

3434

35+
@udf
36+
def add(x: int, y: int) -> int:
37+
"""
38+
Add two integers.
39+
40+
Parameters
41+
----------
42+
x : int
43+
First integer.
44+
y : int
45+
Second integer.
46+
47+
Returns
48+
-------
49+
int
50+
Sum of x and y.
51+
52+
"""
53+
return x + y
54+
55+
56+
@udf
57+
def add_vec(x: npt.Int64Array, y: npt.Int64Array) -> npt.Int64Array:
58+
"""
59+
Add two numpy arrays of int64.
60+
61+
Parameters
62+
----------
63+
x : numpy.ndarray
64+
First array.
65+
y : numpy.ndarray
66+
Second array.
67+
68+
Returns
69+
-------
70+
numpy.ndarray
71+
Elementwise sum of x and y.
72+
73+
"""
74+
return x + y
75+
76+
77+
@udf
78+
async def async_add(x: int, y: int) -> int:
79+
"""
80+
Asynchronously add two integers.
81+
82+
Parameters
83+
----------
84+
x : int
85+
First integer.
86+
y : int
87+
Second integer.
88+
89+
Returns
90+
-------
91+
int
92+
Sum of x and y.
93+
94+
"""
95+
return x + y
96+
97+
98+
@udf
99+
async def async_add_vec_vec(x: npt.Int64Array, y: npt.Int64Array) -> npt.Int64Array:
100+
"""
101+
Asynchronously add two numpy arrays of int64.
102+
103+
Parameters
104+
----------
105+
x : numpy.ndarray
106+
First array.
107+
y : numpy.ndarray
108+
Second array.
109+
110+
Returns
111+
-------
112+
numpy.ndarray
113+
Elementwise sum of x and y.
114+
115+
"""
116+
return x + y
117+
118+
35119
@udf
36120
def doc_test(x: int, y: float) -> int:
37121
"""

0 commit comments

Comments
 (0)