SRW, CQL, 2003
[yaz-moved-to-github.git] / zutil / logrpn.c
1 /*
2  * Copyright (C) 1995-2001, Index Data
3  * All rights reserved.
4  *
5  * $Id: logrpn.c,v 1.9 2003-01-06 08:20:29 adam Exp $
6  */
7 #include <stdio.h>
8
9 #include <yaz/log.h>
10 #include <yaz/logrpn.h>
11
12 static const char *relToStr(int v)
13 {
14     const char *str = 0;
15     switch (v)
16     {
17     case 1: str = "Less than"; break;
18     case 2: str = "Less than or equal"; break;
19     case 3: str = "Equal"; break;
20     case 4: str = "Greater or equal"; break;
21     case 5: str = "Greater than"; break;
22     case 6: str = "Not equal"; break;
23     case 100: str = "Phonetic"; break;
24     case 101: str = "Stem"; break;
25     case 102: str = "Relevance"; break;
26     case 103: str = "AlwaysMatches"; break;
27     }
28     return str;
29 }
30 static void attrStr (int type, int value, enum oid_value ast, char *str)
31 {
32     const char *rstr;
33     *str = '\0';
34     switch (ast)
35     {
36     case VAL_BIB1:
37     case VAL_EXP1:
38     case VAL_GILS:
39         switch (type)
40         {
41         case 1:
42             sprintf (str, "use");
43             break;
44         case 2:
45             rstr = relToStr(value);
46             if (rstr)
47                 sprintf (str, "relation=%s", rstr);
48             else
49                 sprintf (str, "relation=%d", value);
50             break;
51         case 3:
52             switch (value)
53             {
54             case 1:
55                 sprintf (str, "position=First in field");
56                 break;
57             case 2:
58                 sprintf (str, "position=First in any subfield");
59                 break;
60             case 3:
61                 sprintf (str, "position=Any position in field");
62                 break;
63             default:
64                 sprintf (str, "position");
65             }
66             break;
67         case 4:
68             switch (value)
69             {
70             case 1:
71                 sprintf (str, "structure=Phrase");
72                 break;
73             case 2:
74                 sprintf (str, "structure=Word");
75                 break;
76             case 3:
77                 sprintf (str, "structure=Key");
78                 break;
79             case 4:
80                 sprintf (str, "structure=Year");
81                 break;
82             case 5:
83                 sprintf (str, "structure=Date");
84                 break;
85             case 6:
86                 sprintf (str, "structure=Word list");
87                 break;
88             case 100:
89                 sprintf (str, "structure=Date (un)");
90                 break;
91             case 101:
92                 sprintf (str, "structure=Name (norm)");
93                 break;
94             case 102:
95                 sprintf (str, "structure=Name (un)");
96                 break;
97             case 103:
98                 sprintf (str, "structure=Structure");
99                 break;
100             case 104:
101                 sprintf (str, "structure=urx");
102                 break;
103             case 105:
104                 sprintf (str, "structure=free-form-text");
105                 break;
106             case 106:
107                 sprintf (str, "structure=document-text");
108                 break;
109             case 107:
110                 sprintf (str, "structure=local-number");
111                 break;
112             case 108:
113                 sprintf (str, "structure=string");
114                 break;
115             case 109:
116                 sprintf (str, "structure=numeric string");
117                 break;
118             default:
119                 sprintf (str, "structure");
120             }
121             break;
122         case 5:
123             switch (value)
124             {
125             case 1:
126                 sprintf (str, "truncation=Right");
127                 break;
128             case 2:
129                 sprintf (str, "truncation=Left");
130                 break;
131             case 3:
132                 sprintf (str, "truncation=Left&right");
133                 break;
134             case 100:
135                 sprintf (str, "truncation=Do not truncate");
136                 break;
137             case 101:
138                 sprintf (str, "truncation=Process #");
139                 break;
140             case 102:
141                 sprintf (str, "truncation=re-1");
142                 break;
143             case 103:
144                 sprintf (str, "truncation=re-2");
145                 break;
146             default:
147                 sprintf (str, "truncation");
148             }
149             break;
150         case 6:
151             switch (value)
152             {
153             case 1:
154                 sprintf (str, "completeness=Incomplete subfield");
155                 break;
156             case 2:
157                 sprintf (str, "completeness=Complete subfield");
158                 break;
159             case 3:
160                 sprintf (str, "completeness=Complete field");
161                 break;
162             default:
163                 sprintf (str, "completeness");
164             }
165             break;
166         }
167         break;
168     default:
169         break;
170     }
171     if (*str)
172         sprintf (str + strlen(str), " (%d=%d)", type, value);
173     else
174         sprintf (str, "%d=%d", type, value);
175 }
176
177 /*
178  * zlog_attributes: print attributes of term
179  */
180 static void zlog_attributes (Z_AttributesPlusTerm *t, int level,
181                              enum oid_value ast)
182 {
183     int of, i;
184     char str[80];
185     int num_attributes = t->attributes->num_attributes;
186     
187     for (of = 0; of < num_attributes; of++)
188     {
189         const char *attset_name = "";
190         Z_AttributeElement *element;
191         element = t->attributes->attributes[of];
192         if (element->attributeSet)
193         {
194             oident *attrset;
195             attrset = oid_getentbyoid (element->attributeSet);
196             attset_name = attrset->desc;
197         }
198         switch (element->which) 
199         {
200         case Z_AttributeValue_numeric:
201             attrStr (*element->attributeType,
202                      *element->value.numeric, ast, str);
203             yaz_log (LOG_LOG, "%*.0s%s %s", level, "", attset_name, str);
204             break;
205         case Z_AttributeValue_complex:
206             yaz_log (LOG_LOG, "%*.0s%s attributeType=%d complex",
207                   level, "", attset_name, *element->attributeType);
208             for (i = 0; i<element->value.complex->num_list; i++)
209             {
210                 if (element->value.complex->list[i]->which ==
211                     Z_StringOrNumeric_string)
212                     yaz_log (LOG_LOG, "%*.0s  string: '%s'", level, "",
213                              element->value.complex->list[i]->u.string);
214                 else if (element->value.complex->list[i]->which ==
215                          Z_StringOrNumeric_numeric)
216                     yaz_log (LOG_LOG, "%*.0s  numeric: '%d'", level, "",
217                              *element->value.complex->list[i]->u.numeric);
218             }
219             break;
220         default:
221             yaz_log (LOG_LOG, "%.*s%s attribute unknown",
222                      level, "", attset_name);
223         }
224     }
225 }
226
227 static void zlog_structure (Z_RPNStructure *zs, int level, enum oid_value ast)
228 {
229     if (zs->which == Z_RPNStructure_complex)
230     {
231         Z_Operator *op = zs->u.complex->roperator;
232         const char *rstr = 0;
233         const char *unit = "private";
234         switch (op->which)
235         {
236         case Z_Operator_and:
237             yaz_log (LOG_LOG, "%*.0s and", level, "");
238             break;
239         case Z_Operator_or:
240             yaz_log (LOG_LOG, "%*.0s or", level, "");
241             break;
242         case Z_Operator_and_not:
243             yaz_log (LOG_LOG, "%*.0s and-not", level, "");
244             break;
245         case Z_Operator_prox:
246             if (op->u.prox->which == Z_ProximityOperator_known)
247             {
248                 switch(*op->u.prox->u.known)
249                 {
250                 case Z_ProxUnit_character: unit = "character"; break;
251                 case Z_ProxUnit_word: unit = "word"; break;
252                 case Z_ProxUnit_sentence: unit = "sentence"; break;
253                 case Z_ProxUnit_paragraph: unit = "paragraph"; break;
254                 case Z_ProxUnit_section: unit = "section"; break;
255                 case Z_ProxUnit_chapter: unit = "chapter"; break;
256                 case Z_ProxUnit_document: unit = "document"; break;
257                 case Z_ProxUnit_element: unit = "element"; break;
258                 case Z_ProxUnit_subelement: unit = "subelement"; break;
259                 case Z_ProxUnit_elementType: unit = "elementType"; break;
260                 case Z_ProxUnit_byte: unit = "byte"; break;
261                 default: unit = "unknown"; break;
262                 }
263             }
264             rstr = relToStr(*op->u.prox->relationType);
265             yaz_log (LOG_LOG, "%*.0s prox excl=%s dist=%d order=%s "
266                      "rel=%s unit=%s",
267                      level, "", op->u.prox->exclusion ?
268                      (*op->u.prox->exclusion ? "T" : "F") : "N", 
269                      *op->u.prox->distance,
270                      *op->u.prox->ordered ? "T" : "F",
271                      rstr ? rstr : "unknown",
272                      unit);
273             break;
274         default:
275             yaz_log (LOG_LOG, "%*.0s unknown complex", level, "");
276             return;
277         }
278         zlog_structure (zs->u.complex->s1, level+2, ast);
279         zlog_structure (zs->u.complex->s2, level+2, ast);
280     }
281     else if (zs->which == Z_RPNStructure_simple)
282     {
283         if (zs->u.simple->which == Z_Operand_APT)
284         {
285             Z_AttributesPlusTerm *zapt = zs->u.simple->u.attributesPlusTerm;
286
287             switch (zapt->term->which)
288             {
289             case Z_Term_general:
290                 yaz_log (LOG_LOG, "%*.0s term '%.*s' (general)", level, "",
291                          zapt->term->u.general->len,
292                          zapt->term->u.general->buf);
293                 break;
294             case Z_Term_characterString:
295                 yaz_log (LOG_LOG, "%*.0s term '%s' (string)", level, "",
296                          zapt->term->u.characterString);
297                 break;
298             case Z_Term_numeric:
299                 yaz_log (LOG_LOG, "%*.0s term '%d' (numeric)", level, "",
300                          *zapt->term->u.numeric);
301                 break;
302             case Z_Term_null:
303                 yaz_log (LOG_LOG, "%*.0s term (null)", level, "");
304                 break;
305             default:
306                 yaz_log (LOG_LOG, "%*.0s term (not general)", level, "");
307             }
308             zlog_attributes (zapt, level+2, ast);
309         }
310         else if (zs->u.simple->which == Z_Operand_resultSetId)
311         {
312             yaz_log (LOG_LOG, "%*.0s set '%s'", level, "",
313                      zs->u.simple->u.resultSetId);
314         }
315         else
316             yaz_log (LOG_LOG, "%*.0s unknown simple structure", level, "");
317     }
318     else
319         yaz_log (LOG_LOG, "%*.0s unknown structure", level, "");
320 }
321
322 void log_rpn_query (Z_RPNQuery *rpn)
323 {
324     oident *attrset;
325     enum oid_value ast;
326     
327     attrset = oid_getentbyoid (rpn->attributeSetId);
328     if (attrset)
329     {
330         ast = attrset->value;
331         yaz_log (LOG_LOG, "RPN query. Type: %s", attrset->desc);
332     } 
333     else
334     {
335         ast = VAL_NONE;
336         yaz_log (LOG_LOG, "RPN query. Unknown type");
337     }
338     zlog_structure (rpn->RPNStructure, 0, ast);
339 }
340
341 void log_scan_term (Z_AttributesPlusTerm *zapt, oid_value ast)
342 {
343     int level = 0;
344     if (zapt->term->which == Z_Term_general) 
345     {
346         yaz_log (LOG_LOG, "%*.0s term '%.*s' (general)", level, "",
347                  zapt->term->u.general->len, zapt->term->u.general->buf);
348     }
349     else
350         yaz_log (LOG_LOG, "%*.0s term (not general)", level, "");
351     zlog_attributes (zapt, level+2, ast);
352 }
353
354 void yaz_log_zquery (Z_Query *q)
355 {
356     static int cql_oid[] = {1, 2, 840, 10003, 16, 2, -1};
357     switch (q->which)
358     {
359     case Z_Query_type_1: case Z_Query_type_101:
360         log_rpn_query (q->u.type_1);
361         break;
362     case Z_Query_type_104:
363         if (q->u.type_104->which == Z_External_CQL)
364             yaz_log (LOG_LOG, "CQL: %s", q->u.type_104->u.cql);
365     }
366 }