implemented more db cursor methods: scroll, next, __iter__
This commit is contained in:
parent
08deef8cc5
commit
a95cdbba58
@ -47,15 +47,6 @@ static set<Rcl::Doc *> the_docs;
|
|||||||
|
|
||||||
static RclConfig *rclconfig;
|
static RclConfig *rclconfig;
|
||||||
|
|
||||||
// This has to exist somewhere in the python api ??
|
|
||||||
static PyObject *obj_Create(PyTypeObject *tp, PyObject *args, PyObject *kwargs)
|
|
||||||
{
|
|
||||||
PyObject *result = tp->tp_new(tp, args, kwargs);
|
|
||||||
if (result && tp->tp_init(result, args, kwargs) < 0)
|
|
||||||
return 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
/// SEARCHDATA SearchData code
|
/// SEARCHDATA SearchData code
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -707,6 +698,7 @@ static PyTypeObject recoll_DocType = {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
/// QUERY Query object
|
/// QUERY Query object
|
||||||
|
struct recoll_DbObject;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
@ -717,6 +709,7 @@ typedef struct {
|
|||||||
string *sortfield;
|
string *sortfield;
|
||||||
int ascending;
|
int ascending;
|
||||||
int arraysize; // Default size for fetchmany
|
int arraysize; // Default size for fetchmany
|
||||||
|
recoll_DbObject* connection;
|
||||||
} recoll_QueryObject;
|
} recoll_QueryObject;
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_Query_close,
|
PyDoc_STRVAR(doc_Query_close,
|
||||||
@ -730,6 +723,8 @@ Query_close(recoll_QueryObject *self)
|
|||||||
the_queries.erase(self->query);
|
the_queries.erase(self->query);
|
||||||
deleteZ(self->query);
|
deleteZ(self->query);
|
||||||
deleteZ(self->sortfield);
|
deleteZ(self->sortfield);
|
||||||
|
if (self->connection)
|
||||||
|
Py_DECREF(self->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -754,6 +749,7 @@ Query_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
|||||||
self->rowcount = -1;
|
self->rowcount = -1;
|
||||||
self->arraysize = 1;
|
self->arraysize = 1;
|
||||||
self->sortfield = new string;
|
self->sortfield = new string;
|
||||||
|
self->connection = 0;
|
||||||
return (PyObject *)self;
|
return (PyObject *)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,6 +770,12 @@ Query_init(recoll_QueryObject *self, PyObject *, PyObject *)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
Query_iter(PyObject *self)
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_Query_sortby,
|
PyDoc_STRVAR(doc_Query_sortby,
|
||||||
"sortby(field=fieldname, ascending=True)\n"
|
"sortby(field=fieldname, ascending=True)\n"
|
||||||
"Sort results by 'fieldname', in ascending or descending order.\n"
|
"Sort results by 'fieldname', in ascending or descending order.\n"
|
||||||
@ -919,9 +921,10 @@ PyDoc_STRVAR(doc_Query_fetchone,
|
|||||||
"Fetches the next Doc object in the current search results.\n"
|
"Fetches the next Doc object in the current search results.\n"
|
||||||
);
|
);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
Query_fetchone(recoll_QueryObject* self, PyObject *, PyObject *)
|
Query_fetchone(PyObject *_self)
|
||||||
{
|
{
|
||||||
LOGDEB(("Query_fetchone\n"));
|
recoll_QueryObject* self = (recoll_QueryObject*)_self;
|
||||||
|
LOGDEB(("Query_fetchone/next\n"));
|
||||||
|
|
||||||
if (self->query == 0 ||
|
if (self->query == 0 ||
|
||||||
the_queries.find(self->query) == the_queries.end()) {
|
the_queries.find(self->query) == the_queries.end()) {
|
||||||
@ -934,11 +937,15 @@ Query_fetchone(recoll_QueryObject* self, PyObject *, PyObject *)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
recoll_DocObject *result =
|
recoll_DocObject *result =
|
||||||
(recoll_DocObject *)obj_Create(&recoll_DocType, 0, 0);
|
(recoll_DocObject *)PyObject_CallObject((PyObject *)&recoll_DocType, 0);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
PyErr_SetString(PyExc_EnvironmentError, "doc create failed");
|
PyErr_SetString(PyExc_EnvironmentError, "doc create failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (self->next >= self->rowcount) {
|
||||||
|
PyErr_SetString(PyExc_StopIteration, "End of list reached");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (!self->query->getDoc(self->next, *result->doc)) {
|
if (!self->query->getDoc(self->next, *result->doc)) {
|
||||||
PyErr_SetString(PyExc_EnvironmentError, "query: cant fetch result");
|
PyErr_SetString(PyExc_EnvironmentError, "query: cant fetch result");
|
||||||
self->next = -1;
|
self->next = -1;
|
||||||
@ -951,10 +958,10 @@ Query_fetchone(recoll_QueryObject* self, PyObject *, PyObject *)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_Query_fetchmany,
|
PyDoc_STRVAR(doc_Query_fetchmany,
|
||||||
"fetchmany([size=query.arraysize]) -> Doc list\n"
|
"fetchmany([size=query.arraysize]) -> Doc list\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Fetches the next Doc objects in the current search results.\n"
|
"Fetches the next Doc objects in the current search results.\n"
|
||||||
);
|
);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
Query_fetchmany(recoll_QueryObject* self, PyObject *args, PyObject *kwargs)
|
Query_fetchmany(recoll_QueryObject* self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
@ -963,45 +970,86 @@ Query_fetchmany(recoll_QueryObject* self, PyObject *args, PyObject *kwargs)
|
|||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", (char**)kwlist,
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", (char**)kwlist,
|
||||||
&size))
|
&size))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
size = self->arraysize;
|
size = self->arraysize;
|
||||||
|
|
||||||
|
if (self->query == 0 ||
|
||||||
|
the_queries.find(self->query) == the_queries.end()) {
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "query");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int cnt = self->query->getResCnt();
|
||||||
|
if (cnt <= 0 || self->next < 0) {
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "query: no results");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *reslist = PyList_New(0);
|
||||||
|
int howmany = MIN(self->rowcount - self->next, size);
|
||||||
|
for (int i = 0; i < howmany; i++) {
|
||||||
|
recoll_DocObject *docobj = (recoll_DocObject *)
|
||||||
|
PyObject_CallObject((PyObject *)&recoll_DocType, 0);
|
||||||
|
if (!docobj) {
|
||||||
|
PyErr_SetString(PyExc_EnvironmentError, "doc create failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!self->query->getDoc(self->next, *docobj->doc)) {
|
||||||
|
PyErr_SetString(PyExc_EnvironmentError, "can't fetch");
|
||||||
|
self->next = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->next++;
|
||||||
|
movedocfields(docobj->doc);
|
||||||
|
PyList_Append(reslist, (PyObject*)docobj);
|
||||||
|
}
|
||||||
|
return (PyObject *)reslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR(doc_Query_scroll,
|
||||||
|
"scroll(value, [, mode='relative'/'absolute' ]) -> new int position\n"
|
||||||
|
"\n"
|
||||||
|
"Adjusts the position in the current result set.\n"
|
||||||
|
);
|
||||||
|
static PyObject *
|
||||||
|
Query_scroll(recoll_QueryObject* self, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
LOGDEB(("Query_scroll\n"));
|
||||||
|
static const char *kwlist[] = {"position", "mode", NULL};
|
||||||
|
int pos = 0;
|
||||||
|
char *smode = 0;
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s", (char**)kwlist,
|
||||||
|
&pos, &smode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bool isrelative = 1;
|
||||||
|
if (smode != 0) {
|
||||||
|
if (!strcasecmp(smode, "relative")) {
|
||||||
|
isrelative = 1;
|
||||||
|
} else if (!strcasecmp(smode, "absolute")) {
|
||||||
|
isrelative = 0;
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "bad mode value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (self->query == 0 ||
|
if (self->query == 0 ||
|
||||||
the_queries.find(self->query) == the_queries.end()) {
|
the_queries.find(self->query) == the_queries.end()) {
|
||||||
PyErr_SetString(PyExc_AttributeError, "query");
|
PyErr_SetString(PyExc_AttributeError, "query");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int cnt = self->query->getResCnt();
|
int newpos = isrelative ? self->next + pos : pos;
|
||||||
if (cnt <= 0 || self->next < 0) {
|
if (newpos < 0 || newpos >= self->rowcount) {
|
||||||
PyErr_SetString(PyExc_AttributeError, "query: no results");
|
PyErr_SetString(PyExc_IndexError, "position out of range");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
self->next = newpos;
|
||||||
PyObject *reslist = PyList_New(0);
|
return Py_BuildValue("i", newpos);
|
||||||
int howmany = MIN(self->rowcount - self->next, size);
|
|
||||||
for (int i = 0; i < howmany; i++) {
|
|
||||||
recoll_DocObject *docobj =
|
|
||||||
(recoll_DocObject *)obj_Create(&recoll_DocType, 0, 0);
|
|
||||||
if (!docobj) {
|
|
||||||
PyErr_SetString(PyExc_EnvironmentError, "doc create failed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!self->query->getDoc(self->next, *docobj->doc)) {
|
|
||||||
PyErr_SetString(PyExc_EnvironmentError, "can't fetch");
|
|
||||||
self->next = -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
self->next++;
|
|
||||||
movedocfields(docobj->doc);
|
|
||||||
PyList_Append(reslist, (PyObject*)docobj);
|
|
||||||
}
|
|
||||||
return (PyObject *)reslist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_Query_highlight,
|
PyDoc_STRVAR(doc_Query_highlight,
|
||||||
"highlight(text, ishtml = 0/1, methods = object))\n"
|
"highlight(text, ishtml = 0/1, methods = object))\n"
|
||||||
"Will insert <span \"class=rclmatch\"></span> tags around the match areas\n"
|
"Will insert <span \"class=rclmatch\"></span> tags around the match areas\n"
|
||||||
@ -1262,6 +1310,8 @@ static PyMethodDef Query_methods[] = {
|
|||||||
doc_Query_execute},
|
doc_Query_execute},
|
||||||
{"executesd", (PyCFunction)Query_executesd, METH_VARARGS|METH_KEYWORDS,
|
{"executesd", (PyCFunction)Query_executesd, METH_VARARGS|METH_KEYWORDS,
|
||||||
doc_Query_executesd},
|
doc_Query_executesd},
|
||||||
|
{"next", (PyCFunction)Query_fetchone, METH_NOARGS,
|
||||||
|
doc_Query_fetchone},
|
||||||
{"fetchone", (PyCFunction)Query_fetchone, METH_NOARGS,
|
{"fetchone", (PyCFunction)Query_fetchone, METH_NOARGS,
|
||||||
doc_Query_fetchone},
|
doc_Query_fetchone},
|
||||||
{"fetchmany", (PyCFunction)Query_fetchmany, METH_VARARGS|METH_KEYWORDS,
|
{"fetchmany", (PyCFunction)Query_fetchmany, METH_VARARGS|METH_KEYWORDS,
|
||||||
@ -1278,6 +1328,8 @@ static PyMethodDef Query_methods[] = {
|
|||||||
doc_Query_getgroups},
|
doc_Query_getgroups},
|
||||||
{"makedocabstract", (PyCFunction)Query_makedocabstract,
|
{"makedocabstract", (PyCFunction)Query_makedocabstract,
|
||||||
METH_VARARGS|METH_KEYWORDS, doc_Query_makedocabstract},
|
METH_VARARGS|METH_KEYWORDS, doc_Query_makedocabstract},
|
||||||
|
{"scroll", (PyCFunction)Query_scroll,
|
||||||
|
METH_VARARGS|METH_KEYWORDS, doc_Query_scroll},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1291,12 +1343,15 @@ static PyMemberDef Query_members[] = {
|
|||||||
(char*)"Alias for 'next'. Next index to be fetched from results.\n"
|
(char*)"Alias for 'next'. Next index to be fetched from results.\n"
|
||||||
"Starts at 0"
|
"Starts at 0"
|
||||||
},
|
},
|
||||||
{(char*)"rowcount", T_INT, offsetof(recoll_QueryObject, rowcount), 0,
|
{(char*)"rowcount", T_INT, offsetof(recoll_QueryObject, rowcount),
|
||||||
(char*)"Number of records returned by the last execute"
|
READONLY, (char*)"Number of records returned by the last execute"
|
||||||
},
|
},
|
||||||
{(char*)"arraysize", T_INT, offsetof(recoll_QueryObject, arraysize), 0,
|
{(char*)"arraysize", T_INT, offsetof(recoll_QueryObject, arraysize), 0,
|
||||||
(char*)"Default number of records processed by fetchmany (r/w)"
|
(char*)"Default number of records processed by fetchmany (r/w)"
|
||||||
},
|
},
|
||||||
|
{(char*)"connection", T_OBJECT_EX, offsetof(recoll_QueryObject, connection),
|
||||||
|
0, (char*)"Connection object this is from"
|
||||||
|
},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1325,14 +1380,14 @@ static PyTypeObject recoll_QueryType = {
|
|||||||
0, /*tp_getattro*/
|
0, /*tp_getattro*/
|
||||||
0, /*tp_setattro*/
|
0, /*tp_setattro*/
|
||||||
0, /*tp_as_buffer*/
|
0, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
|
||||||
doc_QueryObject, /* tp_doc */
|
doc_QueryObject, /* tp_doc */
|
||||||
0, /* tp_traverse */
|
0, /* tp_traverse */
|
||||||
0, /* tp_clear */
|
0, /* tp_clear */
|
||||||
0, /* tp_richcompare */
|
0, /* tp_richcompare */
|
||||||
0, /* tp_weaklistoffset */
|
0, /* tp_weaklistoffset */
|
||||||
0, /* tp_iter */
|
Query_iter, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
Query_fetchone, /* tp_iternext */
|
||||||
Query_methods, /* tp_methods */
|
Query_methods, /* tp_methods */
|
||||||
Query_members, /* tp_members */
|
Query_members, /* tp_members */
|
||||||
0, /* tp_getset */
|
0, /* tp_getset */
|
||||||
@ -1349,7 +1404,7 @@ static PyTypeObject recoll_QueryType = {
|
|||||||
|
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
////// DB Db object code
|
////// DB Db object code
|
||||||
typedef struct {
|
typedef struct recoll_DbObject {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
/* Type-specific fields go here. */
|
/* Type-specific fields go here. */
|
||||||
Rcl::Db *db;
|
Rcl::Db *db;
|
||||||
@ -1472,11 +1527,14 @@ Db_query(recoll_DbObject* self)
|
|||||||
PyErr_SetString(PyExc_AttributeError, "db");
|
PyErr_SetString(PyExc_AttributeError, "db");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
recoll_QueryObject *result =
|
recoll_QueryObject *result = (recoll_QueryObject *)
|
||||||
(recoll_QueryObject *)obj_Create(&recoll_QueryType, 0, 0);
|
PyObject_CallObject((PyObject *)&recoll_QueryType, 0);
|
||||||
if (!result)
|
if (!result)
|
||||||
return 0;
|
return 0;
|
||||||
result->query = new Rcl::Query(self->db);
|
result->query = new Rcl::Query(self->db);
|
||||||
|
result->connection = self;
|
||||||
|
Py_INCREF(self);
|
||||||
|
|
||||||
the_queries.insert(result->query);
|
the_queries.insert(result->query);
|
||||||
return (PyObject *)result;
|
return (PyObject *)result;
|
||||||
}
|
}
|
||||||
@ -1734,9 +1792,8 @@ static PyObject *
|
|||||||
recoll_connect(PyObject *self, PyObject *args, PyObject *kwargs)
|
recoll_connect(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
LOGDEB(("recoll_connect\n"));
|
LOGDEB(("recoll_connect\n"));
|
||||||
recoll_DbObject *db =
|
recoll_DbObject *db = (recoll_DbObject *)
|
||||||
(recoll_DbObject *)obj_Create(&recoll_DbType, args, kwargs);
|
PyObject_Call((PyObject *)&recoll_DbType, args, kwargs);
|
||||||
|
|
||||||
return (PyObject *)db;
|
return (PyObject *)db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -227,7 +227,7 @@ class RclGui_Main(QtGui.QMainWindow):
|
|||||||
self.ui.resTable.setModel(self.qmodel)
|
self.ui.resTable.setModel(self.qmodel)
|
||||||
|
|
||||||
def onexit(self):
|
def onexit(self):
|
||||||
sys.exit(0)
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
def Usage():
|
def Usage():
|
||||||
@ -235,7 +235,6 @@ def Usage():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
|
|
||||||
app = QtGui.QApplication(args)
|
app = QtGui.QApplication(args)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user