Changeset 297
- Timestamp:
- 09/01/06 20:35:19
- Files:
-
- trunk/__init__.py (modified) (1 diff)
- trunk/storage/geniusql.py (modified) (1 diff)
- trunk/storage/storeado.py (modified) (2 diffs)
- trunk/storage/storepypgsql.py (modified) (1 diff)
- trunk/storage/storesqlite.py (modified) (8 diffs)
- trunk/test/test_storesqlite.py (modified) (1 diff)
- trunk/test/zoo_fixture.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/__init__.py
r296 r297 109 109 return None 110 110 111 def day(value): 112 """The day attribute of a date.""" 113 if isinstance(value, (_datetime.date, _datetime.datetime)): 114 return value.day 115 else: 116 return None 117 111 118 def now(): 112 119 """Late-bound datetime.datetime.now(). Taint this when early binding.""" trunk/storage/geniusql.py
r296 r297 797 797 return "MONTH(" + x + ")" 798 798 799 def dejavu_day(self, x): 800 return "DAY(" + x + ")" 801 799 802 def func__builtin___len(self, x): 800 803 return "LENGTH(" + x + ")" trunk/storage/storeado.py
r296 r297 294 294 def dejavu_today(self): 295 295 return "DATEADD(dd, DATEDIFF(dd,0,getdate()), 0)" 296 297 def dejavu_year(self, x): 298 return "DATEPART(year, " + x + ")" 299 300 def dejavu_month(self, x): 301 return "DATEPART(month, " + x + ")" 302 303 def dejavu_day(self, x): 304 return "DATEPART(day, " + x + ")" 296 305 297 306 def func__builtin___len(self, x): … … 813 822 def dejavu_year(self, x): 814 823 return "Year(" + x + ")" 815 824 825 def dejavu_month(self, x): 826 return "Month(" + x + ")" 827 828 def dejavu_day(self, x): 829 return "Day(" + x + ")" 816 830 817 831 class TypeAdapter_MSAccess(db.TypeAdapter): trunk/storage/storepypgsql.py
r296 r297 107 107 def dejavu_month(self, x): 108 108 return "date_part('month', " + x + ")" 109 109 110 def dejavu_day(self, x): 111 return "date_part('day', " + x + ")" 110 112 111 113 trunk/storage/storesqlite.py
r296 r297 1 import datetime 1 2 import os 2 3 import time … … 9 10 # This will import the "old API for SQLite 3.x", using e.g. pysqlite 1.1.7 10 11 import _sqlite 12 11 13 _version = storage.Version(_sqlite.sqlite_version()) 12 14 … … 22 24 _rename_table_support = (_version >= storage.Version([3, 1, 0])) 23 25 _autoincrement_support = (_version >= storage.Version([3, 1, 0])) 24 26 _cast_support = (_version >= storage.Version([3, 2, 3])) 25 27 26 28 class AdapterToSQLite(db.AdapterToSQL): … … 33 35 bool_true = "1" 34 36 bool_false = "0" 37 38 # If you are using type adapters that support a "standard" 39 # date/datetime format for SQLite, set the following flag to True 40 using_perfect_dates = False 35 41 36 42 def coerce_bool_to_any(self, value): … … 52 58 class SQLiteDecompiler(db.SQLDecompiler): 53 59 60 def visit_COMPARE_OP(self, lo, hi): 61 if self.adapter.using_perfect_dates: 62 op2, op1 = self.stack.pop(), self.stack.pop() 63 #@@NOTE: date/datetime comparision 64 # This code seems to work fine, but see the NOTE in visit_LOAD_ATTR 65 # for the problem... 66 67 # SQLite can do meaningful date/datetime comparisions with 68 # Julian dates. It has a function to convert a string date 69 # to a Julian date. We make use of it here. 70 if (isinstance(op1, db.ConstWrapper) and 71 isinstance(op1.basevalue, (datetime.date, datetime.datetime))): 72 op1 = "julianday(" + op1 + ")" 73 74 elif (isinstance(op2, db.ConstWrapper) and 75 isinstance(op2.basevalue, (datetime.date, datetime.datetime))): 76 op2 = "julianday(" + op2 + ")" 77 78 # Put the operands back on the stack so that the standard 79 # visit_COMPARE_OP can have its way with them. 80 self.stack.append(op1) 81 self.stack.append(op2) 82 83 db.SQLDecompiler.visit_COMPARE_OP(self, lo, hi) 84 85 def visit_LOAD_ATTR(self, lo, hi): 86 name = self.co_names[lo + (hi << 8)] 87 tos = self.stack.pop() 88 if isinstance(tos, tuple): 89 # The name in question refers to a DB column. 90 tablename, table = tos 91 col = table.columns[name] 92 if col.imperfect_type: 93 atom = db.cannot_represent 94 self.imperfect = True 95 # @@NOTE: date/datetime comparision 96 # I hit a wall here. With the lack of a definitive date/datetime 97 # coltype in SQLite, and with the Python type of a column being 98 # determined by a different adapter, I have no way of determining 99 # if I should wrap a [table].[column] reference in the julianday() 100 # function :-( I would like to do something like ... 101 # elif col.pytype in (datetime.date, datetime.datetime): 102 # atom = "julianday(%s.%s)" % (tablename, col.qname) 103 else: 104 atom = '%s.%s' % (tablename, col.qname) 105 else: 106 # 'tos.name' will reference an attribute of the tos object. 107 # Stick the tos and name in a tuple for later processing. 108 atom = (tos, name) 109 self.stack.append(atom) 110 54 111 def attr_startswith(self, tos, arg): 55 112 if _escape_support: … … 127 184 128 185 def dejavu_now(self): 129 self.imperfect = True 130 return db.cannot_represent 186 if self.adapter.using_perfect_dates and _cast_support: 187 return "julianday('now')" 188 else: 189 self.imperfect = True 190 return db.cannot_represent 131 191 132 192 dejavu_today = dejavu_now 133 193 134 194 def dejavu_year(self, x): 135 self.imperfect = True 136 return db.cannot_represent 137 195 if self.adapter.using_perfect_dates and _cast_support: 196 return "CAST(strftime('%Y', " + x + ") AS NUMERIC)" 197 else: 198 self.imperfect = True 199 return db.cannot_represent 200 138 201 def dejavu_month(self, x): 139 self.imperfect = True 140 return db.cannot_represent 141 202 if self.adapter.using_perfect_dates and _cast_support: 203 return "CAST(strftime('%m', " + x + ") AS NUMERIC)" 204 else: 205 self.imperfect = True 206 return db.cannot_represent 207 208 def dejavu_day(self, x): 209 if self.adapter.using_perfect_dates and _cast_support: 210 return "CAST(strftime('%d', " + x + ") AS NUMERIC)" 211 else: 212 self.imperfect = True 213 return db.cannot_represent 142 214 143 215 class TypeAdapterSQLite(db.TypeAdapter): … … 358 430 359 431 columnsetclass = SQLiteColumnSet 432 433 def isrelatedtype(self, pytype1, pytype2): 434 if (self.using_perfect_dates and 435 issubclass(pytype1, (datetime.date, datetime.time, datetime.datetime)) and 436 issubclass(pytype2, self.python_type(self.typeadapter.coerce(None, pytype1)))): 437 return True 438 return db.Database.isrelatedtype(self, pytype1, pytype2) 360 439 361 440 def _get_tables(self, conn=None): … … 557 636 allOptions['mode'] = int(allOptions.pop('Mode', '0755'), 8) 558 637 db.StorageManagerDB.__init__(self, arena, allOptions) 638 pd = str(allOptions.get('Perfect Dates', 'False')).lower() == "true" 639 self.databaseclass.using_perfect_dates = pd 640 self.databaseclass.adaptertosql.using_perfect_dates = pd 559 641 560 642 def version(self): trunk/test/test_storesqlite.py
r296 r297 19 19 20 20 print 21 print "Testing SQLite ':memory:' database..."22 opts[' Database'] = ':memory:'21 print "Testing SQLite with 'Perfect Dates'" 22 opts['Perfect Dates'] = True 23 23 reload(zoo_fixture) 24 24 zoo_fixture.init() 25 25 zoo_fixture.run(SM_class, opts) 26 opts['Perfect Dates'] = False 27 28 ## print 29 ## print "Testing SQLite ':memory:' database..." 30 ## opts['Database'] = ':memory:' 31 ## reload(zoo_fixture) 32 ## zoo_fixture.init() 33 ## zoo_fixture.run(SM_class, opts) 26 34 27 35 print trunk/test/zoo_fixture.py
r296 r297 421 421 self.assertEqual(matches(lambda x: 'i' in x.Species), 7) 422 422 423 # Test now(), today(), year(), month() 423 # Test now(), today(), year(), month(), day() 424 424 self.assertEqual(matches(lambda x: x.Founded != None 425 425 and x.Founded < dejavu.today(), Zoo), 3) … … 427 427 self.assertEqual(matches(lambda x: dejavu.year(x.LastEscape) == 2004), 1) 428 428 self.assertEqual(matches(lambda x: dejavu.month(x.LastEscape) == 12), 1) 429 self.assertEqual(matches(lambda x: dejavu.day(x.LastEscape) == 21), 1) 429 430 430 431
