On Sun, Dec 19, 2010 at 01:21:03PM +0100, Sören Brunk scratched on the wall:
> In xBestIndex, each constraint contains the column on the left-hand side > (iColumn) and the operator (op). If I understood correctly, xFilter gets > the value on the right-hand side of each constraint you chose to use. Correct. > But I need to know not only that value in xFilter, but also the column > on the left-hand side and the operator. Column indexes are not passed into xFilter(). From inside xFilter(), there is no way to match a given value to a specific column. You have to know the order that the column values that are passed in. That ordering is determined by your code in xBestIndex(). Inside xBestIndex(), the values you set in idxinfo->aConstraintUsage[x].argvIndex will determine where the idxinfo->aConstraint[x].iColumn value is passed into xFilter(). So the two functions must agree on how and where all those values are setup, or you must somehow convey the information via idxNum/idxStr. > I'm wondering if there is any way to pass that additional information to > xFilter besides encoding it into idxNum/idxStr somehow. Not easily. There may be multiple tables in-flight at a given time, so any kind of global storage outside the function parameters can get quite tricky. By far, the easiest thing is to pack everything into those two parameters. xBestIndex() can be called multiple times to test multiple query plans. This means anything you allocate inside of xBestIndex() may get abandoned. Again, without some complex logic to deal with external memory stores, the safest thing to do is single allocations with sqlite3_malloc() that are passed via idxStr. If the memory is allocated with sqlite3_malloc(), then SQLite will properly deallocate any abandoned query plans. But the allocation must be one big chunk (it cannot be a multi-level or "deep" data structure with pointers to other data structures) because SQLite will only call sqlite3_free() on the top level idxStr pointer. As explained on page 267, the most typical usage is for "internal" modules that are using normal SQL statements on "shadow tables" to implement the virtual table. In that case, xBestIndex() can build SQL statement strings, complete with indexed SQL statement parameters, such as "?1", "?2", etc. These SQL command strings can be passed via idxStr, and the parameter indexes can be matched to table column indexes by setting the argvIndex numbers. Then, xFilter() only need to prepare the given idxStr command strings and bind argv[0] to parameter index 1, argv[1] to parameter index 2, and so on (remember that parameter indexes start with 1), and run the statements. In that situation, most of the actual logic happens in xBestIndex(). This doesn't work so well with "external" modules, where you often need to pass a great deal more state than a simple string. If you need to pass a data structure, you can use the idxStr pointer. Just remember that you should allocate the structure as a single call to sqlite3_malloc(). That means keeping the data structure "flat", either by using static sizes or hand-packing the memory. You also can't bind every column value to its own column index via the argvIndex (that is, make all the argv[] indexes match the column indexes), because the argvIndex values are not allowed to have gaps. I'd love to point you at some examples, but I'm not sure there are any significant "external" style modules that provide solid examples of xBestIndex() and xFilter(). External modules are typically fairly custom in nature, and I'm not sure there is a very established design pattern, as there is with "internal" style modules. -j -- Jay A. Kreibich < J A Y @ K R E I B I.C H > "Intelligence is like underwear: it is important that you have it, but showing it to the wrong people has the tendency to make them feel uncomfortable." -- Angela Johnson _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users