Psycopg2 callproc 和 SQL 参数
我有一个SQL函数
CREATE OR REPLACE FUNCTION tools.update_company(IN company_id integer, OUT value integer)
RETURNS integer AS
$BODY$
BEGIN
select * into value from function_making_int(company_id)
END;$BODY$
然后在Psycopg2(它在Django里面,如果这有关系的话)我做了
c = connection.cursor()
c.callproc('tools.update_company', [1, ])
但是这个函数返回的结果和我输入的一模一样,完全不管结果和输出参数。把参数改成IN OUT并传入一些值也没有任何变化。当在数据库内部调用这个SQL函数时,它的表现是正常的。
2 个回答
1
这段内容来自pyscopg2的源代码,pyscopg2是一个用于Python和PostgreSQL数据库交互的库。这里提到的“callproc”是一个用C语言实现的函数,它通过C语言的接口来执行。
/* callproc method - execute a stored procedure */
#define psyco_curs_callproc_doc \
"callproc(procname, parameters=None) -- Execute stored procedure."
static PyObject *
psyco_curs_callproc(cursorObject *self, PyObject *args)
{
const char *procname = NULL;
char *sql = NULL;
Py_ssize_t procname_len, i, nparameters = 0, sl = 0;
PyObject *parameters = Py_None;
PyObject *operation = NULL;
PyObject *res = NULL;
if (!PyArg_ParseTuple(args, "s#|O",
&procname, &procname_len, ¶meters
))
{ goto exit; }
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, callproc);
EXC_IF_TPC_PREPARED(self->conn, callproc);
if (self->name != NULL) {
psyco_set_error(ProgrammingError, self,
"can't call .callproc() on named cursors");
goto exit;
}
if (parameters != Py_None) {
if (-1 == (nparameters = PyObject_Length(parameters))) { goto exit; }
}
/* allocate some memory, build the SQL and create a PyString from it */
sl = procname_len + 17 + nparameters*3 - (nparameters ? 1 : 0);
sql = (char*)PyMem_Malloc(sl);
if (sql == NULL) {
PyErr_NoMemory();
goto exit;
}
sprintf(sql, "SELECT * FROM %s(", procname);
for(i=0; i<nparameters; i++) {
strcat(sql, "%s,");
}
sql[sl-2] = ')';
sql[sl-1] = '\0';
if (!(operation = Bytes_FromString(sql))) { goto exit; }
if (0 <= _psyco_curs_execute(self, operation, parameters,
self->conn->async, 0)) {
Py_INCREF(parameters);
res = parameters;
}
exit:
Py_XDECREF(operation);
PyMem_Free((void*)sql);
return res;
}
你会注意到,传给“callproc”的参数没有被本地修改,但结果还是被返回了。
c = connection.cursor()
res = c.callproc('tools.update_company', [1, ])
没错,实际上这段代码在后台执行了一个“SELECT” SQL语句来完成这个操作。
1
我做了一些小调查,查看了psycopg2的代码——这个函数的当前实现其实就是这样做的:
select * from function_name(params)
return params
所以它并没有以任何方式修改任何东西。