First cleanup, zebra_api_ext.c is epmty now
[idzebra-moved-to-github.git] / perl / zebra_perl.c
1 //#include "zebraapi.h"
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5
6 #include <yaz/yaz-util.h>
7 #include <yaz/proto.h>
8 #include <yaz/log.h>
9 #include <yaz/cql.h>
10 #include <yaz/pquery.h>
11
12 #include "zebra_perl.h"
13 #include <data1.h>
14
15 NMEM handles;
16
17 void init (void) {
18   nmem_init ();
19   yaz_log_init_prefix ("ZebraPerl");
20   yaz_log (LOG_LOG, "Zebra API initialized");
21 }
22
23 void DESTROY (void) {
24   nmem_exit ();
25   yaz_log (LOG_LOG, "Zebra API destroyed");
26 }   
27
28 /* Logging facilities from yaz */
29 void logLevel (int level) {
30   yaz_log_init_level(level);
31 }
32  
33 void logFile (const char *fname) {
34   yaz_log_init_file(fname);
35 }
36
37 void logMsg (int level, const char *message) {
38   logf(level, "%s", message);
39 }
40
41 /* debug tool for data1... maybe should be moved to data1. 
42    perl can't really pass filehandles */
43 void data1_print_tree(data1_handle dh, data1_node *n) {
44   data1_pr_tree(dh, n, stdout);
45 }
46
47 /* ---------------------------------------------------------------------------
48   Record retrieval 
49   2 phase retrieval - I didn't manage to return array of blessed references
50   to wrapped structures... it's feasible, but I'll need some time 
51   / pop - 2002-11-17
52 */
53
54 void record_retrieve(RetrievalObj *ro,
55                      ODR stream,
56                      RetrievalRecord *res,
57                      int pos) 
58 {
59   int i = pos - 1;
60
61
62   RetrievalRecordBuf *buf = 
63     (RetrievalRecordBuf *) odr_malloc(stream, sizeof(*buf));  
64
65   res->errCode    = ro->records[i].errCode;
66   if (ro->records[i].errString) {
67     res->errString  = odr_strdup(stream, ro->records[i].errString);
68   } else {
69     res->errString = "";
70   }
71   res->position   = ro->records[i].position;
72   res->base       = ro->records[i].base;
73   res->format     = (char *) 
74     yaz_z3950_oid_value_to_str(ro->records[i].format, CLASS_RECSYN); 
75   res->buf        = buf;
76   res->buf->len   = ro->records[i].len;
77   res->buf->buf   = ro->records[i].buf;
78   res->score      = ro->records[i].score;
79   res->sysno      = ro->records[i].sysno;
80
81 }
82
83
84
85 /* most of the code here was copied from yaz-client */
86 void records_retrieve(ZebraHandle zh,
87                       ODR stream,
88                       const char *setname,
89                       const char *a_eset, 
90                       const char *a_schema,
91                       const char *a_format,
92                       int from,
93                       int to,
94                       RetrievalObj *res) 
95 {
96   static enum oid_value recordsyntax = VAL_SUTRS;
97   static enum oid_value schema = VAL_NONE;
98   static Z_ElementSetNames *elementSetNames = 0; 
99   static Z_RecordComposition compo;
100   static Z_ElementSetNames esn;
101   static char what[100];
102   int i;
103   int oid[OID_SIZE];
104
105   compo.which = -1;
106
107   if (from < 1) from = 1;
108   if (from > to) to = from;
109   res->noOfRecords = to - from + 1;
110
111   res->records = odr_malloc (stream, 
112                              sizeof(*res->records) * (res->noOfRecords));  
113
114   for (i = 0; i<res->noOfRecords; i++) res->records[i].position = from+i;
115
116   if (!a_eset || !*a_eset) {
117     elementSetNames = 0;
118   } else {
119     strcpy(what, a_eset);
120     esn.which = Z_ElementSetNames_generic;
121     esn.u.generic = what;
122     elementSetNames = &esn;
123   }
124
125   if (!a_schema || !*a_schema) {
126     schema = VAL_NONE;
127   } else {
128     schema = oid_getvalbyname (a_schema);
129     if (schema == VAL_NONE) {
130       logf(LOG_WARN,"unknown schema '%s'",a_schema);
131     }
132   }
133
134   
135   if (!a_format || !*a_format) {
136     recordsyntax = VAL_SUTRS;
137   } else {
138     recordsyntax = oid_getvalbyname (a_format);
139     if (recordsyntax == VAL_NONE) {
140       logf(LOG_WARN,"unknown record syntax '%s', using SUTRS",a_schema);
141       recordsyntax = VAL_SUTRS;
142     }
143   }
144
145   if (schema != VAL_NONE) {
146     oident prefschema;
147
148     prefschema.proto = PROTO_Z3950;
149     prefschema.oclass = CLASS_SCHEMA;
150     prefschema.value = schema;
151     
152     compo.which = Z_RecordComp_complex;
153     compo.u.complex = (Z_CompSpec *)
154       odr_malloc(stream, sizeof(*compo.u.complex));
155     compo.u.complex->selectAlternativeSyntax = (bool_t *) 
156       odr_malloc(stream, sizeof(bool_t));
157     *compo.u.complex->selectAlternativeSyntax = 0;
158     
159     compo.u.complex->generic = (Z_Specification *)
160       odr_malloc(stream, sizeof(*compo.u.complex->generic));
161     compo.u.complex->generic->which = Z_Schema_oid;
162     compo.u.complex->generic->schema.oid = (Odr_oid *)
163       odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
164     if (!compo.u.complex->generic->schema.oid)
165       {
166         /* OID wasn't a schema! Try record syntax instead. */
167         prefschema.oclass = CLASS_RECSYN;
168         compo.u.complex->generic->schema.oid = (Odr_oid *)
169           odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
170       }
171     if (!elementSetNames)
172       compo.u.complex->generic->elementSpec = 0;
173     else
174       {
175         compo.u.complex->generic->elementSpec = (Z_ElementSpec *)
176           odr_malloc(stream, sizeof(Z_ElementSpec));
177         compo.u.complex->generic->elementSpec->which =
178           Z_ElementSpec_elementSetName;
179         compo.u.complex->generic->elementSpec->u.elementSetName =
180           elementSetNames->u.generic;
181       }
182     compo.u.complex->num_dbSpecific = 0;
183     compo.u.complex->dbSpecific = 0;
184     compo.u.complex->num_recordSyntax = 0;
185     compo.u.complex->recordSyntax = 0;
186   } 
187   else if (elementSetNames) {
188     compo.which = Z_RecordComp_simple;
189     compo.u.simple = elementSetNames;
190   }
191
192   if (compo.which == -1) {
193     api_records_retrieve (zh, stream, setname, 
194                             NULL, 
195                             recordsyntax,
196                             res->noOfRecords, res->records);
197   } else {
198     api_records_retrieve (zh, stream, setname, 
199                             &compo,
200                             recordsyntax,
201                             res->noOfRecords, res->records);
202   }
203
204 }
205  
206 int zebra_cql2pqf (cql_transform_t ct, 
207                    const char *query, char *res, int len) {
208   
209   int status;
210   const char *addinfo = "";
211   CQL_parser cp = cql_parser_create();
212
213   if (status = cql_parser_string(cp, query)) {
214     cql_parser_destroy(cp);
215     return (status);
216   }
217
218   if (cql_transform_buf(ct, cql_parser_result(cp), res, len)) {
219     status = cql_transform_error(ct, &addinfo);
220     logf (LOG_WARN,"Transform error %d %s\n", status, addinfo ? addinfo : "");
221     cql_parser_destroy(cp);
222     return (status);
223   }
224
225   cql_parser_destroy(cp);
226   return (0);
227 }
228
229 void zebra_scan_PQF (ZebraHandle zh,
230                      ScanObj *so,
231                      ODR stream,
232                      const char *pqf_query)
233 {
234   Z_AttributesPlusTerm *zapt;
235   Odr_oid *attrsetid;
236   const char* oidname;
237   oid_value attributeset;
238   ZebraScanEntry *entries;
239   int i, class;
240
241   logf(LOG_DEBUG,  
242        "scan req: pos:%d, num:%d, partial:%d", 
243        so->position, so->num_entries, so->is_partial);
244
245   zapt = p_query_scan (stream, PROTO_Z3950, &attrsetid, pqf_query);
246
247   oidname = yaz_z3950oid_to_str (attrsetid, &class); 
248   logf (LOG_DEBUG, "Attributreset: %s", oidname);
249   attributeset = oid_getvalbyname(oidname);
250
251   if (!zapt) {
252     logf (LOG_WARN, "bad query %s\n", pqf_query);
253     odr_reset (stream);
254     return;
255   }
256
257   so->entries = (scanEntry *)
258     odr_malloc (stream, sizeof(so->entries) * (so->num_entries));
259
260
261   zebra_scan (zh, stream, zapt, attributeset, 
262               &so->position, &so->num_entries, 
263               (ZebraScanEntry **) &so->entries, &so->is_partial);
264
265   logf(LOG_DEBUG, 
266        "scan res: pos:%d, num:%d, partial:%d", 
267        so->position, so->num_entries, so->is_partial);
268 }
269
270 scanEntry *getScanEntry(ScanObj *so, int pos) {
271   return (&so->entries[pos-1]);
272 }
273