Changeset 32
- Timestamp:
- 11/21/04 00:13:21
- Files:
-
- trunk/storage/storeado.py (modified) (11 diffs)
- trunk/storage/test.mdb (modified) (previous)
- trunk/storage/test_storeado.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/storage/storeado.py
r31 r32 58 58 class AdapterFromADO(storage.Adapter): 59 59 """Coerce incoming values from ADO to Dejavu datatypes.""" 60 60 61 def __init__(self, unit=None): 61 62 self.unit = unit … … 290 291 291 292 293 # Stack sentinels 294 cannot_represent = object() 295 table_arg = object() 296 kw_arg = object() 297 292 298 class ADOSQLDecompiler(codewalk.LambdaDecompiler): 293 299 """ADOSQLDecompiler(store, unitClass, expr, adapter=AdapterToADOSQL()). … … 313 319 314 320 def __init__(self, store, unitClass, expr, adapter=AdapterToADOSQL()): 315 self.store = store 316 self.unitClass = unitClass 321 self.tablename = store.prefix + unitClass.__name__ 317 322 self.expr = expr 318 323 self.adapter = adapter … … 324 329 self.walk() 325 330 result = self.stack[0] 326 if result is None:331 if result is cannot_represent: 327 332 result = 'True' 328 333 return result, self.imperfect … … 333 338 while terms: 334 339 term, operation = terms.pop() 335 # All this checking of None is done so that a function336 # (like dejavu.iscurrentweek) can be labeled imperfect--337 # all Units (which match the rest of the Expression)338 # will be recalled. They can then be compared in339 # expr.evaluate(unit).340 if comp is None:341 if term is not None:340 # All this checking of cannot_represent is done so that a 341 # function (like dejavu.iscurrentweek) can be labeled 342 # imperfect--all Units (which match the rest of the 343 # Expression) will be recalled. They can then be 344 # compared in expr.evaluate(unit). 345 if term is not cannot_represent: 346 if comp is cannot_represent: 342 347 comp = term 343 else: 344 if term is not None: 348 else: 345 349 comp = "(%s) %s (%s)" % (term, operation, comp) 346 350 self.stack.append(comp) … … 353 357 354 358 def visit_LOAD_FAST(self, lo, hi): 355 pass 359 if lo + (hi << 8) < self.co_argcount: 360 self.stack.append(table_arg) 361 else: 362 self.stack.append(kw_arg) 356 363 357 364 def visit_LOAD_ATTR(self, lo, hi): 358 365 name = self.co_names[lo + (hi << 8)] 359 self.stack.append("[%s%s].[%s]" % 360 (self.store.prefix, self.unitClass.__name__, name)) 366 tos = self.stack.pop() 367 if tos is table_arg: 368 self.stack.append("[%s].[%s]" % (self.tablename, name)) 369 else: 370 self.stack.append((tos, name)) 361 371 362 372 def visit_LOAD_CONST(self, lo, hi): … … 377 387 self.stack.append("(" + terms + ")") 378 388 379 def visit_BUILD_LIST(self, lo, hi): 380 self.visit_BUILD_TUPLE(lo, hi) 389 visit_BUILD_LIST = visit_BUILD_TUPLE 381 390 382 391 def visit_CALL_FUNCTION(self, lo, hi): … … 403 412 self.stack.append(self.functions[func](*args)) 404 413 else: 405 if isinstance(func, basestring): 406 if func.endswith("[startswith]"): 407 self.stack[-1] = self.stack[-1] + " Like '" + args[0][1:-1] + "%'" 414 if isinstance(func, tuple): 415 tos, func = func 416 if func == "startswith": 417 self.stack.append(tos + " Like '" + args[0][1:-1] + "%'") 408 418 self.imperfect = True 409 419 return 410 elif func .endswith("[endswith]"):411 self.stack [-1] = self.stack[-1] + " Like '%" + args[0][1:-1] + "'"420 elif func == "endswith": 421 self.stack.append(tos + " Like '%" + args[0][1:-1] + "'") 412 422 self.imperfect = True 413 423 return 414 elif func == '<built-in function len>': 424 elif isinstance(func, basestring): 425 if func == '<built-in function len>': 415 426 self.stack.append("Len(" + args[0] + ")") 416 427 return 417 428 else: 418 429 if self.stack: 419 self.stack[-1] = None430 self.stack[-1] = cannot_represent 420 431 else: 421 self.stack = [ None]432 self.stack = [cannot_represent] 422 433 self.imperfect = True 423 434 … … 437 448 else: 438 449 if op2.startswith("'") and op2.endswith("'"): 439 # A ll ADO comparison operators for strings are case-insensitive440 # by default. Rather than determine column-by-column which450 # ADO comparison operators for strings are case-insensitive 451 # by default. Rather than determine which columns in the DB 441 452 # might be case-sensitive, just flag them all as imperfect. 442 453 self.imperfect = True … … 448 459 449 460 def visit_BINARY_SUBSCR(self): 450 """The only BINARY_SUBSCR used in Expressions should be kwargs[key]."""461 # The only BINARY_SUBSCR used in Expressions should be kwargs[key]. 451 462 name = self.stack.pop() 463 tos = self.stack.pop() 464 if tos is not kw_arg: 465 raise ValueError(tos, name) 452 466 # name, since formed in LOAD_CONST, has extraneous single-quotes. 453 value = self.expr.kwargs[name[1:-1]] 467 name = name[1:-1] 468 value = self.expr.kwargs[name] 454 469 value = self.adapter.coerce(value) 455 470 self.stack.append(value) … … 457 472 def visit_UNARY_NOT(self): 458 473 op = self.stack.pop() 459 if op is None:474 if op is cannot_represent: 460 475 # Usually as a result of has(farClassName). 461 self.stack.append( None)476 self.stack.append(cannot_represent) 462 477 else: 463 478 self.stack.append("not (" + op + ")") trunk/storage/test_storeado.py
r31 r32 66 66 sel(lambda x: dejavu.year(x.Event) == 2004, 67 67 u"SELECT * FROM [djvThings] WHERE Year([djvThings].[Event]) = 2004", False) 68 ##69 ## sel(lambda x: x.has('Animals'), u"SELECT * FROM [djvThings] WHERE True", True)70 ## # Paradoxically, "not has" should also return True, so71 ## # we can pass all Units to dejavu for final eval.72 ## sel(lambda x: not x.has('Animals'), u"SELECT * FROM [djvThings] WHERE True", True)73 68 74 69 def test_multiselect(self): … … 80 75 u"FROM [djvThings] LEFT JOIN [djvAnimals] ON [djvThings].[Size] " 81 76 u"= [djvAnimals].[Legs] WHERE [djvThings].[Group] = 3") 82 self.assertEqual(testSM.multiselect(Things, f, [(Animals, None)])[0], sql) 77 self.assertEqual(testSM.multiselect(Things, f, 78 [(Animals, None)])[0], sql) 83 79 84 80 def test_create_storage(self): … … 196 192 trial(lambda x: x.DateTo == None, u"[djvThings].[DateTo] Is Null", False) 197 193 198 # Multiple arguments 194 # Multiple arguments (? Why should this be supported?) 199 195 trial(lambda x, y, z: x.Date == 3 and y.Qty > 4 and z.Qty < 20, 200 196 "([djvThings].[Date] = 3) and (([djvThings].[Qty] > 4) and ([djvThings].[Qty] < 20))", False)
