From: Florin M. <fm...@ob...> - 2006-04-08 02:39:51
|
On 7-Apr-06, at 6:08 PM, Michael Kifer wrote: > > > When XSB is called from C, we have to go through string-level > interface, > which involves parsing a query string and is slow. The only other > possibility is to call XSB by constructing a query term in C, but > this is > difficult for ad hoc queries. > > I was wondering if there is a way to do something similar to the > prepare > statement in databases: to pass and compile queries, which would then > return a query handle. A separate statement would then use that query > handle and the actual parameters to invoke the query. > > Any thought on how this could be done? > > > --michael Would the following hack be sufficient? It seems to work for me, but let me know of any flaws you may find. It relies on two helper Prolog predicates. I also included an example C client (I omitted all the XSB initialization code). One obvious improvement would be automatic detection of the variables in the query string by using some markup, but the following should be enough to illustrate the idea. The test output is at the end. %%% File compile_q.P :- import trie_intern/3, trie_interned/3 from intern. :- import concat_atom/2 from string. :- import numbervars/1, unnumbervars/3 from num_vars. compile_q(Query, NumVars, Functor) :- trie_intern(Query, Handle, _), concat_atom(['q', Handle], Functor), functor(Head, Functor, NumVars), numbervars(Head), numbervars(Query), unnumbervars((Head :- Query), 0, Term), assert(Term). run_q(Functor, Args) :- Query =.. [Functor|Args], call(Query). %%% EOF compile_q.P /*** The C test function ***/ char compile_query[1024]; char run_query[1024]; void compile_and_run() { // The test query. char* query = "(append(X,Y,Z))"; int num_vars = 3; // Consult the helper file. xsb_command_string("consult('basics.P')."); xsb_command_string("consult('/Users/fm/compile_q.P')."); // Compile the test query. sprintf(compile_query, "compile_q(%s, %d, Handle).", query, num_vars); xsb_query_string_string(compile_query, &answer_buf, "%"); // Retrieve the query handle. char* functor = answer_buf.string + answer_buf.length; while (*functor != '%' && functor - answer_buf.string > 0) --functor; ++functor; xsb_close_query(); XSB_StrSet(&answer_buf, ""); // Run the compiled query. sprintf(run_query, "run_q(%s, [X, Y, [1,2,3]]).", functor); xsb_query_string_string(run_query, &answer_buf, "%"); // Print the results. int done = 0; while (!done) { printf("%s\n", answer_buf.string); XSB_StrSet(&answer_buf, ""); done = xsb_next_string(&answer_buf, "%"); } } /*** End ***/ When the test is executed, the following output is printed: [basics loaded] [compile_q loaded] []%[1,2,3] [1]%[2,3] [1,2]%[3] [1,2,3]%[] --Florin |