2010-07-08 74 views
5

我得到了一些SQL函數Psycopg2 callproc和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, ]) 

但函數返回完全相同的輸入序列的我給出,忽略結果和OUT參數。切換到IN OUT並傳遞一些foo值沒有任何變化。當數據庫SQL函數中調用按預期工作

回答

1

嗯,我做了一點研究,我已經檢查psycopg2碼 - 當前實現此功能的只是做

select * from function_name(params) 
return params 

所以它不以任何方式修改任何東西。

1

從pyscopg2源代碼,C實現使用C-API給下面的代碼callproc採取:

/* 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, &parameters 
     )) 
    { 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, ]) 

是的,實際上,代碼生成一個「選擇」的SQL在地面執行的行動。