1
2
3
4
5
6
7 from mdinterface import CommandException
8 from mdtable import EmptyTableException
9 import re
10
11
12
13 DEBUGS = False
14 DEBUG = False
15
17 - def __init__(self, query, tables, mainTable, loadTable):
18 self.reINT = re.compile("\d+")
19 self.reFLOAT = re.compile("\.\d+\.\d+")
20 self.reNAME = re.compile("[_a-zA-Z0-9.]+")
21 self.reTABLEREF = re.compile("[_a-zA-Z0-9/.]+:[_a-zA-Z0-9.]+")
22 self.reVARID = re.compile("[a-zA-Z][_a-zA-Z0-9]*")
23 self.reSTRING = re.compile('"[^"]*"')
24 self.q = query
25 self.tables=tables
26 if not len(mainTable):
27 mainTable = '/'
28 if mainTable[len(mainTable)-1] == '/':
29 mainTable = mainTable[0:len(mainTable)-1]
30 self.mainTable=mainTable
31 self.loadTable = loadTable
32 self.parseDict=[(None, None, None)]*(len(query)+1)
33
34
36 if DEBUG: print "parsing where clause: ", self.q
37 if len(self.q) == 0:
38 return True
39 self.__qp = 0
40 try:
41 token, v = self.__pStatement()
42 except EmptyTableException:
43 return False
44 if token == 'CONST':
45 return v > 0
46 if token == 'EXP':
47 return v > 0
48 raise CommandException(8, "Illegal " + self.q + ": not boolean")
49
50
59
60
62 if self.__qp+len(literal) <= len(self.q) \
63 and self.q[self.__qp:self.__qp+len(literal)] == literal \
64 and ( ( (len(self.q)> self.__qp+len(literal) )
65 and self.q[self.__qp+len(literal)].isspace() )
66 or len(self.q) == self.__qp+len(literal) ):
67 self.__qp = self.__qp + len(literal)
68 if DEBUGS: 'Found literal ', literal
69 self.parseDict[start] = literal, literal, self.__qp
70 return literal, literal
71 else:
72 return None, 0
73
74
76 if DEBUGS: print 'Reading token at ' + str(self.__qp)
77
78 t, v, next = self.parseDict[self.__qp]
79 if t:
80 if DEBUGS: print 'Returning ', [self.__qp], t, ' ', v
81 self.__qp = next
82 return t, v
83 start = self.__qp
84
85 while self.__qp < len(self.q):
86 if self.q[self.__qp].isspace():
87 self.__qp = self.__qp +1
88 else:
89 break
90
91 if DEBUGS: print 'Reading token 2 '
92
93 if self.__qp>= len(self.q):
94 if DEBUGS: print "Token " + str(self.__qp) + " END"
95 self.parseDict[start] = 'END', 0, self.__qp
96 return 'END', 0
97
98 t=self.reINT.match(self.q[self.__qp:])
99 if t!= None:
100 t=t.group()
101 self.__qp=self.__qp+len(t)
102 if DEBUGS: print "Token " + str(self.__qp) + " CONST " + t
103 self.parseDict[start] = 'CONST', int(t), self.__qp
104 return 'CONST', int(t)
105
106 t=self.reFLOAT.match(self.q[self.__qp:])
107 if t!= None:
108 t=t.group()
109 self.__qp=self.__qp+len(t)
110 if DEBUGS: print "Token " + str(self.__qp) + " CONST " + t
111 self.parseDict[start] = 'CONST', float(t), self.__qp
112 return 'CONST', float(t)
113
114 if DEBUGS: print 'Reading token 3 '
115
116 t, v = self.__isLiteral(start, 'and')
117 if t:
118 return t, v
119 t, v = self.__isLiteral(start, 'or')
120 if t:
121 return t, v
122 t, v = self.__isLiteral(start, 'FILE')
123 if t:
124 return t, v
125
126 if DEBUGS: print 'Reading token 4 '
127 t=self.reTABLEREF.match(self.q[self.__qp:])
128 if t != None:
129 t = t.group()
130 self.__qp=self.__qp+len(t)
131 if DEBUGS: print "Token ", self.__qp, " TABLREF ", t
132 self.parseDict[start] = 'TABLEREF', t, self.__qp
133 return 'TABLEREF', t
134
135 t=self.reNAME.match(self.q[self.__qp:])
136 if t != None:
137 t = t.group()
138 self.__qp=self.__qp+len(t)
139 if DEBUGS: print "Token ", self.__qp, " NAME ", t
140 self.parseDict[start] = 'NAME', t, self.__qp
141 return 'NAME', t
142
143 if DEBUGS: print 'Reading token 5 '
144
145
146 if self.__qp +1 < len(self.q):
147 t = self.q[self.__qp:self.__qp+1]
148 if "=<>*/+-".find(t) >=0:
149 if DEBUGS: print "Token " + str(self.__qp) + " " + t
150 self.__qp = self.__qp + 1
151 self.parseDict[start] = t, t, self.__qp
152 return t, t
153
154 if DEBUGS: print 'Reading token 6 '
155
156 if self.__qp +2 < len(self.q):
157 if self.q[self.__qp:self.__qp+2] == '>=':
158 if DEBUGS: print "Token " + str(self.__qp) + " >="
159 self.__qp = self.__qp + 2
160 self.parseDict[start] = '>=', 0, self.__qp
161 return ">=", 0
162 if self.q[self.__qp:self.__qp+2] == '<=':
163 if DEBUGS: print "Token " + str(self.__qp) + " <="
164 self.__qp = self.__qp + 2
165 self.parseDict[start] = '<=', 0, self.__qp
166 return "<=", 0
167 if self.q[self.__qp:self.__qp+2] == '!=':
168 if DEBUGS: print "Token " + str(self.__qp) + " !="
169 self.__qp = self.__qp + 2
170 self.parseDict[start] = '!=', 0, self.__qp
171 return "!=", 0
172 if self.q[self.__qp:self.__qp+2] == '<>':
173 self.__qp = self.__qp + 2
174 self.parseDict[start] = '<>', 0, self.__qp
175 return "<>", 0
176
177
178 t=self.reSTRING.match(self.q[self.__qp:])
179 if t!= None:
180 t=t.group()
181 self.__qp=self.__qp+len(t)
182 t = t[1:-1]
183 if DEBUGS: print "Token " + str(self.__qp) + " CONST " + t
184 self.parseDict[start] = 'CONST', str(t), self.__qp
185 return 'CONST', str(t)
186
187 return self.q[self.__qp], 0
188
189
197
198
200 token, v = self.__readToken()
201 if DEBUG: print 'Got ', token, " ", v
202 if token == 'CONST':
203 if DEBUG: print 'Token: CONST ', v
204 return 'CONST', v
205
206 return self.__evalVar(token, v)
207
208
210 if DEBUG: print 'Evaluating operation: ', exp1, op, exp2
211 if op == '=':
212 return 'CONST', exp1 == exp2
213 if op == '>':
214 return 'CONST', exp1 > exp2
215 if op == '<':
216 return 'CONST', exp1 < exp2
217 if op == '<=':
218 return 'CONST', exp1 <= exp2
219 if op == '>=':
220 return 'CONST', exp1 >= exp2
221 if op == '!=':
222 return 'CONST', exp1 != exp2
223 if op == '+':
224 return 'CONST', exp1 + exp2
225 if op == '-':
226 return 'CONST', exp1 - exp2
227 if op == '*':
228 return 'CONST', exp1 * exp2
229 if op == '/':
230 return 'CONST', exp1 / exp2
231 if op == 'or':
232 return 'CONST', exp1 or exp2
233 if op == 'and':
234 return 'CONST', exp1 and exp2
235 raise CommandException (8, 'Illegal query: unknown op' + op)
236
237
239 if DEBUG: print "Evaluating variable ", token, " : ", v
240
241 if token == 'NAME':
242 v = self.mainTable + ':' + v
243 token = 'TABLEREF'
244
245 if token == 'TABLEREF':
246 table, v = v.split(':', 1)
247
248 if DEBUG: print 'TABLE BEFORE ', table
249 if not self.tables.has_key(table):
250 mdtable, table = self.loadTable(table)
251 if DEBUG: print 'TABLE AFTER ', table
252 mdtable = self.tables[table]
253
254 if mdtable.currentRow <0:
255 return None, 0
256 row = mdtable.entries[mdtable.currentRow]
257 if DEBUG: print 'Evaluating ', table, v, row
258 if v == 'FILE':
259 return 'CONST', str(row[0])
260 if not mdtable.attributeDict.has_key(v):
261 raise CommandException (8, 'Illegal query, unknown ' + v)
262 if mdtable.typeDict[v] == 'int':
263 if row[mdtable.attributeDict[v]+1] == '':
264 return 'CONST', None
265 nv = int(row[mdtable.attributeDict[v]+1])
266 elif mdtable.typeDict[v] == 'float' or mdtable.typeDict[v] == 'double':
267 nv = float(row[mdtable.attributeDict[v]+1])
268 if DEBUG: print 'CONST ', row[mdtable.attributeDict[v]+1]
269 else:
270 nv = str(row[mdtable.attributeDict[v]+1])
271 return 'CONST', nv
272
273 if token == 'FILE':
274 return 'CONST', str(row[0])
275 return None, 0
276
277
279 if DEBUG: print "Expression: Trying x and/or y"
280 myi=self.__qp
281 if DEBUG: print 'Expression: was ' + str(self.__qp)
282 token, v = self.__pComparison()
283 if DEBUG: print 'Expression: now ' +str(self.__qp)
284 if token:
285 if DEBUG: print 'Comp ' + str(v)
286 myi2 = self.__qp
287 DEBUGS = True
288 op, opv = self.__readToken()
289 DEBUGS = False
290 if DEBUG: print 'Expression token: ' + str(op) + str(opv)
291 if op == 'and' or op == 'or':
292 ntoken, nv = self.__pExpression()
293 if not ntoken:
294 raise CommandException (8, 'Illegal query: expecting exp')
295 if DEBUG: print 'Expression: reducing a op b'
296 return self.__pEvaluateOp(op, v, nv)
297 self.__qp = myi2
298 self.__qp=myi
299
300 if DEBUG: print 'Expression: Trying comp' + str(self.__qp)
301 token, v = self.__pComparison()
302 if not token:
303 raise CommandException (8, 'Illegal query: expecting comp')
304 if DEBUG: print "Expression: Found comp " + str(v)
305 return token, v
306
307
309 if DEBUG: print "Comparison: Trying x =>< y"
310 myi=self.__qp
311 if DEBUG: print 'Comparison: was ' + str(self.__qp)
312 token, v = self.__pSum()
313 if DEBUG: print 'Comparison: now ' +str(self.__qp)
314 if token:
315 myi2 = self.__qp
316 op, opv = self.__readToken()
317 if DEBUG: print 'Comparison: got op ' + op + ' '
318 if op == '=' or op == '>' or op == '<' \
319 or op == '<=' or op == '>=' or op == '!=':
320 ntoken, nv = self.__pComparison()
321 if not ntoken:
322 raise CommandException (8, 'Illegal query: expecting comp')
323 if DEBUG: print 'Comparison: reducing a op b'
324 return self.__pEvaluateOp(op, v, nv)
325 self.__qp = myi2
326 self.__qp=myi
327
328 if DEBUG: print 'Comparison: Trying sum' + str(self.__qp)
329 token, v = self.__pSum()
330 if not token:
331 raise CommandException (8, 'Illegal query: expecting sum')
332 if DEBUG: print "Comparison: Found sum " + str(v)
333 return token, v
334
335
337 if DEBUG: print "Sum: Trying x +- y"
338 myi=self.__qp
339 if DEBUG: print 'Sum: was ' + str(self.__qp)
340 token, v = self.__pTerm()
341 if DEBUG: print 'Sum: now ' +str(self.__qp)
342 if token:
343 if DEBUG: print 'Sum ' + str(v)
344 myi2 = self.__qp
345 op, opv = self.__readToken()
346 if op == '+' or op == '-':
347 ntoken, nv = self.__pSum()
348 if not ntoken:
349 raise CommandException (8, 'Illegal query: expecting term')
350 return self.__pEvaluateOp(op, v, nv)
351 self.__qp = myi2
352 self.__qp=myi
353
354 if DEBUG: print 'Sum: Trying term' + str(self.__qp)
355 token, v = self.__pTerm()
356 if not token:
357 raise CommandException (8, 'Illegal query: expecting term')
358 if DEBUG: print "Sum: Found term " + str(v)
359 return token, v
360
361
363 if DEBUG: print "Term: Trying x */ y"
364 myi=self.__qp
365 if DEBUG: print 'Term: I was ' + str(self.__qp)
366 token, v = self.__pFactor()
367 if DEBUG: print 'Term: I now ' +str(self.__qp)
368 if token:
369 if DEBUG: print "Term: " +str(v)
370 myi2 = self.__qp
371 op, opv = self.__readToken()
372 if op == '*' or op == '/':
373 ntoken, nv = self.__pTerm()
374 if not ntoken:
375 raise CommandException (8, 'Illegal query: expecting fact')
376 return self.__pEvaluateOp(op, v, nv)
377 self.__qp = myi2
378 self.__qp=myi
379
380 if DEBUG: print 'Term: Trying faktor' + str(self.__qp)
381 token, v = self.__pFactor()
382 if not token:
383 raise CommandException (8, 'Illegal query: expecting factor')
384 if DEBUG: print "Term: Found factor " + str(v)
385 return token, v
386
387
389 if DEBUG: print "Factor: Trying ()"
390 myi=self.__qp
391 if DEBUG: print 'Factor: I was ' + str(self.__qp)
392 token, v = self.__readToken()
393 if DEBUG: print "Factor: now " + str(self.__qp)
394 if token == '(':
395 token, v = self.__pExpression()
396 ntoken, nv = self.__readToken()
397 if ntoken != ')':
398 raise CommandException (8, 'Illegal query: expecting )')
399 return token, v
400 self.__qp=myi
401
402
403 if DEBUG: print "Factor: Trying Token"
404 token, v = self.__pToken()
405
406 if not token:
407 raise EmptyTableException
408 if DEBUG: print "Factor: Found token " + str(v)
409 return token, v
410