2010-07-08 13 views
5

ho avuto qualche funzione SQLpsycopg2 callproc e SQL parametri

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$ 

e da psycopg2 (suo interno Django se quello che conta) faccio

c = connection.cursor() 
c.callproc('tools.update_company', [1, ]) 

ma funzione restituisce esattamente la stessa sequenza di ingresso come ho dato, ignorando i risultati e il parametro OUT. Passare a IN OUT e passare qualche valore foo non cambia nulla. Quando viene chiamato all'interno della funzione database SQL funziona come previsto

risposta

1

Beh ho fatto qualche ricerca e ho controllato il codice psycopg2 - attuale implementazione di questa funzione è sufficiente fare

select * from function_name(params) 
return params 

quindi non modifica nulla in alcun modo.

1

preso dal codice sorgente pyscopg2, l'implementazione C di callproc utilizzando il C-API dare il seguente codice:

/* 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; 
} 

si può notare che non v'è una modifica locale sugli argomenti passati al "callproc" ma il risultato viene restituito:

c = connection.cursor() 
res = c.callproc('tools.update_company', [1, ]) 

e sì, in realtà il codice di produrre uno SQL "SELECT" sul terreno per perfom l'azione.