Changeset 978 for trunk/pgmodule.c


Ignore:
Timestamp:
Apr 21, 2019, 3:07:48 PM (4 months ago)
Author:
cito
Message:

Make classic query work as iterator

Mostly following Justin's proposal on the mailing list.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/pgmodule.c

    r957 r978  
    9090
    9191static PyObject *decimal = NULL, /* decimal type */
    92                                 *namedresult = NULL, /* function for getting named results */
     92                                *dictiter = NULL, /* function for getting named results */
     93                                *namediter = NULL, /* function for getting named results */
    9394                                *jsondecode = NULL; /* function for decoding json strings */
    9495static const char *date_format = NULL; /* date format that is always assumed */
     
    157158        int                     result_type;    /* result type (DDL/DML/DQL) */
    158159        long            arraysize;              /* array size for fetch method */
    159         int                     current_row;    /* current selected row */
     160        int                     current_row;    /* currently selected row */
    160161        int                     max_row;                /* number of rows in the result */
    161162        int                     num_fields;             /* number of fields in each row */
     
    177178        PGresult   *result;                     /* result content */
    178179        int                     encoding;               /* client encoding */
     180        int                     current_row;    /* currently selected row */
     181        int                     max_row;                /* number of rows in the result */
     182        int                     num_fields;             /* number of fields in each row */
     183        int                *col_types;          /* PyGreSQL column types */
    179184}       queryObject;
    180185#define is_queryObject(v) (PyType(v) == &queryType)
     
    932937                        char       *estr;
    933938                        Py_ssize_t      esize;
    934                         int quoted = 0, escaped =0;
     939                        int quoted = 0, escaped = 0;
    935940
    936941                        estr = s;
     
    16541659largeNew(connObject *pgcnx, Oid oid)
    16551660{
    1656         largeObject *npglo;
    1657 
    1658         if (!(npglo = PyObject_NEW(largeObject, &largeType)))
     1661        largeObject *large_obj;
     1662
     1663        if (!(large_obj = PyObject_NEW(largeObject, &largeType)))
    16591664                return NULL;
    16601665
    16611666        Py_XINCREF(pgcnx);
    1662         npglo->pgcnx = pgcnx;
    1663         npglo->lo_fd = -1;
    1664         npglo->lo_oid = oid;
    1665 
    1666         return npglo;
     1667        large_obj->pgcnx = pgcnx;
     1668        large_obj->lo_fd = -1;
     1669        large_obj->lo_oid = oid;
     1670
     1671        return large_obj;
    16671672}
    16681673
     
    21212126connSource(connObject *self, PyObject *noargs)
    21222127{
    2123         sourceObject *npgobj;
     2128        sourceObject *source_obj;
    21242129
    21252130        /* checks validity */
     
    21282133
    21292134        /* allocates new query object */
    2130         if (!(npgobj = PyObject_NEW(sourceObject, &sourceType)))
     2135        if (!(source_obj = PyObject_NEW(sourceObject, &sourceType)))
    21312136                return NULL;
    21322137
    21332138        /* initializes internal parameters */
    21342139        Py_XINCREF(self);
    2135         npgobj->pgcnx = self;
    2136         npgobj->result = NULL;
    2137         npgobj->valid = 1;
    2138         npgobj->arraysize = PG_ARRAYSIZE;
    2139 
    2140         return (PyObject *) npgobj;
     2140        source_obj->pgcnx = self;
     2141        source_obj->result = NULL;
     2142        source_obj->valid = 1;
     2143        source_obj->arraysize = PG_ARRAYSIZE;
     2144
     2145        return (PyObject *) source_obj;
    21412146}
    21422147
     
    21472152_connQuery(connObject *self, PyObject *args, int prepared)
    21482153{
    2149         PyObject        *query_obj;
     2154        PyObject        *query_str_obj;
    21502155        PyObject        *param_obj = NULL;
    21512156        char            *query;
    21522157        PGresult        *result;
    2153         queryObject *npgobj;
     2158        queryObject *query_obj;
    21542159        int                     encoding,
    21552160                                status,
     
    21632168
    21642169        /* get query args */
    2165         if (!PyArg_ParseTuple(args, "O|O", &query_obj, &param_obj))
     2170        if (!PyArg_ParseTuple(args, "O|O", &query_str_obj, &param_obj))
    21662171        {
    21672172                return NULL;
     
    21702175        encoding = PQclientEncoding(self->cnx);
    21712176
    2172         if (PyBytes_Check(query_obj))
    2173         {
    2174                 query = PyBytes_AsString(query_obj);
    2175                 query_obj = NULL;
    2176         }
    2177         else if (PyUnicode_Check(query_obj))
    2178         {
    2179                 query_obj = get_encoded_string(query_obj, encoding);
    2180                 if (!query_obj) return NULL; /* pass the UnicodeEncodeError */
    2181                 query = PyBytes_AsString(query_obj);
     2177        if (PyBytes_Check(query_str_obj))
     2178        {
     2179                query = PyBytes_AsString(query_str_obj);
     2180                query_str_obj = NULL;
     2181        }
     2182        else if (PyUnicode_Check(query_str_obj))
     2183        {
     2184                query_str_obj = get_encoded_string(query_str_obj, encoding);
     2185                if (!query_str_obj) return NULL; /* pass the UnicodeEncodeError */
     2186                query = PyBytes_AsString(query_str_obj);
    21822187        }
    21832188        else
     
    21982203                if (!param_obj)
    21992204                {
    2200                         Py_XDECREF(query_obj);
     2205                        Py_XDECREF(query_str_obj);
    22012206                        return NULL;
    22022207                }
     
    22302235                {
    22312236                        PyMem_Free((void *)parms); PyMem_Free(str);
    2232                         Py_XDECREF(query_obj); Py_XDECREF(param_obj);
     2237                        Py_XDECREF(query_str_obj); Py_XDECREF(param_obj);
    22332238                        return PyErr_NoMemory();
    22342239                }
     
    22572262                                        while (s != str) { s--; Py_DECREF(*s); }
    22582263                                        PyMem_Free(str);
    2259                                         Py_XDECREF(query_obj);
     2264                                        Py_XDECREF(query_str_obj);
    22602265                                        Py_XDECREF(param_obj);
    22612266                                        /* pass the UnicodeEncodeError */
     
    22732278                                        while (s != str) { s--; Py_DECREF(*s); }
    22742279                                        PyMem_Free(str);
    2275                                         Py_XDECREF(query_obj);
     2280                                        Py_XDECREF(query_str_obj);
    22762281                                        Py_XDECREF(param_obj);
    22772282                                        PyErr_SetString(PyExc_TypeError,
     
    23072312
    23082313        /* we don't need the query and its params any more */
    2309         Py_XDECREF(query_obj);
     2314        Py_XDECREF(query_str_obj);
    23102315        Py_XDECREF(param_obj);
    23112316
     
    23692374        }
    23702375
    2371         if (!(npgobj = PyObject_NEW(queryObject, &queryType)))
     2376        if (!(query_obj = PyObject_NEW(queryObject, &queryType)))
    23722377                return PyErr_NoMemory();
    23732378
    23742379        /* stores result and returns object */
    23752380        Py_XINCREF(self);
    2376         npgobj->pgcnx = self;
    2377         npgobj->result = result;
    2378         npgobj->encoding = encoding;
    2379         return (PyObject *) npgobj;
     2381        query_obj->pgcnx = self;
     2382        query_obj->result = result;
     2383        query_obj->encoding = encoding;
     2384        query_obj->current_row = 0;
     2385        query_obj->max_row = PQntuples(result);
     2386        query_obj->num_fields = PQnfields(result);
     2387        query_obj->col_types = get_col_types(result, query_obj->num_fields);
     2388        if (!query_obj->col_types) {
     2389                Py_DECREF(query_obj);
     2390                Py_DECREF(self);
     2391                return NULL;
     2392        }
     2393
     2394        return (PyObject *) query_obj;
    23802395}
    23812396
     
    24822497        if (result && PQresultStatus(result) == PGRES_COMMAND_OK)
    24832498        {
    2484                 queryObject *npgobj = PyObject_NEW(queryObject, &queryType);
    2485                 if (!npgobj)
     2499                queryObject *query_obj = PyObject_NEW(queryObject, &queryType);
     2500                if (!query_obj)
    24862501                        return PyErr_NoMemory();
    24872502                Py_XINCREF(self);
    2488                 npgobj->pgcnx = self;
    2489                 npgobj->result = result;
    2490                 return (PyObject *) npgobj;
     2503                query_obj->pgcnx = self;
     2504                query_obj->result = result;
     2505                query_obj->encoding = PQclientEncoding(self->cnx);
     2506                query_obj->current_row = 0;
     2507                query_obj->max_row = PQntuples(result);
     2508                query_obj->num_fields = PQnfields(result);
     2509                query_obj->col_types = get_col_types(result, query_obj->num_fields);
     2510                return (PyObject *) query_obj;
    24912511        }
    24922512        set_error(ProgrammingError, "Cannot describe prepared statement",
     
    45584578        int                     pgport;
    45594579        char            port_buffer[20];
    4560         connObject *npgobj;
     4580        connObject *conn_obj;
    45614581
    45624582        pghost = pgopt = pgdbname = pguser = pgpasswd = NULL;
     
    45944614#endif /* DEFAULT_VARS */
    45954615
    4596         if (!(npgobj = PyObject_NEW(connObject, &connType)))
     4616        if (!(conn_obj = PyObject_NEW(connObject, &connType)))
    45974617        {
    45984618                set_error_msg(InternalError, "Can't create new connection object");
     
    46004620        }
    46014621
    4602         npgobj->valid = 1;
    4603         npgobj->cnx = NULL;
    4604         npgobj->date_format = date_format;
    4605         npgobj->cast_hook = NULL;
    4606         npgobj->notice_receiver = NULL;
     4622        conn_obj->valid = 1;
     4623        conn_obj->cnx = NULL;
     4624        conn_obj->date_format = date_format;
     4625        conn_obj->cast_hook = NULL;
     4626        conn_obj->notice_receiver = NULL;
    46074627
    46084628        if (pgport != -1)
     
    46134633
    46144634        Py_BEGIN_ALLOW_THREADS
    4615         npgobj->cnx = PQsetdbLogin(pghost, pgport == -1 ? NULL : port_buffer,
     4635        conn_obj->cnx = PQsetdbLogin(pghost, pgport == -1 ? NULL : port_buffer,
    46164636                pgopt, NULL, pgdbname, pguser, pgpasswd);
    46174637        Py_END_ALLOW_THREADS
    46184638
    4619         if (PQstatus(npgobj->cnx) == CONNECTION_BAD)
    4620         {
    4621                 set_error(InternalError, "Cannot connect", npgobj->cnx, NULL);
    4622                 Py_XDECREF(npgobj);
    4623                 return NULL;
    4624         }
    4625 
    4626         return (PyObject *) npgobj;
     4639        if (PQstatus(conn_obj->cnx) == CONNECTION_BAD)
     4640        {
     4641                set_error(InternalError, "Cannot connect", conn_obj->cnx, NULL);
     4642                Py_XDECREF(conn_obj);
     4643                return NULL;
     4644        }
     4645
     4646        return (PyObject *) conn_obj;
    46274647}
    46284648
     
    46314651{
    46324652        Py_XDECREF(self->pgcnx);
     4653        if (self->col_types)
     4654                PyMem_Free(self->col_types);
    46334655        if (self->result)
    46344656                PQclear(self->result);
     
    46384660
    46394661/* get number of rows */
    4640 static char queryNTuples__doc__[] =
     4662static char queryNtuples__doc__[] =
    46414663"ntuples() -- return number of tuples returned by query";
    46424664
    46434665static PyObject *
    4644 queryNTuples(queryObject *self, PyObject *noargs)
    4645 {
    4646         return PyInt_FromLong((long) PQntuples(self->result));
     4666queryNtuples(queryObject *self, PyObject *noargs)
     4667{
     4668        return PyInt_FromLong(self->max_row);
    46474669}
    46484670
    46494671/* list fields names from query result */
    4650 static char queryListFields__doc__[] =
     4672static char queryListfields__doc__[] =
    46514673"listfields() -- List field names from result";
    46524674
    46534675static PyObject *
    4654 queryListFields(queryObject *self, PyObject *noargs)
    4655 {
    4656         int                     i,
    4657                                 n;
     4676queryListfields(queryObject *self, PyObject *noargs)
     4677{
     4678        int                     i;
    46584679        char       *name;
    46594680        PyObject   *fieldstuple,
     
    46614682
    46624683        /* builds tuple */
    4663         n = PQnfields(self->result);
    4664         fieldstuple = PyTuple_New(n);
    4665 
    4666         for (i = 0; i < n; ++i)
    4667         {
    4668                 name = PQfname(self->result, i);
    4669                 str = PyStr_FromString(name);
    4670                 PyTuple_SET_ITEM(fieldstuple, i, str);
    4671         }
    4672 
     4684        fieldstuple = PyTuple_New(self->num_fields);
     4685        if (fieldstuple) {
     4686                for (i = 0; i < self->num_fields; ++i)
     4687                {
     4688                        name = PQfname(self->result, i);
     4689                        str = PyStr_FromString(name);
     4690                        PyTuple_SET_ITEM(fieldstuple, i, str);
     4691                }
     4692        }
    46734693        return fieldstuple;
    46744694}
    46754695
    46764696/* get field name from last result */
    4677 static char queryFieldName__doc__[] =
     4697static char queryFieldname__doc__[] =
    46784698"fieldname(num) -- return name of field from result from its position";
    46794699
    46804700static PyObject *
    4681 queryFieldName(queryObject *self, PyObject *args)
     4701queryFieldname(queryObject *self, PyObject *args)
    46824702{
    46834703        int             i;
     
    46934713
    46944714        /* checks number validity */
    4695         if (i >= PQnfields(self->result))
     4715        if (i >= self->num_fields)
    46964716        {
    46974717                PyErr_SetString(PyExc_ValueError, "Invalid field number");
     
    47054725
    47064726/* gets fields number from name in last result */
    4707 static char queryFieldNumber__doc__[] =
     4727static char queryFieldnum__doc__[] =
    47084728"fieldnum(name) -- return position in query for field from its name";
    47094729
    47104730static PyObject *
    4711 queryFieldNumber(queryObject *self, PyObject *args)
     4731queryFieldnum(queryObject *self, PyObject *args)
    47124732{
    47134733        int             num;
     
    47324752}
    47334753
    4734 /* retrieves last result */
    4735 static char queryGetResult__doc__[] =
     4754/* The __iter__() method of the queryObject.
     4755   This returns the default iterator yielding rows as tuples. */
     4756static PyObject* queryGetIter(queryObject *self)
     4757{
     4758        self->current_row = 0;
     4759        Py_INCREF(self);
     4760        return (PyObject*)self;
     4761}
     4762
     4763/* Return the value in the given column of the current row. */
     4764static PyObject *
     4765getValueInColumn(queryObject *self, int column)
     4766{
     4767        if (PQgetisnull(self->result, self->current_row, column))
     4768        {
     4769                Py_INCREF(Py_None);
     4770                return Py_None;
     4771        }
     4772
     4773        /* get the string representation of the value */
     4774        /* note: this is always null-terminated text format */
     4775        char   *s = PQgetvalue(self->result, self->current_row, column);
     4776        /* get the PyGreSQL type of the column */
     4777        int             type = self->col_types[column];
     4778        /* cast the string representation into a Python object */
     4779        if (type & PYGRES_ARRAY)
     4780                return cast_array(s,
     4781                        PQgetlength(self->result, self->current_row, column),
     4782                        self->encoding, type, NULL, 0);
     4783        if (type == PYGRES_BYTEA)
     4784                return cast_bytea_text(s);
     4785        if (type == PYGRES_OTHER)
     4786                return cast_other(s,
     4787                        PQgetlength(self->result, self->current_row, column),
     4788                        self->encoding,
     4789                        PQftype(self->result, column), self->pgcnx->cast_hook);
     4790        if (type & PYGRES_TEXT)
     4791                return cast_sized_text(s,
     4792                        PQgetlength(self->result, self->current_row, column),
     4793                        self->encoding, type);
     4794        return cast_unsized_simple(s, type);
     4795}
     4796
     4797/* Return the current row as a tuple. */
     4798static PyObject *
     4799queryGetRowAsTuple(queryObject *self)
     4800{
     4801        PyObject   *row_tuple = NULL;
     4802        int                     j;
     4803
     4804        if (!(row_tuple = PyTuple_New(self->num_fields))) return NULL;
     4805
     4806        for (j = 0; j < self->num_fields; ++j)
     4807        {
     4808                PyObject *val = getValueInColumn(self, j);
     4809                if (!val)
     4810                {
     4811                        Py_DECREF(row_tuple); return NULL;
     4812                }
     4813                PyTuple_SET_ITEM(row_tuple, j, val);
     4814        }
     4815
     4816        return row_tuple;
     4817}
     4818
     4819/* The __next__() method of the queryObject.
     4820   Returns the current current row as a tuple and moves to the next one. */
     4821static PyObject *
     4822queryNext(queryObject *self, PyObject *noargs)
     4823{
     4824        PyObject   *row_tuple = NULL;
     4825
     4826        if (self->current_row >= self->max_row) {
     4827                PyErr_SetNone(PyExc_StopIteration);
     4828                return NULL;
     4829        }
     4830
     4831        row_tuple = queryGetRowAsTuple(self);
     4832        if (row_tuple) ++self->current_row;
     4833    return row_tuple;
     4834}
     4835
     4836/* Retrieves the last query result as a list of tuples. */
     4837static char queryGetresult__doc__[] =
    47364838"getresult() -- Get the result of a query\n\n"
    47374839"The result is returned as a list of rows, each one a tuple of fields\n"
     
    47394841
    47404842static PyObject *
    4741 queryGetResult(queryObject *self, PyObject *noargs)
    4742 {
    4743         PyObject   *reslist;
    4744         int                     i, m, n, *col_types;
    4745         int                     encoding = self->encoding;
    4746 
    4747         /* stores result in tuple */
    4748         m = PQntuples(self->result);
    4749         n = PQnfields(self->result);
    4750         if (!(reslist = PyList_New(m))) return NULL;
    4751 
    4752         if (!(col_types = get_col_types(self->result, n))) return NULL;
    4753 
    4754         for (i = 0; i < m; ++i)
    4755         {
    4756                 PyObject   *rowtuple;
    4757                 int                     j;
    4758 
    4759                 if (!(rowtuple = PyTuple_New(n)))
     4843queryGetresult(queryObject *self, PyObject *noargs)
     4844{
     4845        PyObject   *result_list;
     4846        int                     i;
     4847
     4848        if (!(result_list = PyList_New(self->max_row))) return NULL;
     4849
     4850        for (i = self->current_row = 0; i < self->max_row; ++i)
     4851        {
     4852                PyObject   *row_tuple = queryNext(self, noargs);
     4853                if (!row_tuple)
    47604854                {
    4761                         Py_DECREF(reslist);
    4762                         reslist = NULL;
    4763                         goto exit;
     4855                        Py_DECREF(result_list); return NULL;
    47644856                }
    4765 
    4766                 for (j = 0; j < n; ++j)
     4857                PyList_SET_ITEM(result_list, i, row_tuple);
     4858        }
     4859
     4860        return result_list;
     4861}
     4862
     4863/* Return the current row as a dict. */
     4864static PyObject *
     4865queryGetRowAsDict(queryObject *self)
     4866{
     4867        PyObject   *row_dict = NULL;
     4868        int                     j;
     4869
     4870        if (!(row_dict = PyDict_New())) return NULL;
     4871
     4872        for (j = 0; j < self->num_fields; ++j)
     4873        {
     4874                PyObject *val = getValueInColumn(self, j);
     4875                if (!val)
    47674876                {
    4768                         PyObject * val;
    4769 
    4770                         if (PQgetisnull(self->result, i, j))
    4771                         {
    4772                                 Py_INCREF(Py_None);
    4773                                 val = Py_None;
    4774                         }
    4775                         else /* not null */
    4776                         {
    4777                                 /* get the string representation of the value */
    4778                                 /* note: this is always null-terminated text format */
    4779                                 char   *s = PQgetvalue(self->result, i, j);
    4780                                 /* get the PyGreSQL type of the column */
    4781                                 int             type = col_types[j];
    4782 
    4783                                 if (type & PYGRES_ARRAY)
    4784                                         val = cast_array(s, PQgetlength(self->result, i, j),
    4785                                                 encoding, type, NULL, 0);
    4786                                 else if (type == PYGRES_BYTEA)
    4787                                         val = cast_bytea_text(s);
    4788                                 else if (type == PYGRES_OTHER)
    4789                                         val = cast_other(s,
    4790                                                 PQgetlength(self->result, i, j), encoding,
    4791                                                 PQftype(self->result, j), self->pgcnx->cast_hook);
    4792                                 else if (type & PYGRES_TEXT)
    4793                                         val = cast_sized_text(s, PQgetlength(self->result, i, j),
    4794                                                 encoding, type);
    4795                                 else
    4796                                         val = cast_unsized_simple(s, type);
    4797                         }
    4798 
    4799                         if (!val)
    4800                         {
    4801                                 Py_DECREF(reslist);
    4802                                 Py_DECREF(rowtuple);
    4803                                 reslist = NULL;
    4804                                 goto exit;
    4805                         }
    4806 
    4807                         PyTuple_SET_ITEM(rowtuple, j, val);
     4877                        Py_DECREF(row_dict); return NULL;
    48084878                }
    4809 
    4810                 PyList_SET_ITEM(reslist, i, rowtuple);
    4811         }
    4812 
    4813 exit:
    4814         PyMem_Free(col_types);
    4815 
    4816         /* returns list */
    4817         return reslist;
    4818 }
    4819 
    4820 /* retrieves last result as a list of dictionaries*/
    4821 static char queryDictResult__doc__[] =
     4879                PyDict_SetItemString(row_dict, PQfname(self->result, j), val);
     4880                Py_DECREF(val);
     4881        }
     4882
     4883        return row_dict;
     4884}
     4885
     4886/* Return the current current row as a dict and move to the next one. */
     4887static PyObject *
     4888queryNextDict(queryObject *self, PyObject *noargs)
     4889{
     4890        PyObject   *row_dict = NULL;
     4891
     4892        if (self->current_row >= self->max_row) {
     4893                PyErr_SetNone(PyExc_StopIteration);
     4894                return NULL;
     4895        }
     4896
     4897        row_dict = queryGetRowAsDict(self);
     4898        if (row_dict) ++self->current_row;
     4899    return row_dict;
     4900}
     4901
     4902/* Retrieve the last query result as a list of dictionaries. */
     4903static char queryDictresult__doc__[] =
    48224904"dictresult() -- Get the result of a query\n\n"
    48234905"The result is returned as a list of rows, each one a dictionary with\n"
    4824 "the field names used as the labels.\n";
    4825 
    4826 static PyObject *
    4827 queryDictResult(queryObject *self, PyObject *noargs)
    4828 {
    4829         PyObject   *reslist;
    4830         int                     i,
    4831                                 m,
    4832                                 n,
    4833                            *col_types;
    4834         int                     encoding = self->encoding;
    4835 
    4836         /* stores result in list */
    4837         m = PQntuples(self->result);
    4838         n = PQnfields(self->result);
    4839         if (!(reslist = PyList_New(m))) return NULL;
    4840 
    4841         if (!(col_types = get_col_types(self->result, n))) return NULL;
    4842 
    4843         for (i = 0; i < m; ++i)
    4844         {
    4845                 PyObject   *dict;
    4846                 int                     j;
    4847 
    4848                 if (!(dict = PyDict_New()))
     4906"the field names used as the keys.\n";
     4907
     4908static PyObject *
     4909queryDictresult(queryObject *self, PyObject *noargs)
     4910{
     4911        PyObject   *result_list;
     4912        int                     i;
     4913
     4914        if (!(result_list = PyList_New(self->max_row))) return NULL;
     4915
     4916        for (i = self->current_row = 0; i < self->max_row; ++i)
     4917        {
     4918                PyObject   *row_dict = queryNextDict(self, noargs);
     4919                if (!row_dict)
    48494920                {
    4850                         Py_DECREF(reslist);
    4851                         reslist = NULL;
    4852                         goto exit;
     4921                        Py_DECREF(result_list); return NULL;
    48534922                }
    4854 
    4855                 for (j = 0; j < n; ++j)
    4856                 {
    4857                         PyObject * val;
    4858 
    4859                         if (PQgetisnull(self->result, i, j))
    4860                         {
    4861                                 Py_INCREF(Py_None);
    4862                                 val = Py_None;
    4863                         }
    4864                         else /* not null */
    4865                         {
    4866                                 /* get the string representation of the value */
    4867                                 /* note: this is always null-terminated text format */
    4868                                 char   *s = PQgetvalue(self->result, i, j);
    4869                                 /* get the PyGreSQL type of the column */
    4870                                 int             type = col_types[j];
    4871 
    4872                                 if (type & PYGRES_ARRAY)
    4873                                         val = cast_array(s, PQgetlength(self->result, i, j),
    4874                                                 encoding, type, NULL, 0);
    4875                                 else if (type == PYGRES_BYTEA)
    4876                                         val = cast_bytea_text(s);
    4877                                 else if (type == PYGRES_OTHER)
    4878                                         val = cast_other(s,
    4879                                                 PQgetlength(self->result, i, j), encoding,
    4880                                                 PQftype(self->result, j), self->pgcnx->cast_hook);
    4881                                 else if (type & PYGRES_TEXT)
    4882                                         val = cast_sized_text(s, PQgetlength(self->result, i, j),
    4883                                                 encoding, type);
    4884                                 else
    4885                                         val = cast_unsized_simple(s, type);
    4886                         }
    4887 
    4888                         if (!val)
    4889                         {
    4890                                 Py_DECREF(dict);
    4891                                 Py_DECREF(reslist);
    4892                                 reslist = NULL;
    4893                                 goto exit;
    4894                         }
    4895 
    4896                         PyDict_SetItemString(dict, PQfname(self->result, j), val);
    4897                         Py_DECREF(val);
    4898                 }
    4899 
    4900                 PyList_SET_ITEM(reslist, i, dict);
    4901         }
    4902 
    4903 exit:
    4904         PyMem_Free(col_types);
    4905 
    4906         /* returns list */
    4907         return reslist;
    4908 }
    4909 
    4910 /* retrieves last result as named tuples */
    4911 static char queryNamedResult__doc__[] =
     4923                PyList_SET_ITEM(result_list, i, row_dict);
     4924        }
     4925
     4926        return result_list;
     4927}
     4928
     4929/* retrieves last result as iterator of dictionaries */
     4930static char queryDictiter__doc__[] =
     4931"dictiter() -- Get the result of a query\n\n"
     4932"The result is returned as an iterator of rows, each one a a dictionary\n"
     4933"with the field names used as the keys.\n";
     4934
     4935static PyObject *
     4936queryDictiter(queryObject *self, PyObject *noargs)
     4937{
     4938        if (dictiter) {
     4939                return PyObject_CallFunction(dictiter, "(O)", self);
     4940        }
     4941        return queryGetIter(self);
     4942}
     4943
     4944
     4945/* retrieves last result as list of named tuples */
     4946static char queryNamedresult__doc__[] =
    49124947"namedresult() -- Get the result of a query\n\n"
    4913 "The result is returned as a list of rows, each one a tuple of fields\n"
     4948"The result is returned as a list of rows, each one a named tuple of fields\n"
    49144949"in the order returned by the server.\n";
    49154950
    49164951static PyObject *
    4917 queryNamedResult(queryObject *self, PyObject *noargs)
    4918 {
    4919         PyObject   *ret;
    4920 
    4921         if (namedresult)
    4922         {
    4923                 ret = PyObject_CallFunction(namedresult, "(O)", self);
    4924 
    4925                 if (ret == NULL)
    4926                         return NULL;
    4927                 }
    4928         else
    4929         {
    4930                 ret = queryGetResult(self, NULL);
    4931         }
    4932 
    4933         return ret;
     4952queryNamedresult(queryObject *self, PyObject *noargs)
     4953{
     4954        if (namediter) {
     4955                PyObject* res = PyObject_CallFunction(namediter, "(O)", self);
     4956                if (res && PyList_Check(res))
     4957                        return res;
     4958                PyObject *res_list = PySequence_List(res);
     4959                Py_DECREF(res);
     4960                return res_list;
     4961        }
     4962        return queryGetresult(self, noargs);
     4963}
     4964
     4965/* retrieves last result as iterator of named tuples */
     4966static char queryNamediter__doc__[] =
     4967"namediter() -- Get the result of a query\n\n"
     4968"The result is returned as an iterator of rows, each one a named tuple\n"
     4969"of fields in the order returned by the server.\n";
     4970
     4971static PyObject *
     4972queryNamediter(queryObject *self, PyObject *noargs)
     4973{
     4974        if (namediter) {
     4975                PyObject* res = PyObject_CallFunction(namediter, "(O)", self);
     4976                if (res && !PyList_Check(res))
     4977                        return res;
     4978                PyObject* res_iter = (Py_TYPE(res)->tp_iter)((PyObject *)self);
     4979                Py_DECREF(res);
     4980                return res_iter;
     4981        }
     4982        return queryGetIter(self);
     4983}
     4984
     4985/* Return length of a query object. */
     4986static Py_ssize_t
     4987queryLen(PyObject *self)
     4988{
     4989        PyObject   *tmp;
     4990        long            len;
     4991
     4992        tmp = PyLong_FromLong(((queryObject*)self)->max_row);
     4993        len = PyLong_AsSsize_t(tmp);
     4994        Py_DECREF(tmp);
     4995        return len;
     4996}
     4997
     4998/* Return given item from a query object. */
     4999static PyObject *
     5000queryGetItem(PyObject *self, Py_ssize_t i)
     5001{
     5002        queryObject        *q = (queryObject *)self;
     5003        PyObject           *tmp;
     5004        long                    row;
     5005
     5006        tmp = PyLong_FromSize_t(i);
     5007        row = PyLong_AsLong(tmp);
     5008        Py_DECREF(tmp);
     5009
     5010        if (row < 0 || row >= q->max_row) {
     5011                PyErr_SetNone(PyExc_IndexError);
     5012                return NULL;
     5013        }
     5014
     5015        q->current_row = row;
     5016        return queryGetRowAsTuple(q);
    49345017}
    49355018
     
    50525135/* query object methods */
    50535136static struct PyMethodDef queryMethods[] = {
    5054         {"getresult", (PyCFunction) queryGetResult, METH_NOARGS,
    5055                         queryGetResult__doc__},
    5056         {"dictresult", (PyCFunction) queryDictResult, METH_NOARGS,
    5057                         queryDictResult__doc__},
    5058         {"namedresult", (PyCFunction) queryNamedResult, METH_NOARGS,
    5059                         queryNamedResult__doc__},
    5060         {"fieldname", (PyCFunction) queryFieldName, METH_VARARGS,
    5061                          queryFieldName__doc__},
    5062         {"fieldnum", (PyCFunction) queryFieldNumber, METH_VARARGS,
    5063                         queryFieldNumber__doc__},
    5064         {"listfields", (PyCFunction) queryListFields, METH_NOARGS,
    5065                         queryListFields__doc__},
    5066         {"ntuples", (PyCFunction) queryNTuples, METH_NOARGS,
    5067                         queryNTuples__doc__},
     5137        {"getresult", (PyCFunction) queryGetresult, METH_NOARGS,
     5138                        queryGetresult__doc__},
     5139        {"dictresult", (PyCFunction) queryDictresult, METH_NOARGS,
     5140                        queryDictresult__doc__},
     5141        {"dictiter", (PyCFunction) queryDictiter, METH_NOARGS,
     5142                        queryDictiter__doc__},
     5143        {"namedresult", (PyCFunction) queryNamedresult, METH_NOARGS,
     5144                        queryNamedresult__doc__},
     5145        {"namediter", (PyCFunction) queryNamediter, METH_NOARGS,
     5146                        queryNamediter__doc__},
     5147        {"fieldname", (PyCFunction) queryFieldname, METH_VARARGS,
     5148                         queryFieldname__doc__},
     5149        {"fieldnum", (PyCFunction) queryFieldnum, METH_VARARGS,
     5150                        queryFieldnum__doc__},
     5151        {"listfields", (PyCFunction) queryListfields, METH_NOARGS,
     5152                        queryListfields__doc__},
     5153        {"ntuples", (PyCFunction) queryNtuples, METH_NOARGS,
     5154                        queryNtuples__doc__},
    50685155        {NULL, NULL}
    50695156};
     5157
     5158/* query sequence protocol methods */
     5159static PySequenceMethods querySequenceMethods = {
     5160        (lenfunc) queryLen,                             /* sq_length */
     5161        0,                                                              /* sq_concat */
     5162        0,                                                              /* sq_repeat */
     5163        (ssizeargfunc) queryGetItem,    /* sq_item */
     5164        0,                                                              /* sq_ass_item */
     5165        0,                                                              /* sq_contains */
     5166        0,                                                              /* sq_inplace_concat */
     5167        0,                                                              /* sq_inplace_repeat */
     5168};
     5169
    50705170
    50715171/* query type definition */
    50725172static PyTypeObject queryType = {
    50735173        PyVarObject_HEAD_INIT(NULL, 0)
    5074         "pg.Query",                                             /* tp_name */
    5075         sizeof(queryObject),                    /* tp_basicsize */
    5076         0,                                                              /* tp_itemsize */
     5174        "pg.Query",                                     /* tp_name */
     5175        sizeof(queryObject),            /* tp_basicsize */
     5176        0,                                                      /* tp_itemsize */
    50775177        /* methods */
    5078         (destructor) queryDealloc,              /* tp_dealloc */
    5079         0,                                                              /* tp_print */
    5080         0,                                                              /* tp_getattr */
    5081         0,                                                              /* tp_setattr */
    5082         0,                                                              /* tp_compare */
    5083         0,                                                              /* tp_repr */
    5084         0,                                                              /* tp_as_number */
    5085         0,                                                              /* tp_as_sequence */
    5086         0,                                                              /* tp_as_mapping */
    5087         0,                                                              /* tp_hash */
    5088         0,                                                              /* tp_call */
    5089         (reprfunc) queryStr,                    /* tp_str */
    5090         PyObject_GenericGetAttr,                /* tp_getattro */
    5091         0,                                                              /* tp_setattro */
    5092         0,                                                              /* tp_as_buffer */
    5093         Py_TPFLAGS_DEFAULT,                             /* tp_flags */
    5094         0,                                                              /* tp_doc */
    5095         0,                                                              /* tp_traverse */
    5096         0,                                                              /* tp_clear */
    5097         0,                                                              /* tp_richcompare */
    5098         0,                                                              /* tp_weaklistoffset */
    5099         0,                                                              /* tp_iter */
    5100         0,                                                              /* tp_iternext */
    5101         queryMethods,                                   /* tp_methods */
     5178        (destructor) queryDealloc,      /* tp_dealloc */
     5179        0,                                                      /* tp_print */
     5180        0,                                                      /* tp_getattr */
     5181        0,                                                      /* tp_setattr */
     5182        0,                                                      /* tp_compare */
     5183        0,                                                      /* tp_repr */
     5184        0,                                                      /* tp_as_number */
     5185        &querySequenceMethods,          /* tp_as_sequence */
     5186        0,                                                      /* tp_as_mapping */
     5187        0,                                                      /* tp_hash */
     5188        0,                                                      /* tp_call */
     5189        (reprfunc) queryStr,            /* tp_str */
     5190        PyObject_GenericGetAttr,        /* tp_getattro */
     5191        0,                                                      /* tp_setattro */
     5192        0,                                                      /* tp_as_buffer */
     5193        Py_TPFLAGS_DEFAULT
     5194                |Py_TPFLAGS_HAVE_ITER,  /* tp_flags */
     5195        0,                                                      /* tp_doc */
     5196        0,                                                      /* tp_traverse */
     5197        0,                                                      /* tp_clear */
     5198        0,                                                      /* tp_richcompare */
     5199        0,                                                      /* tp_weaklistoffset */
     5200        (getiterfunc)queryGetIter,      /* tp_iter */
     5201        (iternextfunc)queryNext,        /* tp_iternext */
     5202        queryMethods,                           /* tp_methods */
    51025203};
    51035204
     
    54985599}
    54995600
    5500 /* get named result factory */
    5501 static char pgGetNamedresult__doc__[] =
    5502 "get_namedresult() -- get the function used for getting named results";
    5503 
    5504 static PyObject *
    5505 pgGetNamedresult(PyObject *self, PyObject *noargs)
     5601/* get dict result factory */
     5602static char pgGetDictiter__doc__[] =
     5603"get_dictiter() -- get the generator used for getting dict results";
     5604
     5605static PyObject *
     5606pgGetDictiter(PyObject *self, PyObject *noargs)
    55065607{
    55075608        PyObject *ret;
    55085609
    5509         ret = namedresult ? namedresult : Py_None;
     5610        ret = dictiter ? dictiter : Py_None;
    55105611        Py_INCREF(ret);
    55115612
     
    55135614}
    55145615
    5515 /* set named result factory */
    5516 static char pgSetNamedresult__doc__[] =
    5517 "set_namedresult(func) -- set a function to be used for getting named results";
    5518 
    5519 static PyObject *
    5520 pgSetNamedresult(PyObject *self, PyObject *func)
     5616/* set dict result factory */
     5617static char pgSetDictiter__doc__[] =
     5618"set_dictiter(func) -- set a generator to be used for getting dict results";
     5619
     5620static PyObject *
     5621pgSetDictiter(PyObject *self, PyObject *func)
    55215622{
    55225623        PyObject *ret = NULL;
     
    55245625        if (func == Py_None)
    55255626        {
    5526                 Py_XDECREF(namedresult); namedresult = NULL;
     5627                Py_XDECREF(dictiter); dictiter = NULL;
    55275628                Py_INCREF(Py_None); ret = Py_None;
    55285629        }
    55295630        else if (PyCallable_Check(func))
    55305631        {
    5531                 Py_XINCREF(func); Py_XDECREF(namedresult); namedresult = func;
     5632                Py_XINCREF(func); Py_XDECREF(dictiter); dictiter = func;
    55325633                Py_INCREF(Py_None); ret = Py_None;
    55335634        }
    55345635        else
    55355636                PyErr_SetString(PyExc_TypeError,
    5536                         "Function set_namedresult() expects"
     5637                        "Function set_dictiter() expects"
     5638                         " a callable or None as argument");
     5639
     5640        return ret;
     5641}
     5642
     5643/* get named result factory */
     5644static char pgGetNamediter__doc__[] =
     5645"get_namediter() -- get the generator used for getting named results";
     5646
     5647static PyObject *
     5648pgGetNamediter(PyObject *self, PyObject *noargs)
     5649{
     5650        PyObject *ret;
     5651
     5652        ret = namediter ? namediter : Py_None;
     5653        Py_INCREF(ret);
     5654
     5655        return ret;
     5656}
     5657
     5658/* set named result factory */
     5659static char pgSetNamediter__doc__[] =
     5660"set_namediter(func) -- set a generator to be used for getting named results";
     5661
     5662static PyObject *
     5663pgSetNamediter(PyObject *self, PyObject *func)
     5664{
     5665        PyObject *ret = NULL;
     5666
     5667        if (func == Py_None)
     5668        {
     5669                Py_XDECREF(namediter); namediter = NULL;
     5670                Py_INCREF(Py_None); ret = Py_None;
     5671        }
     5672        else if (PyCallable_Check(func))
     5673        {
     5674                Py_XINCREF(func); Py_XDECREF(namediter); namediter = func;
     5675                Py_INCREF(Py_None); ret = Py_None;
     5676        }
     5677        else
     5678                PyErr_SetString(PyExc_TypeError,
     5679                        "Function set_namediter() expects"
    55375680                         " a callable or None as argument");
    55385681
     
    60286171        {"set_bytea_escaped", (PyCFunction) pgSetByteaEscaped, METH_VARARGS,
    60296172                pgSetByteaEscaped__doc__},
    6030         {"get_namedresult", (PyCFunction) pgGetNamedresult, METH_NOARGS,
    6031                         pgGetNamedresult__doc__},
    6032         {"set_namedresult", (PyCFunction) pgSetNamedresult, METH_O,
    6033                         pgSetNamedresult__doc__},
     6173        {"get_dictiter", (PyCFunction) pgGetDictiter, METH_NOARGS,
     6174                        pgGetDictiter__doc__},
     6175        {"set_dictiter", (PyCFunction) pgSetDictiter, METH_O,
     6176                        pgSetDictiter__doc__},
     6177        {"get_namediter", (PyCFunction) pgGetNamediter, METH_NOARGS,
     6178                        pgGetNamediter__doc__},
     6179        {"set_namediter", (PyCFunction) pgSetNamediter, METH_O,
     6180                        pgSetNamediter__doc__},
     6181        /* get/set_namedresult is deprecated, use get/set_namediter */
     6182        {"get_namedresult", (PyCFunction) pgGetNamediter, METH_NOARGS,
     6183                        pgGetNamediter__doc__},
     6184        {"set_namedresult", (PyCFunction) pgSetNamediter, METH_O,
     6185                        pgSetNamediter__doc__},
    60346186        {"get_jsondecode", (PyCFunction) pgGetJsondecode, METH_NOARGS,
    60356187                        pgGetJsondecode__doc__},
Note: See TracChangeset for help on using the changeset viewer.